find vs find_by vs where


127

Raylarda yeniyim. Bir kayıt bulmanın birçok yolu olduğunu görüyorum:

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

Görünüşe göre hepsi tamamen aynı SQL'i oluşturuyor. Aynı şeyin birden fazla kayıt bulmak için de geçerli olduğuna inanıyorum:

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

Hangisinin kullanılacağına dair genel bir kural veya tavsiye var mı?

Yanıtlar:


103

İhtiyaçlarınıza en uygun olduğunu düşündüğünüz hangisini kullanın.

findYöntem genellikle No bir satır elde etmek için kullanılır:

Model.find(1)

findÖğe, sağladığınız özellik tarafından bulunmazsa bir istisna atacağını belirtmek gerekir . Kullanım whereistisna önlemek için (öznitelik bulunmazsa boş bir dizi döndürür aşağıda açıklandığı gibi) atılan.

Diğer kullanımları findgenellikle şu gibi şeylerle değiştirilir:

Model.all
Model.first

find_bybir sütun içinde bilgi ararken yardımcı olarak kullanılır ve adlandırma kurallarıyla buna eşlenir. Örneğin, nameveritabanınızda adlandırılmış bir sütununuz varsa, aşağıdaki sözdizimini kullanırsınız:

Model.find_by(name: "Bob")

.where geleneksel yardımcıların yapmayacağı durumlar için biraz daha karmaşık mantık kullanmanıza izin veren ve koşullarınıza uyan bir öğe dizisi (veya aksi takdirde boş bir dizi) döndüren bir yakalama daha fazlasıdır.


62
find_bykullanımdan kaldırılmadı, ancak sözdizimi biraz değişiyor. Gönderen find_by_name("Bob")için find_by(:name, "Bob").
Brian Morearty

61
@BrianMorearty Bunu kastettiğine inanıyorumfind_by(name: "Bob")
MCB

1
@BrianMorearty Kullanımdan find_by_...kaldırıldığına dair herhangi bir kanıt bulamadım , kaynağınız var mı? Görünüşe göre find_byve find_by_...her ikisi de Rails 4'te hala destekleniyor.
Dennis

4
@Dennis, kullanımdan kaldırılmadığı konusunda haklısınız ve ben de öyle dedim. Ama "ama sözdizimi biraz değişiyor" dediğimde daha net olabilirdim. Demek istediğim, "ama artık yeni bir sözdizimi de mevcut." Yeni sözdizimi için MCB'nin düzeltmesine bakın.
Brian Morearty

3
Rails 4.0 sürümünde "find_by _... ve find_by _...! Dışındaki tüm dinamik yöntemler kullanımdan kaldırılmıştır" daha fazla edgeguides.rubyonrails.org/…
Mukesh Singh Rathaur sürümünde bahsedilen

131

nerede ActiveRecord :: ilişkisi döndürür

Şimdi uygulama ile bul'a bir göz atın:

def find_by
  where(*args).take
end

Gördüğünüz gibi find_by , nerede olduğu ile aynıdır, ancak yalnızca bir kayıt döndürür. Bu yöntem 1 kayıt almak için kullanılmalı ve bazı şartlar ile tüm kayıtları almak için nerede kullanılmalıdır.


1
find_by bir nesne döndürür, ancak burada bir koleksiyon döndürür.
Kick Buttowski

Ne zaman aralığının dışında sorgu değeri, find_bykurtaracak ::RangeErrorgelen where(*args) ve dönüş nil.
fangxing

34

Model.find

1- Parametre: Bulunacak nesnenin kimliği.

2- Bulunursa: Nesneyi döndürür (Sadece bir nesne).

3- Bulunmazsa: bir ActiveRecord::RecordNotFoundistisna oluşturur.

Model.find_by

1- Parametre: anahtar / değer

Misal:

User.find_by name: 'John', email: 'john@doe.com'

2- Bulunursa: Nesneyi döndürür.

3- Bulunmazsa: geri döner nil.

Not:ActiveRecord::RecordNotFound Kullanımıartırmasını istiyorsanızfind_by!

Model.where

1- Parametre: aynı find_by

2- Bulunursa: ActiveRecord::RelationParametrelerle eşleşen bir veya daha fazla kayıt içeren döndürür .

3- Bulunmazsa: Boş döndürür ActiveRecord::Relation.


31

Aralarında findve find_byarasında bir fark vardır, findbulunmazsa bir hata döndürür, oysa find_byboş döndürür.

Bazen bunun find_by email: "haha"aksine bir yönteminiz varsa okumak daha kolaydır .where(email: some_params).first.


17

Rails 4'ten bu yana şunları yapabilirsiniz:

User.find_by(name: 'Bob')

bu find_by_nameRails 3'teki eşdeğerdir .

#whereNe zaman #findve #find_byyeterli olmadığında kullanın .


2
Agis, sana katılıyorum ama internet kullandığımız neden olduğu üzerinde arama oldum find_bydeğil find_by_<column_name>. Birine cevap vermem gerekiyor.
KULKING

Agis, artık find_by_nameRails 4'te kullanmamamız gerektiği iddianızı destekleyecek herhangi bir kaynağınız var mı? Bildiğim kadarıyla kullanımdan kaldırılmadı .
Dennis

Bunu yapmanın basit bir yolu var mı, ancak adın içinde joker karakter olduğunu söyleyin, bu gibi bir şeyfind_by(name: "Rob*")
Batman

1
@Dennis Her ikisini de kullanmak mümkündür, geçerlidir. API daha sezgisel IMHO olduğu için yeni sözdizimini tercih ediyorum. Kendim böyle tasarlardım :)
Agis

8

Kabul edilen cevap genellikle hepsini kapsar, ama sadece sen güncellenmesi gibi bir şekilde modelle işe planlıyoruz ve (kimin tek bir kayıt alınıyor örtmek, bir şeyler eklemek istiyorum id, O zaman bilmiyorum) find_byolduğunu gidilecek yol, çünkü kaydı alır ve onu bir diziye koymaz

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

ama kullanırsanız where, doğrudan güncelleyemezsiniz

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)

böyle bir durumda bunu şu şekilde belirtmeniz gerekirdi

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

tam olarak aradığım şey
Paul Brunache

2
@kit = Kit.where (numara: "3456"). ilk - Bu, doğrudan güncellemenizi sağlar ve kullanımdan kaldırıldıktan sonra daha güvenli olur
Paul Brunache

6

Kabul edilen cevabın yanı sıra aşağıdakiler de geçerlidir

Model.find()kimlik dizisini kabul edebilir ve eşleşen tüm kayıtları döndürür. Model.find_by_id(123)ayrıca diziyi de kabul eder, ancak yalnızca dizide bulunan ilk kimlik değerini işler

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


3

Şimdiye kadar verilen cevapların hepsi tamam.

Ancak, ilginç bir fark, Model.findkimliğe göre arama yapılmasıdır; bulunursa, bir Modelnesne (sadece tek bir kayıt) döndürür, ancak ActiveRecord::RecordNotFoundbaşka türlü atar .

Model.find_byçok benzerdir Model.findve veritabanınızdaki herhangi bir sütun veya sütun grubunu aramanıza izin verir, ancak nilaramayla eşleşen hiçbir kayıt yoksa geri döner .

Model.whereÖte yandan , aramayla eşleşen tüm kayıtlarıModel::ActiveRecord_Relation içeren bir dizi gibi bir nesne döndürür . Kayıt bulunamazsa, boş bir nesne döndürür .Model::ActiveRecord_Relation

Umarım bunlar, herhangi bir zamanda hangisini kullanacağınıza karar vermenize yardımcı olur.


3

Bir modelim olduğunu varsayalım User

  1. User.find(id)

Birincil anahtarın = id olduğu bir satır döndürür. Dönüş türü Usernesne olacaktır .

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

Bu durumda, eşleşen özelliğe veya e-postaya sahip ilk satırı döndürür. Dönüş türü Useryine nesne olacaktır .

Not: - User.find_by(email: "abc@xyz.com")benzerdirUser.find_by_email("abc@xyz.com")

  1. User.where(project_id:1)

Özelliğin eşleştiği kullanıcılar tablosundaki tüm kullanıcıları döndürür.

Burada dönüş türü ActiveRecord::Relationnesne olacaktır . ActiveRecord::Relationsınıfı Ruby'nin Enumerablemodülünü içerir, böylece nesnesini bir dizi gibi kullanabilir ve üzerinde gezinebilirsiniz.


0

Herhangi bir açık kaynak teknolojisiyle çalışmanın en iyi yanı, uzunluğunu ve genişliğini inceleyebilmenizdir. Bu bağlantıya göz atın

find_by ~> Belirtilen koşullarla eşleşen ilk kaydı bulur. Örtülü bir sipariş yoktur, bu nedenle sipariş önemliyse, kendiniz belirtmelisiniz. Kayıt bulunmazsa, sıfır döndürür.

bul ~> Belirtilen koşullarla eşleşen ilk kaydı bulur, ancak herhangi bir kayıt bulunmazsa, bir istisna oluşturur, ancak bu kasıtlı olarak yapılır.

Yukarıdaki bağlantıya göz atın, aşağıdaki iki işlev için tüm açıklamalara ve kullanım durumlarına sahiptir.


-5

Şahsen kullanmanızı tavsiye edeceğim

where(< columnname> => < columnvalue>)

1
Bu soruya cevap verebilir. Ancak, kabul edilen cevap yerine yaklaşımınızı kullanmanın artılarını ve eksilerini açıklamaya çalışın.
Vivek Kumar
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.