Raylarda kapsam / adlandırılmış_ kapsam nedir?


106

Yakın zamanda staj yapmaya başladım. İşverenim ruby ​​on rails kullanıyor ve anlamak için aramam gereken yeni sözdizimiyle sık sık karşılaşıyorum. Name_scope ile ilgili iyi bir açıklama için etrafta dolaştım, ancak şu ana kadar bulduğum şey çoğunlukla bunun için yüksek övgü veren blog yazıları, daha ziyade düz bir tanım veya giriş.

Ruby on rails'de name_scope (şimdi basitçe kapsam olarak adlandırılır) tam olarak nedir?



2
Bu blog yazısı, adlandırılmış kapsamları öğrenirken benim için çok değerliydi
Peter Brown

@notapatch bağlantı öldü, başka bir tane var mı?
mbigras

Ryan Daigle: Adlandırılmış Kapsam: Sadece Koşullar İçin Değil, Biliyor musunuz ?: web.archive.org/web/20160306110506/http://…
notapatch

Yanıtlar:


213

Kapsam, bir koleksiyonun alt kümesidir. Karmaşık görünüyor mu? Değil. Şunu hayal edin:

Kullanıcılarınız var. Şimdi, bu Kullanıcılardan bazıları bülteninize abone oldu. Kullanıcı Veritabanına bir alan ekleyerek haber bülteni alan kişileri işaretlediniz (user.subscribed_to_newsletter = true). Doğal olarak, bazen haber bülteninize abone olan Kullanıcıları almak istersiniz.

Elbette bunu her zaman yapabilirsiniz:

User.where(subscribed_to_newsletter: true).each do #something

Her zaman bunu yazmak yerine, bunun gibi bir şey yapabilirsiniz.

#File: users.rb
class User < ActiveRecord::Base
  scope :newsletter, where(subscribed_to_newsletter: true)
  #yada yada
end

Rails 4 veya daha yenisini kullanıyorsanız , bunun yerine şunu yapın:

#File: users.rb
class User < ActiveRecord::Base
  scope :newsletter, -> { where(subscribed_to_newsletter: true) }
  #yada yada
end

Bu, abonelerinize yalnızca şunu yaparak erişmenizi sağlar:

User.newsletter.each do #something

Bu çok basit bir örnektir ancak genel olarak kapsamlar işinizi kolaylaştırmak için çok güçlü araçlar olabilir.

Bu bağlantıya göz atın: API Açıklaması


7
Bunun, Kullanıcı Sınıfında 'subscribedUsers' adlı bir yöntemi tanımlamaya kıyasla avantajlarının ne olduğunu sorabilir miyim? örn. 'def self.subscribedUsers self.where (: subscribed_to_newsletter => true) end
2011'de

3
@redroot avantajı, scopesözdizimi çok daha temiz, aynı sonucu elde edersiniz, ancak tek bir satırla
Aldo 'xoen' Giambelluca 3'12

9
@redroot Kapsamlar veritabanını tembel bir şekilde sorgularken yöntemler hevesle yapacağı için büyük bir verimlilik avantajı vardı. Rails 3'te yöntemler de tembelleşti, bu yüzden artık fark daha sözdizimsel. Kaynak
evanrmurphy


Ayrıca kapsamlı rotalar bağlantısının
Benjineer

34

Aktif kayıttaki kapsam, sınıf yöntemleri gibidir, ancak İlişki nesnesini döndürürler, bu da başka bir kapsam veya aktif kayıt sorgulama yöntemini çağırabileceğiniz anlamına gelir.

Örneğin, aşağıda belirtilen kapsam yöntemlerine sahip bir Zombie modeliniz (zombi tablosu) varsa,

class Zombie
  scope :rotting, -> { where(rotting: true) }
  scope :fresh, -> { where('age < ?', 25) }
  scope :recent, -> { order(created_at: :desc) }
end

Ve sen arıyorsun

Zombie.rotting.fresh.recent.limit(3)

Aşağıdakine SQL'de çevirir,

select "zombies.*" from "zombies" where "zombies"."rotting" = 't' and (age<20) order by create_at desc limit 3

Yukarıdaki örnek, raylar 4 sözdizimine dayanmaktadır


Herhangi bir belgede sipariş örneğini (: created_at,: desc) bulamıyorum. Kastettiğin mümkün mü scope :recent, -> { order(created_at: :desc) }? apidock.com/rails/v4.2.9/ActiveRecord/QueryMethods/order
notapatch


7

Kapsamlar, sınıf yöntemlerinden başka bir şey değildir.

Neden kullanıyorsunuz?

Kapsam belirleme , ilişkilendirme nesneleri veya modellerinde yöntem çağrıları olarak başvurulabilecek, yaygın olarak kullanılan sorguları (uzun veya en sık kullanılan sorgular için kısayol olarak düşünülebilir) belirlemenize olanak tanır . Bu kapsamlar ile, nerede, birleşir ve içerir gibi daha önce ele alınan her yöntemi kullanabilirsiniz. Tüm kapsam yöntemleri, başka yöntemlerin (diğer kapsamlar gibi) çağrılmasına izin verecek bir ActiveRecord :: Relation nesnesi döndürür .

Basit bir kapsam tanımlamak için, sınıf içinde kapsam yöntemini kullanırız, bu kapsam çağrıldığında çalıştırmak istediğimiz sorguyu iletiriz:

class Article < ActiveRecord::Base
  scope :published, -> { where(published: true) }
end

Bu, bir sınıf yöntemini tanımlamakla tamamen aynıdır ve kullandığınız kişisel tercih meselesidir:

class Article < ActiveRecord::Base
  def self.published
    where(published: true)
  end
end

Örnekli tam açıklama için lütfen aşağıdaki bağlantıyı izleyin. Umarım bu sana yardımcı olmuştur.

http://guides.rubyonrails.org/active_record_querying.html


3
Bir sınıf yöntemi tanımlamakla tam olarak aynı değildir . Sınıf yöntemleri nilbirkaç durumda geri döner ve bu nedenle belirli koşullar için zincirlenemez.
Arslan Ali

1
  • Bir modeliniz olduğunu hayal edin: Kişi .

Şimdi sizi hayal edin:

  • Kızıl saçlı dünyadaki bütün insanları istiyorum.
  • dünyadaki kriket oynayan tüm insanları istiyorum

Bir dürbün kullanarak bu belirli insan sınıflarını elde edebilirsiniz!

Person.red_hair.cricket ## finds all people with red hair who play cricket
Person.red_hair ## finds all people with red hair
Person.cricket ## finds all people who play cricket.

Şimdi bu o kadar zor değildi, değil mi?

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.