DRY方式将哈希值分配给对象

时间:2010-09-08 16:19:53

标签: ruby hash

我正在寻找一种优雅的方法将存储在Hash中的值分配给预先存在的对象。 为了清楚起见,如果我有一个对象,说obj有两个属性,比如姓名和年龄,我想分配这个来自哈希值的值而不做类似的事情:

obj.name = hash[:name]
obj.age = hash[:age] 

感谢您的关注。 西蒙

6 个答案:

答案 0 :(得分:11)

最好的办法可能是简单地定义像update_attributes这样的方法,它接受一个哈希并在类的实例方法中进行。

扩展其他人所写的内容以及您似乎需要的内容我认为您最好的选择是:

hash.keys.each do |key|
  m = "#{key}="
  obj.send( m, hash[key] ) if obj.respond_to?( m )
end

这将解释:

  • 始终没有哈希中类的所有属性,
  • 哈希中的任意数量的键(不仅仅是:名称等)

答案 1 :(得分:3)

这是我多年来使用的一种非常易于使用的模式:

{
  first_name: "John",
  last_name: "Smith",
  ...
}.each {|k, v| send("#{k}=", v)}

答案 2 :(得分:2)

不知道优雅,但你可以这样做:

[:name, :age].each do |att|
  obj.send("#{att}=", hash[att])
end

答案 3 :(得分:2)

使用instance_variable_set是另一种选择。这是一个例子:

class Test; attr_accessor :name, :age; end

hash = {name: 'John', age: 52}

obj = Test.new
hash.each do |k,v|
  obj.instance_variable_set("@#{k}".to_sym, v) # :name is converted to :@name
end

p obj # => #<Test:0x007fd8cbb75b00 @name="John", @age=52> 

唯一的技巧是instance_variable_set需要一个以@开头的符号,因此:@name有效但:name不是。

答案 4 :(得分:1)

obj.methods.grep(/[^!=]=$/).each {|attr| obj.send(attr, hash[attr]) }

答案 5 :(得分:1)

You can directly call the assign_attributes method on the object.

obj.assign_attributes(hash)