Vic*_*nin 118 ruby-on-rails dynamic-finders rails-activerecord
我是铁杆新手.我看到有很多方法可以找到记录:
find_by_<columnname>(<columnvalue>)find(:first, :conditions => { <columnname> => <columnvalue> }where(<columnname> => <columnvalue>).first看起来所有这些都会产生完全相同的SQL.此外,我相信找到多个记录也是如此:
find_all_by_<columnname>(<columnvalue>)find(:all, :conditions => { <columnname> => <columnvalue> }where(<columnname> => <columnvalue>)是否有经验法则或建议使用哪一个?
Mik*_*nov 125
其中,返回的ActiveRecord ::关系
现在来看看find_by的实现:
def find_by
where(*args).take
end
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,find_by与where相同,但它只返回一条记录.这个方法应该用于获取1条记录,并在那里应该用于获取的所有记录的一些条件.
Joh*_*ohn 94
使用您认为最适合您需求的任何一种.
该find方法通常用于按ID检索行:
Model.find(1)
Run Code Online (Sandbox Code Playgroud)
值得注意的是,find如果您提供的属性找不到该项,则会抛出异常.使用where(如下所述,如果找不到该属性,将返回一个空数组)以避免抛出异常.
其他用途find通常被替换为这样的东西:
Model.all
Model.first
Run Code Online (Sandbox Code Playgroud)
find_by当您在列中搜索信息时,它将用作帮助程序,并使用命名约定映射到此类.例如,如果name在数据库中有一个以列命名的列,则使用以下语法:
Model.find_by(name: "Bob")
Run Code Online (Sandbox Code Playgroud)
.where 更常见的是,当传统的帮助程序不能执行时,它会让您使用更复杂的逻辑,并返回符合条件的项目数组(否则为空数组).
小智 31
有之间的差异find,并find_by在find会返回一个错误,如果没有找到,而find_by将返回null.
如果你有一个像这样的方法find_by email: "haha",有时会更容易阅读.where(email: some_params).first.
Hos*_*mis 29
Model.find
1-参数:要查找的对象的ID.
2-如果找到:它返回对象(仅一个对象).
3-如果未找到:引发ActiveRecord::RecordNotFound异常.
Model.find_by
1-参数:键/值
例:
User.find_by name: 'John', email: 'john@doe.com'
Run Code Online (Sandbox Code Playgroud)
2-如果找到:它返回对象.
3-如果未找到:返回nil.
注意:如果您希望它提高ActiveRecord::RecordNotFound使用率find_by!
Model.where
1-参数:与...相同 find_by
2-如果找到:它返回ActiveRecord::Relation包含一个或多个与参数匹配的记录.
3-如果未找到:它返回空ActiveRecord::Relation.
Agi*_*gis 17
从Rails 4开始,您可以:
User.find_by(name: 'Bob')
Run Code Online (Sandbox Code Playgroud)
这与find_by_nameRails 3中的等价物相同.
使用#where时间#find和#find_by不够.
接受的答案通常涵盖了所有内容,但我想添加一些东西,只是因为你计划以更新的方式使用模型,而你正在检索单个记录(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
Run Code Online (Sandbox Code Playgroud)
但如果您使用,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)
Run Code Online (Sandbox Code Playgroud)
在这种情况下,你必须像这样指定它
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
Run Code Online (Sandbox Code Playgroud)
到目前为止给出的答案都是可以的。
然而,一个有趣的区别是Model.find按 id 搜索;如果找到,它返回一个Model对象(只是一个记录),ActiveRecord::RecordNotFound否则抛出一个。
Model.find_by非常类似于Model.find并允许您搜索数据库中的任何列或列组,但nil如果没有记录与搜索匹配,则返回。
Model.where另一方面,返回一个Model::ActiveRecord_Relation对象,它就像一个包含与搜索匹配的所有记录的数组。如果没有找到记录,它返回一个空Model::ActiveRecord_Relation对象。
我希望这些可以帮助您决定在任何时候使用哪个。
您的列表中的#2都被弃用了.你仍然可以使用find(params[:id]).
通常,where()在大多数情况下都适用.
这是一篇很棒的文章:http://m.onkey.org/active-record-query-interface
小智 5
除了接受的答案,以下也是有效的
Model.find()可以接受id数组,并返回匹配的所有记录.
Model.find_by_id(123)也接受数组,但只会处理数组中出现的第一个id值
Model.find([1,2,3])
Model.find_by_id([1,2,3])
Run Code Online (Sandbox Code Playgroud)
假设我有一个模型 User
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::Relationclass 包含 Ruby 的Enumerable模块,因此您可以像使用数组一样使用它的对象并遍历它。