Hartl教程第13.1.3章User / Micropost关联:为什么使用create而不是create来引发异常?

时间:2017-05-04 14:36:23

标签: ruby-on-rails activerecord railstutorial.org

Michael Hartl's rails tutorial chapter 13.3.1中,我们创建了一个类似于Twitter的微博:

Micropost.create

我的问题是为什么使用Micropost.create而不是Micropost.create!

如果出现问题,您似乎总是希望在活动记录中引发异常,以便您可以解决异常问题。

为什么要使用Micropost.create?他解释说这两个都是这个表的选项: enter image description here

但他并没有真正解释为什么你会选择其中一个。那么,你为什么选择一个呢?

2 个答案:

答案 0 :(得分:2)

嗯,这取决于您使用该方法的位置。

何时使用create

如果它是控制器中的简单创建,通常您将使用create来控制流逻辑,请举例:

if Micropost.create(micropost_params)
  # handle success save, e.g.:
  redirect_to :index
else
  # handle failure in save, e.g.:
  render :new
end

使用上面的代码,你控制流没有使用异常,这就是你在创建记录时所需要的:处理你知道可能会出现的错误没有提出异常就会发生。

所以,我更喜欢用相反的方式来问:为什么要使用create!并引发异常(并获得相关的开销),如果你能得到一个false并处理错误?如果我需要更多代码来处理该异常,为什么呢?

虽然这是有效使用create,但这并不常见,因为saveupdate更有可能被使用(在大多数情况下,您将使用{{1}创建然后使用new保存。

何时使用save

如果您想要在同一操作中更新多个记录(阅读transactions),那么create!将为您提供更好的服务;请考虑以下示例:

create!

在此更新2条记录并在同一事务中创建1,但如果其中一条记录失败,则需要进行回滚以保持数据完整性不变。因此,如果您使用ActiveRecord::Base.transaction do user1.update!(balance: user1.balance + 100) user2.update!(balance: user2.balance - 100) transfer.create!(amount: 100, receiver: user1, sender: user2) end ,则需要自己处理回滚以撤消事务;另一方面,使用create会引发一个自动触发回滚的异常。

create!的另一个好用途是测试(如在Hartl的教程中)和调试,我发现它们更方便,因为它们可以更快地捕获错误

答案 1 :(得分:1)

如果case1: values1 with date1 = '2002-02-01' values2 with date2 = '2004-02-01' case2: values1 with date1 ='2001-01-01' values2 with date2 ='2001-01-01' 失败,你就不会完全陷入困境。

max(date1, date2)

它为您提供了一种处理故障情况的简单机制。例如,您可以参考create来确定问题所在并进行相应处理。

然而,在不向最终用户公开异常的情况下从my_micropost = Micropost.create if my_micropost.persisted? puts "successfully saved" else puts "something went wrong" end 恢复意味着您需要从引发的异常中解救,这是一个更复杂的过程。