2

我有一个 YAML 文件,它将一堆属性映射到一个类。我希望能够遍历我的 YAML 文件中的所有属性并将它们动态地设置在对象上。

我怎样才能做到这一点?

这是我到目前为止的要点:

YAML 内容:

my_obj:
    :username: 'myuser'
    :password: 'mypass'
    ...

红宝石:

settings = YAML::load_file SETTINGS_FILE
settings = settings['my_obj']

settings.each do |s|
  #psuedo-code
  #example: my_obj.username = settings[:username] if my_obj.has_property?(:username)
  #my_obj.[s] = settings[:s] if my_obj.has_property?(:s)
end

我不确定这样做是否一定是最佳实践,但是有很多属性,我认为这比直接手动设置每个属性更干净。

4

4 回答 4

2

根据您的实际需要,您可以使用 Ruby 的默认 YAML 转储和加载行为。当将任意对象转储到 YAML 时,Psych(Ruby 中的 Yaml 解析器/发射器)将查看对象的所有实例变量并用它们写出 Yaml 映射。例如:

class MyObj
  def initialize(name, password)
    @name = name
    @password = password
  end
end

my_obj = MyObj.new('myuser', 'mypass')

puts YAML.dump my_obj

将打印出:

--- !ruby/object:MyObj
name: myuser
password: mypass

然后,您可以将其加载回来,YAML.load您将获得MyObj与原始实例变量相同的实例。

您可以通过在您的类上实现encode_with或方法来覆盖或自定义此行为。init_with

于 2013-07-20T21:52:41.523 回答
1

您会看到这在 Ruby gems 和 Rails 中被大量使用。这是一个虚拟类:

require 'yaml'

class MyClass
  attr_accessor :username, :password
  def initialize(params)
    @username, @password = params.values_at(*[:username, :password])
  end
end

我们可以使用 YAML 加载数据load_file

data = YAML.load_file('test.yaml') # => {"my_obj"=>{:username=>"myuser", :password=>"mypass"}}

传递刚刚读取的结构,在这种情况下是一个散列,并且,奇怪的是,或者甚至是神奇的,是类初始化程序所采用的,它创建了一个类的实例:

my_class = MyClass.new(data['my_obj'])

我们可以从 YAML 文件的内容中看到实例变量已正确初始化:

my_class.username # => "myuser"
my_class.password # => "mypass"
于 2013-07-20T22:17:56.177 回答
1

根据您的示例yaml文件内容,您将获得以下内容Hash

require 'yaml'
str = <<-end
my_obj:
  :username: 'myuser'
  :password: 'mypass'
end
settings = YAML.load(str)  
# => {"my_obj"=>{:username=>"myuser", :password=>"mypass"}}
settings['my_obj'][:username] # => "myuser"
settings['my_obj'][:password] # => "mypass"
于 2013-07-20T19:59:56.157 回答
0

这似乎工作。它允许我my_obj从 YAML 设置哈希中动态设置属性。

settings.each do |key, value|
  my_obj.instance_variable_set("@#{key}", value) if my_obj.method_defined?("#{key}")
end

my_objattr_accessor :username, :password

上面的代码片段似乎让我可以使用 动态设置这些属性instance_variable_set,同时还确保my_obj具有我试图分配的属性method_defined?

于 2013-07-20T21:48:05.670 回答