在Michael Hartl's rails tutorial chapter 13.3.1中,我们创建了一个类似于Twitter的微博:
Micropost.create
我的问题是为什么使用Micropost.create
而不是Micropost.create!
?
如果出现问题,您似乎总是希望在活动记录中引发异常,以便您可以解决异常问题。
为什么要使用Micropost.create
?他解释说这两个都是这个表的选项:
但他并没有真正解释为什么你会选择其中一个。那么,你为什么选择一个呢?
答案 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
,但这并不常见,因为save
和update
更有可能被使用(在大多数情况下,您将使用{{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
恢复意味着您需要从引发的异常中解救,这是一个更复杂的过程。