如何在 Ruby 中一次为一个对象分配多个属性

max*_*max 2 ruby methods ruby-on-rails object

我有一个对象Foo,想要一次为其分配多个属性,类似于assign_attributesRails:

class Foo
    attr_accessor :a, :b, :c
end

f = Foo.new
my_hash = {a: "foo", b: "bar", c: "baz"}
f.assign_attributes(my_hash)
Run Code Online (Sandbox Code Playgroud)

除非该类是 Rails 中的 ActiveRecord 模型,否则上述方法不起作用。有什么方法可以在 Ruby 中做到这一点吗?

Ste*_*fan 7

您可以自己实现批量分配方法。

一种选择是通过以下方式设置相应的实例变量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
Run Code Online (Sandbox Code Playgroud)

请注意,这将绕过任何自定义设置器。正如文档中所说:

这可能会绕过类的作者意图的封装,因此应谨慎使用。

另一种方法是通过以下方式动态调用设置器public_send

  def assign_attributes(attrs)
    attrs.each_pair do |attr, value|
      public_send("#{attr}=", value)
    end
  end
Run Code Online (Sandbox Code Playgroud)

这相当于按顺序设置每个单个属性。如果已(重新)定义设置器以包括对所设置的值的约束和控制,则后一种方法会尊重这一点。

如果您尝试设置未定义的属性,它也会引发异常:(因为相应的设置器不存在)

f = Foo.new
f.assign_attributes(d: 'qux')
#=> NoMehodError: undefined method `d=' for #<Foo:0x00007fbb76038430>
Run Code Online (Sandbox Code Playgroud)

此外,您可能希望确保传递的参数确实是哈希,并且如果提供的属性无效/未知,则可能会引发自定义异常。