我啥时候使用保存!,创建!和更新属性!在 Rails 中?

Posted

技术标签:

【中文标题】我啥时候使用保存!,创建!和更新属性!在 Rails 中?【英文标题】:When do I use save!, create! and update_attributes! in Rails?我什么时候使用保存!,创建!和更新属性!在 Rails 中? 【发布时间】:2010-12-18 04:18:15 【问题描述】:

我正试图弄清楚何时使用爆炸!保存和更新记录的版本?我已经阅读并听说,如果您只是保存一条记录或更新单个属性,如果您确信不会出错,或者始终在控制器之外使用它们,则不需要它们。我想我对保存多件事情然后有些事情失败然后数据库中的数据不完整感到偏执。我正在处理的当前 Rails 项目已完成 50% 以上,目前不包含任何刘海。我在模型中调用了一些自定义方法来更新或创建多个记录,并担心它们是否应该在某种事务中。

对不起,如果这看起来很分散,但我只是想弄清楚如何正确使用 ActiveRecord 中的保存功能,最终让我的生活更轻松,更轻松。感谢您的宝贵时间。

【问题讨论】:

Why are exclamation marks used in Ruby methods?的可能重复 【参考方案1】:

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

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

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

【讨论】:

非常适合指出两者之间的关键区别,与所选答案不同。 感谢您指出事务的使用,它们似乎经常被忽视。 +1。可能还值得注意的是,非爆炸方法将在事务中静默失败,因此当您的代码包装在事务中时,请始终使用save!update_attributes! 等。 @NickM 这样事务会自动回滚,我猜?虽然无声的失败会让它通过? @Magne 是的,如果没有引发异常,事务仍然会完成【参考方案2】:

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

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 版本,以确保我知道某些内容是否未验证且未保存。我肯定浪费了时间调试由于更改模型验证而失败的测试,如果我使用 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 对此有更多话要说。

【讨论】:

【参考方案3】:

什么! (bang) 表示update_attributessave 是:

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

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

【讨论】:

以上是关于我啥时候使用保存!,创建!和更新属性!在 Rails 中?的主要内容,如果未能解决你的问题,请参考以下文章

我啥时候应该销毁令牌[关闭]

我啥时候可以开始使用使用 UIAppearance 设置的属性?

我啥时候应该在 NavLink 上使用 Link?

我啥时候使用中心和自动保证金? CSS

我啥时候应该使用“隐藏文本框”,啥时候应该使用(html 5)“数据属性”?

我啥时候需要在 Heroku 中使用工作进程