Ruby 对象质量分配
Ruby object mass assignment
有没有更好的方法来完成下面的代码?
user.name = "abc"
user.email = "abc@test.com"
user.mobile = "12312312"
像这样可以做到:
user.prepare do |u|
u.name = "abc"
u.email = "abc@test.com"
u.mobile = "12312312"
end
tap 让我们来做吧:
user.tap do |u|
u.name = "abc"
u.email = "abc@test.com"
u.mobile = "12312312"
end
当您的属性以散列形式出现时的替代选项:
attrs = {
name: "abc",
email: "abc@test.com",
mobile: "12312312"
}
attrs.each { |key, value| user.send("#{key}=", value) }
对于 ActiveRecord 对象,您可以使用 .assign_attributes
或更新
方法:
user.assign_attributes( name: "abc", email: "abc@test.com", mobile: "12312312")
# attributes= is a shorter alias for assign_attributes
user.attributes = { name: "abc", email: "abc@test.com", mobile: "12312312" }
# this will update the record in the database
user.update( name: "abc", email: "abc@test.com", mobile: "12312312" )
# or with a block
user.update( name: "abc", mobile: "12312312" ) do |u|
u.email = "#{u.name}@test.com"
end
.update
接受一个块,而 assign_attributes 不接受。如果您只是简单地分配文字值的散列值——例如用户在参数中传递的那些值,则无需使用块。
如果你有一个普通的旧 ruby 对象,你想用批量赋值来增加它的趣味性,你可以这样做:
class User
attr_accessor :name, :email, :mobile
def initialize(params = {}, &block)
self.mass_assign(params) if params
yield self if block_given?
end
def assign_attributes(params = {}, &block)
self.mass_assign(params) if params
yield self if block_given?
end
def attributes=(params)
assign_attributes(params)
end
private
def mass_assign(attrs)
attrs.each do |key, value|
self.public_send("#{key}=", value)
end
end
end
这会让你做:
u = User.new(name: "abc", email: "abc@test.com", mobile: "12312312")
u.attributes = { email: "abc@example.com", name: "joe" }
u.assign_attributes(name: 'bob') do |u|
u.email = "#{u.name}@example.com"
end
# etc.
您也可以执行以下操作:
user.instance_eval do
@name = "abc"
@email = "abc@test.com"
@mobile = "12312312"
end
您可以在给定 instance_eval
的块中访问 user
的实例变量
如果您希望调用访问器方法而不是直接操作实例变量,则可以使用以下代码。
user.instance_eval do
self.name = "xyz"
self.email = "abc@test.com"
self.mobile = "12312312"
end
或
user.instance_eval do |o|
o.name = "xyz"
o.email = "abc@test.com"
o.mobile = "12312312"
end
假设'user'是一个你控制的class,那么你可以定义一个方法来做你想做的事情。例如:
def set_all(hash)
@name, @email, @mobile = hash[:name], hash[:email], hash[:mobile]
end
然后在您的其余代码中:
user.set_all(name: "abc", email: "abc@test.com", mobile: "12312312")
如果 'user' 是一个实例,比方说,一个 ActiveRecord 模型,那么我对如何使它工作的细节有些犹豫。但原则仍然适用:通过将复杂性的责任转移给接收者来干燥代码。
有没有更好的方法来完成下面的代码?
user.name = "abc"
user.email = "abc@test.com"
user.mobile = "12312312"
像这样可以做到:
user.prepare do |u|
u.name = "abc"
u.email = "abc@test.com"
u.mobile = "12312312"
end
tap 让我们来做吧:
user.tap do |u|
u.name = "abc"
u.email = "abc@test.com"
u.mobile = "12312312"
end
当您的属性以散列形式出现时的替代选项:
attrs = {
name: "abc",
email: "abc@test.com",
mobile: "12312312"
}
attrs.each { |key, value| user.send("#{key}=", value) }
对于 ActiveRecord 对象,您可以使用 .assign_attributes
或更新
方法:
user.assign_attributes( name: "abc", email: "abc@test.com", mobile: "12312312")
# attributes= is a shorter alias for assign_attributes
user.attributes = { name: "abc", email: "abc@test.com", mobile: "12312312" }
# this will update the record in the database
user.update( name: "abc", email: "abc@test.com", mobile: "12312312" )
# or with a block
user.update( name: "abc", mobile: "12312312" ) do |u|
u.email = "#{u.name}@test.com"
end
.update
接受一个块,而 assign_attributes 不接受。如果您只是简单地分配文字值的散列值——例如用户在参数中传递的那些值,则无需使用块。
如果你有一个普通的旧 ruby 对象,你想用批量赋值来增加它的趣味性,你可以这样做:
class User
attr_accessor :name, :email, :mobile
def initialize(params = {}, &block)
self.mass_assign(params) if params
yield self if block_given?
end
def assign_attributes(params = {}, &block)
self.mass_assign(params) if params
yield self if block_given?
end
def attributes=(params)
assign_attributes(params)
end
private
def mass_assign(attrs)
attrs.each do |key, value|
self.public_send("#{key}=", value)
end
end
end
这会让你做:
u = User.new(name: "abc", email: "abc@test.com", mobile: "12312312")
u.attributes = { email: "abc@example.com", name: "joe" }
u.assign_attributes(name: 'bob') do |u|
u.email = "#{u.name}@example.com"
end
# etc.
您也可以执行以下操作:
user.instance_eval do
@name = "abc"
@email = "abc@test.com"
@mobile = "12312312"
end
您可以在给定 instance_eval
user
的实例变量
如果您希望调用访问器方法而不是直接操作实例变量,则可以使用以下代码。
user.instance_eval do
self.name = "xyz"
self.email = "abc@test.com"
self.mobile = "12312312"
end
或
user.instance_eval do |o|
o.name = "xyz"
o.email = "abc@test.com"
o.mobile = "12312312"
end
假设'user'是一个你控制的class,那么你可以定义一个方法来做你想做的事情。例如:
def set_all(hash)
@name, @email, @mobile = hash[:name], hash[:email], hash[:mobile]
end
然后在您的其余代码中:
user.set_all(name: "abc", email: "abc@test.com", mobile: "12312312")
如果 'user' 是一个实例,比方说,一个 ActiveRecord 模型,那么我对如何使它工作的细节有些犹豫。但原则仍然适用:通过将复杂性的责任转移给接收者来干燥代码。