Ruby-on-rails 我什么时候使用保存!,创建!和更新属性!在 Rails 中?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1761076/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 21:58:40  来源:igfitidea点击:

When do I use save!, create! and update_attributes! in Rails?

ruby-on-railsactiverecordtransactions

提问by CalebHC

I'm trying to figure out when to use the bang! versions for saving and updating records? I've read and heard that you don't need them if you're just saving one record or updating a single attribute, if you're confident nothing should go wrong, or to always use them outside of a controller. I guess I'm paranoid about having multiple things getting saved then something fails then there is incomplete data in the DB. The current Rails project I'm working on is over 50% complete and currently doesn't contain any bangs. I have some custom methods I'm calling in models that update or create multiple records and worry if they should be in some sort of transaction.

我想知道什么时候用砰!用于保存和更新记录的版本?我读过并听说如果您只是保存一条记录或更新单个属性,如果您确信不会出错,或者始终在控制器之外使用它们,则不需要它们。我想我对保存多个东西然后出现故障然后数据库中的数据不完整感到偏执。我正在处理的当前 Rails 项目已完成 50% 以上,目前不包含任何刘海。我在更新或创建多个记录的模型中调用了一些自定义方法,并担心它们是否应该在某种事务中。

Sorry if this seems scattered but I'm just trying to figure how to use the saving capabilities in ActiveRecord correctly and make my life easier and little more stress free in the end. Thanks for your time.

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

采纳答案by samg

Generally you want to use the non-bang versions in your controllers. This allows logic like this:

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

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

I find myself using the bang versions a lot in tests when I want to make sure I know if something doesn't validate, and isn't saved. I've definitely wasted time debugging tests that were failing because of changed model validations, which would be obvious if I used the bang versions.

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

e.g.

例如

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

In terms of not having invalid data in the database, you should be handling this with ActiveRecord validations (e.g. validates_presence_of :user_id), or defining your own validatemethod in the model. (http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html) This should prevent saves from occurring if your data isn't valid. If you're really paranoid you can add some constraints to your database. Check the ActiveRecord::Migrationdocs for how to set up unique indexes and other database constraints in your migrations.

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

Also in my experience you want to avoid using any custom save or create method whenever possible. If you re-implement functionality included in ActiveRecord you end up paying a price down the road. http://matthewpaulmoore.com/post/5190436725/ruby-on-rails-code-quality-checklisthas more to say on this.

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

回答by Andy Gaskell

The main difference is how failed saves are handled. When updating an ActiveRecord class the !version will raise an exception if the record is invalid.

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

I recommend reading the docs here - http://api.rubyonrails.org/classes/ActiveRecord/Base.html

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

Using transactions might also be something worth looking into - http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html

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

回答by Tim Heilman

What ! (bang) means for update_attributesand saveis:

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

"Raise an exception upon failure" rather than "Return false upon failure"

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

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

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

What ! (bang) means for createis:

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

"Raise an exception upon failure" rather than "Return the resulting object upon failure" https://api.rubyonrails.org/classes/ActiveRecord/Persistence/ClassMethods.html#method-i-create-21

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