如何从YAML文件动态设置对象属性?

时间:2013-07-20 19:42:57

标签: ruby yaml

我有一个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 个答案:

答案 0 :(得分: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_withinit_with方法来覆盖或自定义此行为。

答案 1 :(得分: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"

答案 2 :(得分: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&#39; 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"

答案 3 :(得分:0)

这似乎有效。它允许我从YAML设置哈希中动态设置my_obj上的属性。

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?分配的属性。