Ruby中如何为对象一次性批量赋值多个属性
原生Ruby实现assign_attributes功能的方案
原生Ruby没有提供全局的assign_attributes方法,但可以通过以下几种方式快速实现相同效果:
- 方式1:在自定义类中手动实现对应方法
class Foo attr_accessor :a, :b, :c def assign_attributes(attrs) attrs.each do |key, value| # 仅赋值类已定义的可写属性,避免非法属性报错 if respond_to?("#{key}=") public_send("#{key}=", value) end end end end
调用示例:
f = Foo.new my_hash = {a: "foo", b: "bar", c: "baz"} f.assign_attributes(my_hash) # 验证结果:f.a => "foo",f.b => "bar",f.c => "baz"
- 方式2:封装为通用模块实现多类复用
如果多个类都需要该功能,可以把逻辑封装为独立模块,需要用到的类引入即可:
module AttributeAssignable def assign_attributes(attrs) attrs.each do |key, value| public_send("#{key}=", value) if respond_to?("#{key}=") end end end # 任意类引入后即可使用assign_attributes方法 class Foo include AttributeAssignable attr_accessor :a, :b, :c end class Bar include AttributeAssignable attr_accessor :x, :y, :z end
- 方式3:使用Ruby原生Struct(Ruby 2.5+支持)
如果你的类是简单数据容器类,没有复杂自定义逻辑,可以直接用Ruby内置的Struct,开启keyword_init参数后原生自带assign_attributes方法:
# 定义Struct类,开启关键字参数初始化 Foo = Struct.new(:a, :b, :c, keyword_init: true) # 初始化时直接传hash赋值 f = Foo.new(a: "foo", b: "bar", c: "baz") # 后续也可以调用原生assign_attributes批量赋值 f.assign_attributes(a: "new_foo", c: "new_baz")
- 方式4:临时一次性赋值写法
如果只是偶尔需要批量赋值,不想额外定义方法,可以直接遍历hash完成赋值:
f = Foo.new my_hash = {a: "foo", b: "bar", c: "baz"} my_hash.each { |k, v| f.public_send("#{k}=", v) if f.respond_to?("#{k}=") }
注意:所有实现中的
respond_to?判断都是为了过滤类不存在的属性,避免传入非法key抛出异常;如果可以确保入参hash的key都是类已定义的可写属性,可以省略该判断提升执行效率。
内容的提问来源于stack exchange,提问作者max
相关产品推荐
相关产品推荐

