表示虽然他们看起来很相似,你所提到的两个方法,find_or_initialize_by_X
和find_or_initialize
,有很大的不同。
find_or_initialize_by_
类型的方法是在ActiveRecord::Base
的子类上定义的发现者,即主动记录模型。如果没有匹配查询条件,它们将返回单个记录或新实例。
第二个find_or_initialze
方法被称为不在模型类(MyModel
)上,但是(如错误所暗示的)在ActiveRecord::Relation
上。这是因为当你打电话给where
时,你得到的结果是一个关系,而不是一个数组或单个记录。
虽然数组和关系看起来很相似,但Rails将避免将关系转换为数组,直到它没有其他选择,因为这样做意味着实际执行SQL并创建对象,这是性能沉重且只有在需要实际执行时才需要检查结果。
第二次打电话给find_or_initialize
的问题是ActiveRecord::Relation
没有find_or_initialize
方法;它有一个first_or_initialize
方法。 (与上述情况下结果集为空的事实无关。)first_or_initialize
获取关系中的第一个结果,或者如果结果为空,则初始化新模型。
所以简短的答案是你应该只是打电话:MyModel.where(field1: 'foo').first_or_initialize
。
正如在其他的答案中提到,还有其他办法然而,做同样的事情,而无需使用关系,例如:
MyMode.find_or_initialize_by(field1: "foo")
这是更接近find_or_initialize_by_X
您在Rails的3.2使用,实际上一切您应该使用find_by
而不是where(...).first
模式,因为性能原因:where(...).first
将导致SQL按主键排序,这将比find_by
生成的SELECT
慢。
这是自动升级工具的结果吗? –