我有一个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
我不确定这样做是否是最佳做法,但是有很多属性,我认为这比直接手动设置每个属性更简洁。
答案 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_with
或init_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_obj
有attr_accessor :username, :password
等等。
上面的代码段似乎让我使用instance_variable_set
动态设置这些属性,同时还确保my_obj
具有我尝试使用method_defined?
分配的属性。