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

时间:2022-01-08 01:19:52

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%以上,目前还不包含任何bangs。我在模型中调用了一些自定义方法,这些方法更新或创建多个记录,并担心它们是否应该在某种事务中。

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中的存储功能,最终使我的生活变得更轻松,压力也更小。谢谢你的时间。

2 个解决方案

#1


51  

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 validate method 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::Migration docs for how to set up unique indexes and other database constraints in your migrations.

对于在数据库中没有无效数据的问题,您应该使用ActiveRecord验证(例如validates_presence_of:user_id)来处理这个问题,或者在模型中定义您自己的验证方法。(http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html)如果您的数据无效,这应该可以防止发生save。如果你真的很偏执,你可以给你的数据库添加一些限制。请查看ActiveRecord: Migration docs以了解如何在迁移过程中设置惟一的索引和其他数据库约束。

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-checklist has more to say on this.

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

#2


67  

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

#1


51  

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 validate method 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::Migration docs for how to set up unique indexes and other database constraints in your migrations.

对于在数据库中没有无效数据的问题,您应该使用ActiveRecord验证(例如validates_presence_of:user_id)来处理这个问题,或者在模型中定义您自己的验证方法。(http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html)如果您的数据无效,这应该可以防止发生save。如果你真的很偏执,你可以给你的数据库添加一些限制。请查看ActiveRecord: Migration docs以了解如何在迁移过程中设置惟一的索引和其他数据库约束。

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-checklist has more to say on this.

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

#2


67  

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