Ruby-on-rails find vs find_by vs where
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11161663/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
find vs find_by vs where
提问by Victor Ronin
I am new to rails. What I see that there are a lot of ways to find a record:
我是导轨的新手。我看到有很多方法可以找到记录:
find_by_<columnname>(<columnvalue>)find(:first, :conditions => { <columnname> => <columnvalue> }where(<columnname> => <columnvalue>).first
find_by_<columnname>(<columnvalue>)find(:first, :conditions => { <columnname> => <columnvalue> }where(<columnname> => <columnvalue>).first
And it looks like all of them end up generating exactly the same SQL. Also, I believe the same is true for finding multiple records:
看起来它们最终都生成了完全相同的 SQL。另外,我相信查找多条记录也是如此:
find_all_by_<columnname>(<columnvalue>)find(:all, :conditions => { <columnname> => <columnvalue> }where(<columnname> => <columnvalue>)
find_all_by_<columnname>(<columnvalue>)find(:all, :conditions => { <columnname> => <columnvalue> }where(<columnname> => <columnvalue>)
Is there a rule of thumb or recommendation on which one to use?
是否有使用哪一个的经验法则或建议?
采纳答案by John
Use whichever one you feel suits your needs best.
使用您认为最适合您需求的任何一种。
The findmethod is usually used to retrieve a row by ID:
该find方法通常用于按 ID 检索行:
Model.find(1)
It's worth noting that findwill throw an exception if the item is not found by the attribute that you supply. Use where(as described below, which will return an empty array if the attribute is not found) to avoid an exception being thrown.
值得注意的是,find如果您提供的属性未找到该项目,则会引发异常。使用where(如下所述,如果未找到该属性,它将返回一个空数组)以避免抛出异常。
Other uses of findare usually replaced with things like this:
的其他用法find通常用这样的东西代替:
Model.all
Model.first
find_byis used as a helper when you're searching for information within a column, and it maps to such with naming conventions. For instance, if you have a column named namein your database, you'd use the following syntax:
find_by当您在列中搜索信息时用作帮助程序,并且它通过命名约定映射到此类。例如,如果您name的数据库中有一个列名,则应使用以下语法:
Model.find_by(name: "Bob")
.whereis more of a catch all that lets you use a bit more complex logic for when the conventional helpers won't do, and it returns an array of items that match your conditions (or an empty array otherwise).
.where更像是一个包罗万象的东西,它可以让您在传统帮助程序无法执行的情况下使用更复杂的逻辑,并且它返回与您的条件匹配的项目数组(否则为空数组)。
回答by Mike Andrianov
wherereturns ActiveRecord::Relation
其中返回 ActiveRecord::Relation
Now take a look at find_by implementation:
现在看看 find_by 的实现:
def find_by
where(*args).take
end
As you can see find_byis the same as wherebut it returns only one record. This method should be used for getting 1 record and whereshould be used for getting all records with some conditions.
如您所见,find_by与where相同,但它只返回一条记录。此方法应该用于获取 1 条记录,并且应该使用where获取具有某些条件的所有记录。
回答by Hossam Khamis
Model.find
Model.find
1- Parameter: ID of the object to find.
1- 参数:要查找的对象的 ID。
2- If found: It returns the object (One object only).
2- 如果找到:它返回对象(仅一个对象)。
3- If not found: raises an ActiveRecord::RecordNotFoundexception.
3- 如果未找到:引发ActiveRecord::RecordNotFound异常。
Model.find_by
Model.find_by
1- Parameter: key/value
1- 参数:键/值
Example:
例子:
User.find_by name: 'John', email: '[email protected]'
2- If found: It returns the object.
2- 如果找到:它返回对象。
3- If not found: returns nil.
3- 如果没有找到:返回nil。
Note:If you want it to raise ActiveRecord::RecordNotFounduse find_by!
注意:如果你想让它提高ActiveRecord::RecordNotFound使用find_by!
Model.where
Model.where
1- Parameter: same as find_by
1- 参数:同 find_by
2- If found: It returns ActiveRecord::Relationcontaining one or more records matching the parameters.
2- 如果找到:它返回ActiveRecord::Relation包含一个或多个与参数匹配的记录。
3- If not found: It return an Empty ActiveRecord::Relation.
3- 如果没有找到:它返回一个 Empty ActiveRecord::Relation。
回答by Kasumi
There is a difference between findand find_byin that findwill return an error if not found, whereas find_bywill return null.
有之间的差异find,并find_by在find返回如果没有找到,而一个错误find_by将返回null。
Sometimes it is easier to read if you have a method like find_by email: "haha", as opposed to .where(email: some_params).first.
有时,如果您有类似的方法find_by email: "haha",则更容易阅读,而不是.where(email: some_params).first.
回答by Agis
Since Rails 4 you can do:
从 Rails 4 开始,您可以执行以下操作:
User.find_by(name: 'Bob')
which is the equivalent find_by_namein Rails 3.
这与find_by_nameRails 3 中的等效。
Use #wherewhen #findand #find_byare not enough.
使用#where时#find并#find_by不够。
回答by Leonard Kakande
The accepted answer generally covers it all, but I'd like to add something,
just incase you are planning to work with the model in a way like updating, and you are retrieving a single record(whose idyou do not know), Then find_byis the way to go, because it retrieves the record and does not put it in an array
接受的答案通常涵盖所有内容,但我想添加一些内容,以防万一您计划以更新等方式使用模型,并且您正在检索单个记录(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" = , "updated_at" = WHERE "kits"."id" =
1 [["job_id", 2], ["updated_at", Tue, 12 May 2015 07:16:58 UTC +00:00]]
(0.6ms) COMMIT => true
but if you use wherethen you can not update it directly
但是如果你使用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)
in such a case you would have to specify it like this
在这种情况下,您必须像这样指定它
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" = , "updated_at" = WHERE "kits"."id" = 1
[["job_id", 3], ["updated_at", Tue, 12 May 2015 07:28:04 UTC +00:00]]
(0.5ms) COMMIT => true
回答by Saumya Mehta
Apart from accepted answer, following is also valid
除了接受的答案,以下也是有效的
Model.find()can accept array of ids, and will return all records which matches.
Model.find_by_id(123)also accept array but will only process first id value present in array
Model.find()可以接受 id 数组,并返回所有匹配的记录。
Model.find_by_id(123)也接受数组,但只会处理数组中存在的第一个 id 值
Model.find([1,2,3])
Model.find_by_id([1,2,3])
回答by evanbikes
Both #2s in your lists are being deprecated. You can still use find(params[:id])though.
您列表中的两个 #2 都已弃用。你仍然可以使用find(params[:id])。
Generally, where()works in most situations.
通常,where()在大多数情况下都有效。
Here's a great post: http://m.onkey.org/active-record-query-interface
这是一篇很棒的文章:http: //m.onkey.org/active-record-query-interface
回答by Nikhil Mohadikar
Suppose I have a model User
假设我有一个模型 User
User.find(id)
User.find(id)
Returns a row where primary key = id. The return type will be Userobject.
返回主键 = id 的行。返回类型将是User对象。
User.find_by(email:"[email protected]")
User.find_by(email:"[email protected]")
Returns first row with matching attribute or email in this case. Return type will be Userobject again.
在这种情况下,返回具有匹配属性或电子邮件的第一行。返回类型将User再次是对象。
Note :- User.find_by(email: "[email protected]")is similar to User.find_by_email("[email protected]")
注意:-User.find_by(email: "[email protected]")类似于User.find_by_email("[email protected]")
User.where(project_id:1)
User.where(project_id:1)
Returns all users in users table where attribute matches.
返回用户表中属性匹配的所有用户。
Here return type will be ActiveRecord::Relationobject. ActiveRecord::Relationclass includes Ruby's Enumerablemodule so you can use it's object like an array and traverse on it.
这里返回类型将是ActiveRecord::Relation对象。ActiveRecord::Relationclass 包含 Ruby 的Enumerable模块,因此您可以像使用数组一样使用它的对象并遍历它。
回答by echelon
The answers given so far are all OK.
到目前为止给出的答案都是可以的。
However, one interesting difference is that Model.findsearches by id; if found, it returns a Modelobject (just a single record) but throws an ActiveRecord::RecordNotFoundotherwise.
然而,一个有趣的区别是Model.find按 id 搜索;如果找到,它返回一个Model对象(只是一个记录),ActiveRecord::RecordNotFound否则抛出一个。
Model.find_byis very similar to Model.findand lets you search any column or group of columns in your database but it returns nilif no record matches the search.
Model.find_by非常类似于Model.find并允许您搜索数据库中的任何列或列组,但nil如果没有记录与搜索匹配,则返回。
Model.whereon the other hand returns a Model::ActiveRecord_Relationobject which is just like an array containing all the records that match the search. If no record was found, it returns an empty Model::ActiveRecord_Relationobject.
Model.where另一方面,返回一个Model::ActiveRecord_Relation对象,它就像一个包含与搜索匹配的所有记录的数组。如果没有找到记录,它返回一个空Model::ActiveRecord_Relation对象。
I hope these would help you in deciding which to use at any point in time.
我希望这些可以帮助您决定在任何时候使用哪个。

