使用ActiveRecord 3 / Arel查找单个记录的最佳方法是什么?

40

我以前是这么做的:

Foo.find_by_bar('a-value')

我现在可以这样做:

Foo.where(:bar => 'a-value').limit(1).first
这是否被推荐?这是否是最好的方法?我是否应该继续使用“旧”方法,因为它仍然是有用的语法糖,还是现在有更好的方式可以支持链接和其他好东西?

这是否被推荐?这是否是最好的方法?我是否应该继续使用“旧”方法,因为它仍然是有用的语法糖,还是现在有更好的方式可以支持链接和其他好东西?


2
我其实很喜欢旧的 find_by_*。它的意图很明确,如果你只需要这个,语法更简单。 - Matthew Rudy
1
如果在Rails 3中使用仍然是完全有效的。如果使用Rails 4,则可以使用find_by(bar: 'a-value') - sevenseacat
我来这里只是为了寻找一个单独的记录。如果还有其他人也在寻找同样的记录,我已经在这里提供了一个答案:(链接):) - SRack
5个回答

51
Rails 4:最初的回答
Foo.find_by( bar: 'a_value', wibble: 'a wibble value' )

你能为这个添加一个来源吗? - l8nite
1
你有没有想过为什么RubyMine会警告说这个方法不应该从视图助手中调用? - Vlad
find_by 是一种重型操作,建议不要在渲染视图时触发。 - SureshCS

26

我认为返回单个记录的最佳方法类似于你的第二个例子,但可以省略限制部分:

Foo.where(:bar => 'a-value').first

这个遵循了新的语法,如果你想要在查找中添加更多条件,它也支持链接。


4
如果您想确保找到一条记录,请使用Foo.where(:bar => 'a-value').first!。否则将引发ActiveRecord::RecordNotFound异常。 - iltempo
Rails在这种情况下会添加ORDER BY "foo"."id" ASC。这可能会使查询变得不太高效。 - undefined

6
如果您只需要一条记录(我来到这里就是为了找这样的内容),Rails 7.0引入find_sole_by (或者where(...).sole)用于此类情况。
其行为如下所示:
查找匹配的唯一记录。如果没有找到记录,则引发ActiveRecord::RecordNotFound异常。如果找到多个记录,则引发ActiveRecord::SoleRecordExceeded异常。
使用案例很简单:
Foo.find_sole_by(bar: 'a-value')

在只需要单个记录的情况下非常方便。


5
Rails为这种情况提供了很多神奇的方法:
Foo.find_by_bar('a-value')

您也可以使用多个属性:
Foo.find_by_bar_and_wibble('a foo value', 'a wibble value')

追加一个 ! 使它在未找到记录时引发 RecordNotFound 异常:

Foo.find_by_bar!('a-value')

11
Rails 4.0(http://edgeguides.rubyonrails.org/4_0_release_notes.html#active-record-deprecations)起已经废弃了这些动态查找器,所以现在学习这个可能不是一个好习惯。 - Wes Oldenbeuving

2

其他的替代方案:

Foo.find(:first, conditions: { bar: 'a-value' })

您还可以使用多个属性:

Foo.find(:first, conditions: { bar: 'a-value' , wibble: 'a wibble value' })

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