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


69

我正在尝试找出何时使用爆炸!保存和更新记录的版本?我已经阅读并听说,如果您只是保存一个记录或更新单个属性,或者您确信没有问题的话,或者总是在控制器外部使用它们,则不需要它们。我想我对保存多件事情然后发生某些事情失败然后数据库中的数据不完整感到不安。我正在从事的当前Rails项目已完成50%以上,目前还没有任何爆炸。我在模型中调用了一些自定义方法,这些方法会更新或创建多个记录,并担心它们是否应该进行某种事务处理。

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


Answers:


57

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

def update
  @model = Model.find params[:id]
  if @model.update_attributes params[:model] #returns true of false
     # handle success
  else
     # handle failure
  end
end

当我想确定自己是否知道某些内容未通过验证且未保存时,在测试中经常使用爆炸式版本。我肯定浪费了时间,因为更改了模型验证而导致调试失败,如果使用bang版本,这将是显而易见的。

例如

it "should do something" do
   m = Model.create! :foo => 'bar' # will raise an error on validation failure             
   m.should do_something
end

就数据库中没有无效数据而言,您应该使用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还有更多要说的。


87

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

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

使用事务可能也值得研究-http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html


21
与选定的答案不同,非常适合指出两者之间的关键区别。
ifightcrime 2013年

感谢您指出使用交易,它们似乎经常被忽略。
ki4jnq 2014年

4
+1。也可能是值得注意的是,非爆炸方法将在交易默默地消失,所以一直使用save!update_attributes!等等。当你的代码被包装在一个事务中。
NM Pennypacker

@NickM我想该交易会自动回滚吗?无声的失败将使之得以延续吗?
Magne

2
@Magne Yep,如果未引发异常,则交易仍将完成
NM Pennypacker

6

什么 !(bang)表示update_attributessave是:

“失败时引发异常”,而不是“失败时返回假”

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.