Rails update_attributes没有保存?

tyb*_*103 370 ruby ruby-on-rails ruby-on-rails-3 ruby-on-rails-4 rails-activerecord

是否有一个替代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
Run Code Online (Sandbox Code Playgroud)

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

Aje*_*i32 582

我相信你在寻找的是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
Run Code Online (Sandbox Code Playgroud)

  • assign_attributes可从Rails 3.1开始提供,因此如果您仍在运行旧版本的Rails,则无法使用它. (7认同)

Yar*_*rin 166

你可以使用assign_attributesattributes=(它们是相同的)

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

  • update= assign_attributes+save
  • attributes= =别名 assign_attributes
  • update_attributes =别名 update

资料来源:
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 并为另一个模型接受了 但是assign_attributes 不会那样做。 (3认同)

bru*_*077 63

您可以使用'attributes'方法:

@car.attributes = {:model => 'Sierra', :years => '1990', :looks => 'Sexy'}
Run Code Online (Sandbox Code Playgroud)

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

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

如果guard_protected_attributes为true(默认值),则可以使用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
Run Code Online (Sandbox Code Playgroud)


Mic*_*ill 7

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

两种方法都遵循以下用法:

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

@user.attributes = { model: "Sierra", year: "2012", looks: "Sexy" }
Run Code Online (Sandbox Code Playgroud)

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

Rails 3

attributes=assign_attributesRails 3 略有不同. attributes=将检查传递给它的参数是否为Hash,如果不是则立即返回; assign_attributes没有这样的哈希检查.请参阅ActiveRecord属性分配API文档attributes=.

只需在不设置属性的情况下返回,以下无效代码将无声地失败:

@user.attributes = [ { model: "Sierra" }, { year: "2012" }, { looks: "Sexy" } ]
Run Code Online (Sandbox Code Playgroud)

attributes= 将默默地表现得好像作业成功,但实际上,他们不是.

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

@user.assign_attributes([ { model: "Sierra" }, { year: "2012" }, { looks: "Sexy" } ])
Run Code Online (Sandbox Code Playgroud)

assign_attributes将引发NoMethodError异常stringify_keys,表明第一个参数不是Hash.异常本身并不能提供有关实际原因的信息,但异常确实发生的事实非常重要.

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

这些示例可能看似人为,并且它们在一定程度上,但是在从API转换数据时,甚至只是使用一系列数据转换并忘记Hash[]最终结果时,很容易发生这种类型的错误.map.保留一些代码50行以上,并从属性赋值中删除3个函数,并且您有失败的配方.

Rails 3的教训是:始终使用assign_attributes而不是attributes=.

Rails 4

在Rails 4中,attributes=只是一个别名assign_attributes.请参阅ActiveRecord属性分配API文档attributes=.

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

验证

如果您正在准备a的预先飞行任务save,您可能也有兴趣在保存之前进行验证.您可以使用valid?invalid?方法.两者都返回布尔值. valid?如果未保存的模型通过所有验证,则返回true;否则返回false. invalid?简直就是反过来了valid?

valid? 可以像这样使用:

@user.assign_attributes{ model: "Sierra", year: "2012", looks: "Sexy" }.valid?
Run Code Online (Sandbox Code Playgroud)

这将使您能够在呼叫之前处理任何验证问题save.