在Rails中,何时使用save!、create!和update_attributes!?

75

我正在尝试弄清何时使用bang!(感叹号)版本来保存和更新记录?我已经阅读和听说,如果你只是保存一个记录或更新一个单一属性,如果你有信心不会出现问题,或者在控制器之外总是使用它们,那么你不需要它们。我想我对多个事物被保存然后出现故障,导致数据库中存在不完整数据这种情况有些过于担心了。我正在处理的当前Rails项目已完成超过50%,目前没有使用任何bangs。我有一些自定义方法在模型中调用,用于更新或创建多个记录,并担心它们是否应该在某种事务中。

抱歉,如果这看起来有些零散,但我只是试图弄清楚如何正确地使用ActiveRecord中的保存功能,并使我的生活更轻松,最终减少压力。感谢您的时间。


可能是为什么Ruby方法中使用感叹号标记?的重复问题。 - jww
3个回答

91

21
与所选答案不同,这很好地指出了两者之间的关键差异。 - ifightcrime
感谢您指出事务的使用,它们经常被忽视。 - ki4jnq
4
值得注意的是,非感叹号方法在事务中会悄悄失败,因此当您的代码被包裹在事务中时,始终使用save!update_attributes!等方法。 - NM Pennypacker
@NickM 所以这样事务就会自动回滚,我猜测?而静默失败会让它继续执行下去? - Magne
2
@Magne 如果没有引发异常,事务仍将完成。 - NM Pennypacker
update! 在其 源代码 中被包装在一个事务中。 - SMAG

58

通常在控制器中使用非感叹号版本。这样可以实现以下逻辑:

def update
  @model = Model.find params[:id]
  if @model.update_attributes params[:model] #returns true of false
     # handle success
  else
     # handle failure
  end
end
我在测试中经常使用感叹号版本,这样可以确保我知道某些内容没有验证并保存。 如果我使用感叹号版本,那么因为更改了模型验证而导致测试失败的情况将变得非常明显,我肯定会节省时间来调试它们。
例如:
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中包含的功能,那么将来会付出代价。 http://matthewpaulmoore.com/post/5190436725/ruby-on-rails-code-quality-checklist 对此有更多讲解。


9

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接