2015-05-06 51 views
2

显然,我看到allthosequestions,其答案如下:“使用find_or_create_by/initialize_by(<cols>)”。如何在rails中正确插入或更新记录?

问题是:“只是我,还是那些答案有点'破'?”如果有人要求插入或更新,通常意味着记录应该是唯一的:没有两个记录匹配<cols>应该存在。在这些答案之后,最终会在数据库中获得重复的行,或者偶尔会有异常(如果唯一性是通过唯一索引实施的)。

为什么没有人提出这种方式?

begin 
    Counter.create(name: '...', value: 1) 
rescue ActiveRecord::RecordNotUnique 
    Counter.where(name: '...').update_all('value = value + 1') 
end 

那么这是哪一个呢?我应该去find_or_create_by/initialize_by?还是应该依靠db的独特索引?在附注中,我想不出任何人想要插入或更新有重复行的情况。

+0

这是一个修辞问题吗? –

+0

简单地使用良好的验证不是满足吗?请记住,rails背后的概念是惯例而非配置。如果没有必要这么做,为什么会使事情复杂化? –

+1

@DavidHoelzer因为验证受到竞争条件的限制,所以某些逻辑必须放在数据库中。 –

回答

-1

因为begin...rescue不应该用于那个。

begin...rescue用于发生错误情况。

这是Ruby Learning的示例。

def inverse(x) 
    raise ArgumentError, 'Argument is not numeric' unless x.is_a? Numeric 
    1.0/x 
end 

你重复记录的例子是不是一个真正的“错误”,因为每当重复数据提交它可能发生。

find_or_create_by优雅地处理这两种情况,没有“错误条件”的概念。

+1

但是,违反数据库*中的唯一约束是错误。仅仅因为在一个层次上出现错误并不意味着它在各个层面都必须是错误的。顺便说一句,'find_or_create_by'只是'find_by(...)||创建(...)'所以它仍然受到竞争条件的影响,[文档](http://api.rubyonrails.org/classes/ActiveRecord/Relation.html#method-i- find_or_create_by)甚至建议将其包装如果需要唯一性,则使用异常处理程序。 –

相关问题