Ruby对象质量分配

Ruby对象质量分配,ruby,accessor,Ruby,Accessor,有没有更好的方法来执行下面的代码 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 让我们就这样做: user.tap do |u| u.name = "abc" u.email = "abc@te

有没有更好的方法来执行下面的代码

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
让我们就这样做:

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对象,您可以使用或更新 方法:

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\u属性不接受块。如果您只是简单地分配一个文本值的散列,比如用户在参数中传递的值,那么就不需要使用块

如果您有一个普通的旧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\u eval


如果希望调用访问器方法而不是直接操作实例变量,可以使用下面的代码

user.instance_eval do
    self.name = "xyz"
    self.email = "abc@test.com"
    self.mobile = "12312312"
end


假设“user”是您控制的类,那么您可以定义一个方法来执行您想要的操作。例如:

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")

如果“用户”是ActiveRecord模型的一个实例,那么我对如何使其工作的细节有点不确定。但原则仍然适用:将复杂度的责任转移到接收者身上,使代码干涸。

如果
user
ActiveRecord
则可能是一个选项。为什么您更喜欢第二个示例而不是第一个示例?这对
user.send(键)不起作用
将调用getter,而不是setter方法。您需要执行
user.send(“#{key}=”)
。感谢您的帮助!不过我不建议这样做,因为
instance\u eval
违反了封装规则。最好按建议使用
。点击
发送
。@max
send
也会破坏封装;-)Ruby的封装只适用于行为良好的程序员。你说得对<代码>公共_发送
执行。你可能希望
.send
能做到。
user.set_all(name: "abc", email: "abc@test.com", mobile: "12312312")