ChatGPT解决这个技术问题 Extra ChatGPT

Rails update_attributes 没有保存?

是否有不保存记录的 update_attributes 替代方法?

所以我可以做类似的事情:

@car = Car.new(:make => 'GMC')
#other processing
@car.update_attributes(:model => 'Sierra', :year => "2012", :looks => "Super Sexy, wanna make love to it")
#other processing
@car.save

顺便说一句,我知道我可以@car.model = 'Sierra',但我想在一行上更新它们。

你是什么意思“不保存记录”?
update_attributes 将模型保存在数据库中。我想知道是否有类似的方法没有。
属性无损方法。有关详细信息,请参阅 API
您可以使用 update_column(name, value) 更新对象的单个属性,而无需调用 save。 1. 跳过验证。 2. 回调被跳过。 3. 如果该列可用,updated_at/updated_on 列不会更新。 apidock.com/rails/ActiveRecord/Persistence/update_column
对于 3.1+,使用 assign_attributes apidock.com/rails/ActiveRecord/Base/assign_attributes

A
Arel

我相信您正在寻找的是 assign_attributes

它与 update_attributes 基本相同,但不保存记录:

class User < ActiveRecord::Base
  attr_accessible :name
  attr_accessible :name, :is_admin, :as => :admin
end

user = User.new
user.assign_attributes({ :name => 'Josh', :is_admin => true }) # Raises an ActiveModel::MassAssignmentSecurity::Error
user.assign_attributes({ :name => 'Bob'})
user.name        # => "Bob"
user.is_admin?   # => false
user.new_record? # => true

您的示例有点误导,因为您没有从模型中粘贴这一行:attr_accessible :is_admin, :as => :admin ;)
@Robin 或者简单地说:attr_protected :is_admin。或者:attr_accessible :name 在这个例子中,:is_admin 是受保护的。我还应该注意,尝试使用 .assign_attributes 批量分配受保护的属性确实会引发 ActiveModel::MassAssignmentSecurity::Error,即使示例中没有显示。
是的,但我的台词来自您链接到的文档。我只是说您应该复制/粘贴整个示例。但是,是的,您可以说它受到保护。
@Robin 我将更新示例以使其更加具体。文档中的示例也有点误导,因为它没有提到 user.assign_attributes({ :name => 'Josh', :is_admin => true }) 引发错误消息并且实际上没有设置用户的 name 属性。
assign_attributes 从 Rails 3.1 开始可用,因此如果您仍在运行旧版本的 Rails,则无法使用它。
s
slhck

您可以使用 assign_attributesattributes=(它们相同)

更新方法备忘单(适用于 Rails 6):

更新 = 分配属性 + 保存

attributes= = assign_attributes 的别名

update_attributes = 已弃用,更新的别名

来源:
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/persistence.rb
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/attribute_assignment.rb

另一个备忘单:
http://www.davidverhasselt.com/set-attributes-in-activerecord/#cheat-sheet


清晰而简短。谢谢。
在.attributes = val 的情况下,如果您的模型has_one 和accepts_nested_attributes_for 另一个模型,传递that_model_attributes(没有id)将删除现有的has_one 模型,即使您没有坚持(例如保存)。但是assign_attributes 的行为并非如此。
b
bbonamin

您可以使用“属性”方法:

@car.attributes = {:model => 'Sierra', :years => '1990', :looks => 'Sexy'}

来源:http://api.rubyonrails.org/classes/ActiveRecord/Base.html

attributes=(new_attributes, guard_protected_attributes = true) 允许您通过传入带有与属性名称匹配的键的哈希(再次与列名称匹配)来一次设置所有属性。

如果guard_protected_attributes 为真(默认值),则可以使用attr_protected 宏保护敏感属性免受这种形式的批量分配。或者,您也可以使用 attr_accessible 宏指定可以访问哪些属性。那么所有未包含在其中的属性将不允许批量分配。

class User < ActiveRecord::Base
  attr_protected :is_admin
end

user = User.new
user.attributes = { :username => 'Phusion', :is_admin => true }
user.username   # => "Phusion"
user.is_admin?  # => false

user.send(:attributes=, { :username => 'Phusion', :is_admin => true }, false)
user.is_admin?  # => true

M
Michael Gaskill

要在不保存的情况下将值批量分配给 ActiveRecord 模型,请使用 assign_attributesattributes= 方法。这些方法在 Rails 3 和更新版本中可用。但是,需要注意一些细微的差异和与版本相关的问题。

两种方法都遵循这种用法:

@user.assign_attributes{ model: "Sierra", year: "2012", looks: "Sexy" }

@user.attributes = { model: "Sierra", year: "2012", looks: "Sexy" }

请注意,这两种方法都不会执行验证或执行回调;调用 save 时将发生回调和验证。

导轨 3

attributes= 与 Rails 3 中的 assign_attributes 略有不同。attributes= 将检查传递给它的参数是否为 Hash,如果不是则立即返回; assign_attributes 没有这样的哈希检查。请参阅 ActiveRecord Attribute Assignment API documentation for attributes=

以下无效代码将通过简单地返回而不设置属性而静默失败:

@user.attributes = [ { model: "Sierra" }, { year: "2012" }, { looks: "Sexy" } ]

attributes= 会默默地表现得好像分配成功了,但实际上并非如此。

assign_attributes 尝试对封闭数组的哈希键进行字符串化时,此无效代码将引发异常:

@user.assign_attributes([ { model: "Sierra" }, { year: "2012" }, { looks: "Sexy" } ])

assign_attributes 将为 stringify_keys 引发 NoMethodError 异常,指示第一个参数不是哈希。异常本身并不能很好地说明实际原因,但确实发生异常这一事实非常重要。

这些情况之间的唯一区别是用于批量分配的方法:attributes= 静默成功,assign_attributes 引发异常以通知已发生错误。

这些示例可能看起来是做作的,但在一定程度上它们是做作的,但是在从 API 转换数据时很容易发生这种类型的错误,甚至只是使用一系列数据转换而忘记了 Hash[] 最终 {2 }。保留上面 50 行的一些代码,并从属性分配中删除 3 个函数,你就有了失败的秘诀。

Rails 3 的教训是:总是使用 assign_attributes 而不是 attributes=

导轨 4

在 Rails 4 中,attributes= 只是 assign_attributes 的别名。请参阅 ActiveRecord Attribute Assignment API documentation for attributes=

在 Rails 4 中,任何一种方法都可以互换使用。未能将 Hash 作为第一个参数传递将导致一个非常有用的异常:ArgumentError: When assigning attributes, you must pass a hash as an argument.

验证

如果您正在为 save 做准备工作前的任务,您可能也有兴趣在保存前进行验证。为此,您可以使用 valid?invalid? 方法。两者都返回布尔值。如果未保存的模型通过所有验证,valid? 返回 true,否则返回 false。 invalid? 只是 valid? 的倒数

valid? 可以这样使用:

@user.assign_attributes{ model: "Sierra", year: "2012", looks: "Sexy" }.valid?

这将使您能够在调用 save 之前处理任何验证问题。