найти против найти не где
Я новичок в rails. То, что я вижу, что есть много способов найти запись:
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>)
есть ли правила или рекомендации какой из них использовать?
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])
Предположим, у меня есть модель пользователя
User.find(id)
возвращает строку, на которую указывает идентификатор. Поэтому предположим, что если id = 1, то он вернет первую строку. Возвращаемым типом будет объект User.
User.find_by(email:"abc@xyz.com")
возвращает первую строку с соответствующим атрибутом или электронной почтой в этом случае. Возвращаемый тип снова будет объектом пользователя.
User.where(project_id:1)
возвращает всех пользователей в таблице пользователей, где атрибут спички. Здесь возвращаемый тип будет ActiveRecord:: Relation объект, содержащий список пользовательских объектов.