我什么时候使用save !,创建!和update_attributes!在Rails?

Cal*_*bHC 60 activerecord transactions ruby-on-rails

我想知道什么时候使用爆炸!用于保存和更新记录的版本?我已阅读并听说你不需要他们,如果你只是一个保存记录或更新一个属性,如果你确信没有什么应该出问题,或总是使用他们的控制之外.我想我很擅长有多个东西被保存然后出现问题然后数据库中的数据不完整.我正在开发的当前Rails项目已完成50%以上,目前不包含任何刘海.我有一些自定义方法,我在更新或创建多个记录的模型中调用,并担心它们是否应该在某种交易中.

很抱歉,如果这看起来很分散,但我只是想弄清楚如何正确使用ActiveRecord中的保存功能,让我的生活更轻松,最后一点也没有压力.谢谢你的时间.

And*_*ell 77

主要区别在于如何处理失败的保存.更新ActiveRecord类时,!如果记录无效,则版本将引发异常.

我建议在这里阅读文档 - http://api.rubyonrails.org/classes/ActiveRecord/Base.html

使用事务也可能是一个值得探讨- http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html

  • 非常适合指出两者之间的关键差异,与选定的答案不同. (19认同)
  • +1.也许值得注意的是,非爆炸方法会在事务中无声地失败,所以当代码被包装在事务中时,总是使用`save!`,`update_attributes!`等. (3认同)
  • @Magne Yep,如果未引发异常,交易仍将完成 (2认同)

sam*_*amg 51

通常,您希望在控制器中使用非爆炸版本.这允许这样的逻辑:

def update
  @model = Model.find params[:id]
  if @model.update_attributes params[:model] #returns true of false
     # handle success
  else
     # handle failure
  end
end
Run Code Online (Sandbox Code Playgroud)

我发现自己在测试中经常使用爆炸版本,当我想确定我知道某些东西是否无法验证,并且没有保存.我肯定浪费时间调试由于模型验证改变而失败的测试,如果我使用爆炸版本,这将是显而易见的.

例如

it "should do something" do
   m = Model.create! :foo => 'bar' # will raise an error on validation failure             
   m.should do_something
end
Run Code Online (Sandbox Code Playgroud)

就数据库中没有无效数据而言,您应该使用ActiveRecord验证(例如validates_presence_of :user_id)处理此问题,或者validate在模型中定义您自己的方法.(http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html)如果您的数据无效,这应该可以防止发生保存.如果你真的是偏执狂,你可以为数据库添加一些约束.检查ActiveRecord::Migration文档,了解如何在迁移中设置唯一索引和其他数据库约束.

另外根据我的经验,您希望尽可能避免使用任何自定义保存或创建方法.如果您重新实现ActiveRecord中包含的功能,您最终将付出代价. http://matthewpaulmoore.com/post/5190436725/ruby-on-rails-code-quality-checklist对此有更多的话要说.


Tim*_*man 7

什么 !(bang) 表示update_attributes并且save是:

“失败时引发异常”而不是“失败时返回错误”

https://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-update-21 https://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-save

什么 !(bang) 的意思create是:

“在失败时引发异常”而不是“在失败时返回结果对象” https://api.rubyonrails.org/classes/ActiveRecord/Persistence/ClassMethods.html#method-i-create-21