提问人:max 提问时间:11/25/2021 最后编辑:max 更新时间:11/25/2021 访问量:914
如何在 Ruby 中一次为一个对象分配多个属性
How to assign multiple attributes at once to an object in Ruby
问:
我有一个对象,想一次给它分配多个属性,类似于在 Rails 中:Foo
assign_attributes
class Foo
attr_accessor :a, :b, :c
end
f = Foo.new
my_hash = {a: "foo", b: "bar", c: "baz"}
f.assign_attributes(my_hash)
除非该类是 Rails 中的 ActiveRecord 模型,否则上述方法不起作用。有什么方法可以在 Ruby 中做到这一点吗?
答:
7赞
Stefan
11/25/2021
#1
您可以自己实现质量分配方法。
一种选择是通过以下instance_variable_set
设置相应的实例变量:
class Foo
attr_accessor :a, :b, :c
def assign_attributes(attrs)
attrs.each_pair do |attr, value|
instance_variable_set("@#{attr}", value)
end
end
end
请注意,这将绕过任何自定义 setter。如文档中所述:
这可能会规避类作者想要的封装,因此应谨慎使用。
另一种方法是通过public_send
动态调用 setter:
def assign_attributes(attrs)
attrs.each_pair do |attr, value|
public_send("#{attr}=", value)
end
end
这相当于按顺序设置每个属性。如果已(重新)定义 setter 以包含对所设置值的约束和控制,则后一种方法会尊重这一点。
如果您尝试设置未定义的属性,它还会引发异常:(因为相应的 setter 不存在)
f = Foo.new
f.assign_attributes(d: 'qux')
#=> NoMehodError: undefined method `d=' for #<Foo:0x00007fbb76038430>
此外,您可能希望确保传递的参数确实是哈希值,如果提供的属性无效/未知,则可能会引发自定义异常。
评论
1赞
engineersmnky
11/25/2021
我认为后者是一个更好的实现,因为实例变量赋值选项缺乏例如attr_accessor
f.assign_attributes(('a'..'zzz').then {|a| a.zip(a)}.to_h)
0赞
Matheus Moreira
11/25/2021
哈希值可以通过使用 和 的约定来确保。to_h
to_hash
1赞
Stefan
11/25/2021
@MatheusMoreira可能取决于您的用例,但我宁愿使用 or .is_a?(Hash)
respond_to?(:each_pair)
0赞
Nitin Srivastava
11/25/2021
#2
是assign_attributes
ActiveRecord
如果不使用assign_attributes
ActiveRecord
def assign_attributes(attrs_hash)
attrs_hash.each do |k, v|
self.instance_variable_set("@#{k}", v)
end
end
下一个:从模块参数动态创建方法
评论