найти против найти не где


Я новичок в rails. То, что я вижу, что есть много способов найти запись:

  1. find_by_<columnname>(<columnvalue>)
  2. find(:first, :conditions => { <columnname> => <columnvalue> }
  3. where(<columnname> => <columnvalue>).first

и похоже, что все они в конечном итоге генерируют точно такой же SQL. Кроме того, я считаю, что то же самое верно для поиска нескольких записей:

  1. find_all_by_<columnname>(<columnvalue>)
  2. find(:all, :conditions => { <columnname> => <columnvalue> }
  3. where(<columnname> => <columnvalue>)

есть ли правила или рекомендации какой из них использовать?

10 93

10 ответов:

используйте тот, который вы чувствуете, соответствует вашим потребностям лучше всего.

The find метод обычно используется для получения строки по ID:

Model.find(1)

другое использование find обычно заменяются такими вещами:

Model.all
Model.first

Find_by используется в качестве помощника при поиске информации в столбце, и он сопоставляется с такими соглашениями об именах. Например, если у вас есть столбец с именем name в вашей базе данных, используйте следующий синтаксис:

Model.find_by_name("Bob")

однако я верю find_by осуждается.

.where это скорее уловка, которая позволяет вам использовать немного более сложную логику, когда обычные помощники не будут делать.

здесь возвращает ActiveRecord:: Relation

теперь взгляните на реализацию find_by:

def find_by
  where(*args).take
end

Как видите, find_by это то же самое, что здесь но он возвращает только одну запись. Этот метод следует использовать для получения 1 записи и здесь должны использоваться для получения всех записей с некоторыми условиями.

есть разница между find и find_by в этой find вернет ошибку, если не найдено, тогда как find_by вернет null.

иногда это легче читать, если у вас есть метод, как find_by email: "haha", а не .where(email: some_params).first.

Model.find

1-параметр: идентификатор объекта для поиска.

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 Вы можете сделать:

User.find_by(name: 'Bob')

что эквивалентно find_by_name в Rails 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" = , "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

но если вы используете 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" = , "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

оба #2s в ваших списках устарели. Вы все еще можете использовать find(params[:id]) хотя.

как правило, where() работает в большинстве ситуаций.

вот отличный пост:http://m.onkey.org/active-record-query-interface

помимо принятого ответа, следующее также действительно

Model.find() может принимать массив идентификаторов,и вернет все записи, которые соответствуют. Model.find_by_id(123) также принимает массив, но будет обрабатывать только первое значение id, присутствующее в массиве

Model.find([1,2,3])
Model.find_by_id([1,2,3])

Предположим, у меня есть модель пользователя

  1. User.find(id)

возвращает строку, на которую указывает идентификатор. Поэтому предположим, что если id = 1, то он вернет первую строку. Возвращаемым типом будет объект User.

  1. User.find_by(email:"abc@xyz.com")

возвращает первую строку с соответствующим атрибутом или электронной почтой в этом случае. Возвращаемый тип снова будет объектом пользователя.

  1. User.where(project_id:1)

возвращает всех пользователей в таблице пользователей, где атрибут спички. Здесь возвращаемый тип будет ActiveRecord:: Relation объект, содержащий список пользовательских объектов.

Я лично рекомендую использовать

where(< columnname> => < columnvalue>)