我是新来的轨道。我看到有很多方法可以找到记录:
find_by_
看起来它们最终都生成了完全相同的 SQL。另外,我相信查找多条记录也是如此:
find_all_by_
是否有关于使用哪一个的经验法则或建议?
其中返回 ActiveRecord::Relation
现在看一下 find_by 的实现:
def find_by
where(*args).take
end
如您所见, find_by 与 where 相同,但它只返回一条记录。此方法应用于获取 1 条记录,以及应使用 where 获取具有某些条件的所有记录。
编辑:这个答案已经很老了,自从发表这篇文章以来,已经出现了其他更好的答案。我建议查看@Hossam Khamis 在下面发布的更多详细信息。
使用您认为最适合您需要的任何一种。
find
方法通常用于按 ID 检索行:
Model.find(1)
值得注意的是,如果您提供的属性未找到该项目,find
将引发异常。使用 where
(如下所述,如果未找到该属性,它将返回一个空数组)以避免引发异常。
find
的其他用途通常替换为以下内容:
Model.all
Model.first
当您在列中搜索信息时,find_by
用作帮助器,它通过命名约定映射到此类。例如,如果您的数据库中有一个名为 name
的列,您将使用以下语法:
Model.find_by(name: "Bob")
.where
更像是一个包罗万象的方法,它可以让您使用更复杂的逻辑来处理传统助手无法执行的操作,并且它会返回一个符合您的条件的项目数组(否则返回一个空数组)。
find_by
没有被弃用,但语法发生了一些变化。从 find_by_name("Bob")
到 find_by(:name, "Bob")
。
find_by(name: "Bob")
find_by_...
被弃用的证据,你有消息来源吗? Rails 4 似乎仍然支持 find_by
和 find_by_...
。
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- 如果没有找到:它返回一个 Empty ActiveRecord::Relation
。
find
和 find_by
之间的区别在于,如果未找到 find
将返回错误,而 find_by
将返回 null。
有时,如果您有像 find_by email: "haha"
这样的方法,而不是 .where(email: some_params).first
,则更容易阅读。
从 Rails 4 开始,您可以执行以下操作:
User.find_by(name: 'Bob')
这与 Rails 3 中的 find_by_name
等效。
当 #find
和 #find_by
不够时使用 #where
。
find_by
而不是 find_by_<column_name>
。我需要它来回答某人。
find_by_name
?据我所知,it's not been deprecated。
find_by(name: "Rob*")
接受的答案通常涵盖了所有内容,但我想添加一些内容,以防您计划以更新等方式使用模型,并且您正在检索单个记录(您不知道其 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
到目前为止给出的答案都是可以的。
但是,一个有趣的区别是 Model.find
按 id 搜索;如果找到,它返回一个 Model
对象(只是一条记录),否则抛出一个 ActiveRecord::RecordNotFound
。
Model.find_by
与 Model.find
非常相似,可让您搜索数据库中的任何列或列组,但如果没有记录与搜索匹配,则返回 nil
。
另一方面,Model.where
返回一个 Model::ActiveRecord_Relation
对象,它就像一个包含与搜索匹配的所有记录的数组。如果未找到记录,则返回一个空的 Model::ActiveRecord_Relation
对象。
我希望这些可以帮助您决定在任何时候使用哪个。
除了接受的答案外,以下也是有效的
Model.find()
可以接受 id 数组,并将返回所有匹配的记录。 Model.find_by_id(123)
也接受数组,但只会处理数组中存在的第一个 id 值
Model.find([1,2,3])
Model.find_by_id([1,2,3])
假设我有一个模型 User
用户.find(id)
返回主键 = id 的行。返回类型将为 User
对象。
User.find_by(email:"abc@xyz.com")
在这种情况下,返回具有匹配属性或电子邮件的第一行。返回类型将再次为 User
对象。
注意:- User.find_by(email: "abc@xyz.com")
类似于 User.find_by_email("abc@xyz.com")
User.where(project_id:1)
返回用户表中属性匹配的所有用户。
这里的返回类型将是 ActiveRecord::Relation
对象。 ActiveRecord::Relation
类包括 Ruby 的 Enumerable
模块,因此您可以像使用数组一样使用它的对象并对其进行遍历。
您列表中的两个 #2 都已被弃用。您仍然可以使用 find(params[:id])
。
通常,where()
适用于大多数情况。
这是一篇很棒的帖子:https://web.archive.org/web/20150206131559/http://m.onkey.org/active-record-query-interface
使用任何开源技术的最佳部分是您可以检查它的长度和广度。 Checkout this link
find_by ~> 查找符合指定条件的第一条记录。没有隐含的顺序,所以如果顺序很重要,您应该自己指定。如果没有找到记录,则返回 nil。
find ~> 查找符合指定条件的第一条记录,但如果没有找到记录,则会引发异常,但这是故意的。
请查看上面的链接,它包含以下两个功能的所有说明和用例。
我个人会推荐使用
where(< columnname> => < columnvalue>)
不定期副业成功案例分享
find_by
将从where(*args)
中拯救::RangeError
并返回 nil。