find vs find_by vs where

时间:2012-06-22 17:58:10

标签: ruby-on-rails rails-activerecord dynamic-finders

我是铁杆新手。我看到有很多方法可以找到记录:

  1. find_by_<columnname>(<columnvalue>)
  2. find(:first, :conditions => { <columnname> => <columnvalue> }
  3. where(<columnname> => <columnvalue>).first
  4. 看起来所有这些都会产生完全相同的SQL。此外,我相信找到多个记录也是如此:

    1. find_all_by_<columnname>(<columnvalue>)
    2. find(:all, :conditions => { <columnname> => <columnvalue> }
    3. where(<columnname> => <columnvalue>)
    4. 是否有经验法则或建议使用哪一个?

12 个答案:

答案 0 :(得分:113)

其中返回ActiveRecord :: Relation

现在看一下find_by的实现:

def find_by
  where(*args).take
end

正如您所看到的, find_by 其中相同,但它只返回一条记录。此方法应该用于获取1条记录,其中应该用于获取具有某些条件的所有记录。

答案 1 :(得分:79)

使用您认为最适合自己需要的任何一种。

find方法通常用于按ID检索行:

Model.find(1)

值得注意的是,如果您提供的属性找不到该项,find将抛出异常。使用where(如下所述,如果找不到该属性,将返回一个空数组)以避免抛出异常。

find的其他用法通常会替换为以下内容:

Model.all
Model.first
当您在列中搜索信息时,

find_by用作帮助程序,并使用命名约定映射到此类。例如,如果数据库中有一个名为name的列,则使用以下语法:

Model.find_by(name: "Bob")

.where更像是一个捕获所有允许你使用更复杂的逻辑的传统助手不会做的事情,它返回一个符合你条件的项目数组(否则为空数组) )。

答案 2 :(得分:31)

findfind_by之间存在差异,find如果找不到则会返回错误,而find_by将返回null。

如果您使用find_by email: "haha"方法,而不是.where(email: some_params).first,则有时会更容易阅读。

答案 3 :(得分:29)

<强> Model.find

1-参数:要查找的对象的ID。

2-如果找到:它返回对象(仅一个对象)。

3-如果未找到:引发ActiveRecord::RecordNotFound例外。

<强> Model.find_by

1-参数:键/值

示例:

User.find_by name: 'John', email: 'john@doe.com'

2-如果找到:它返回对象。

3-如果未找到:返回nil

注意: 如果您希望它引发ActiveRecord::RecordNotFound使用find_by!

<强> Model.where

1-参数:与find_by

相同

2-如果找到:它返回ActiveRecord::Relation,其中包含一个或多个与参数匹配的记录。

3-如果未找到:它返回空ActiveRecord::Relation

答案 4 :(得分:16)

从Rails 4开始,你可以这样做:

User.find_by(name: 'Bob')

这是Rails 3中的等效find_by_name

#where#find不够时使用#find_by

答案 5 :(得分:9)

接受的答案通常涵盖了所有内容,但我想补充一些内容, 只是因为你计划以更新的方式使用模型,而你正在检索单个记录(你不知道的id),那么find_by是要走的路,因为它检索记录并不将其放在数组中

irb(main):037:0> @kit = Kit.find_by(number: "3456")
  Kit Load (0.9ms)  SELECT "kits".* FROM "kits" WHERE "kits"."number" = 
 '3456' LIMIT 1
=> #<Kit id: 1, number: "3456", created_at: "2015-05-12 06:10:56",   
updated_at: "2015-05-12 06:10:56", job_id: nil>

irb(main):038:0> @kit.update(job_id: 2)
(0.2ms)  BEGIN Kit Exists (0.4ms)  SELECT 1 AS one FROM "kits" WHERE  
("kits"."number" = '3456' AND "kits"."id" != 1) LIMIT 1 SQL (0.5ms)   
UPDATE "kits" SET "job_id" = $1, "updated_at" = $2 WHERE  "kits"."id" = 
1  [["job_id", 2], ["updated_at", Tue, 12 May 2015 07:16:58 UTC +00:00]] 
(0.6ms)  COMMIT => true

但如果您使用where,则无法直接更新

irb(main):039:0> @kit = Kit.where(number: "3456")
Kit Load (1.2ms)  SELECT "kits".* FROM "kits" WHERE "kits"."number" =  
'3456' => #<ActiveRecord::Relation [#<Kit id: 1, number: "3456", 
created_at: "2015-05-12 06:10:56", updated_at: "2015-05-12 07:16:58", 
job_id: 2>]>

irb(main):040:0> @kit.update(job_id: 3)
ArgumentError: wrong number of arguments (1 for 2)

在这种情况下你必须像这样指定它

irb(main):043:0> @kit[0].update(job_id: 3)
(0.2ms)  BEGIN Kit Exists (0.6ms)  SELECT 1 AS one FROM "kits" WHERE 
("kits"."number" = '3456' AND "kits"."id" != 1) LIMIT 1 SQL (0.6ms)   
UPDATE "kits" SET "job_id" = $1, "updated_at" = $2 WHERE "kits"."id" = 1  
[["job_id", 3], ["updated_at", Tue, 12 May 2015 07:28:04 UTC +00:00]]
(0.5ms)  COMMIT => true

答案 6 :(得分:6)

您的列表中的两个#2都已被弃用。您仍然可以使用find(params[:id])

通常,where()适用于大多数情况。

这是一篇很棒的帖子:http://m.onkey.org/active-record-query-interface

答案 7 :(得分:5)

除了已接受的答案,以下内容也有效

Model.find()可以接受id数组,并返回匹配的所有记录。 Model.find_by_id(123)也接受数组,但只会处理数组

中存在的第一个id值
Model.find([1,2,3])
Model.find_by_id([1,2,3])

答案 8 :(得分:2)

假设我有一个模型用户

  1. User.find(id)
  2. 返回id指向的行。所以假设,如果id = 1,那么它将返回第一行。返回类型将是User对象。

    1. User.find_by(email:"abc@xyz.com")
    2. 在这种情况下,返回具有匹配属性或电子邮件的第一行。返回类型将再次为User对象。

      1. User.where(project_id:1)
      2. 返回属性匹配的users表中的所有用户。这里的返回类型将是包含User对象列表的ActiveRecord :: Relation对象。

答案 9 :(得分:1)

到目前为止给出的答案都还可以。

但是,一个有趣的区别是Model.find通过id搜索;如果找到,它将返回一个Model对象(仅一条记录),否则将抛出一个ActiveRecord::RecordNotFound

Model.find_byModel.find非常相似,可让您搜索数据库中的任何列或一组列,但是如果没有记录与搜索匹配,它将返回nil

另一方面,

Model.where返回一个Model::ActiveRecord_Relation对象,该对象就像一个包含与搜索匹配的所有记录的数组。如果未找到任何记录,它将返回一个空的Model::ActiveRecord_Relation对象。

希望这些可以帮助您决定在任何时间使用哪个。

答案 10 :(得分:0)

使用任何开源技术的最好的部分是您可以检查它的长度和宽度。 Checkout this link

find_by〜>查找符合指定条件的第一条记录。没有隐含的订购,因此,如果订购很重要,则应自己指定。如果未找到任何记录,则返回nil。

查找〜>查找符合指定条件的第一条记录,但是如果未找到任何记录,则将引发异常,但这是有意进行的。

请检查以上链接,其中包含以下两个功能的所有说明和用例。

答案 11 :(得分:-3)

我个人建议使用

where(< columnname> => < columnvalue>)