Co to jest scope / named_scope w railsach?


106

Niedawno rozpocząłem staż. Mój pracodawca używa ruby ​​on rails i często napotykam nową składnię, którą muszę spojrzeć, aby zrozumieć. Przeszukałem go w poszukiwaniu dobrego wyjaśnienia named_scope, ale jak dotąd znalazłem głównie posty na blogu, które chwalą go, a raczej prostą definicję lub wprowadzenie.

Czym dokładnie jest named_scope (teraz nazywany po prostu zakresem) w ruby ​​on rails?



2
Ten wpis na blogu był dla mnie nieoceniony podczas nauki nazwanych zakresów: ryandaigle.com/articles/2008/8/20/…
Peter Brown

@notapatch link jest martwy, czy masz inny?
mbigras

Ryan Daigle: Nazwany zakres: to nie tylko dla warunków, wiesz ?: web.archive.org/web/20160306110506/http://…
notapatch

Odpowiedzi:


213

Zakres to podzbiór kolekcji. Brzmi skomplikowanie? Tak nie jest. Wyobraź to sobie:

Masz użytkowników. Teraz niektórzy z tych Użytkowników są zapisani do Twojego biuletynu. Osoby, które otrzymują newsletter, oznaczyłeś dodając pole do Bazy Użytkowników (user.subscribe_to_newsletter = true). Oczywiście czasami chcesz pozyskać tych Użytkowników, którzy zapisali się do Twojego biuletynu.

Oczywiście zawsze możesz to zrobić:

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

Zamiast zawsze to pisać, możesz jednak zrobić coś takiego.

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

Jeśli używasz Rails 4 lub nowszych , zrób to:

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

Dzięki temu możesz uzyskać dostęp do swoich subskrybentów, wykonując po prostu następujące czynności:

User.newsletter.each do #something

To bardzo prosty przykład, ale ogólnie zakresy mogą być bardzo potężnymi narzędziami ułatwiającymi pracę.

Sprawdź ten link: Opis API


7
Czy mogę zapytać, jakie są zalety tego w porównaniu z definiowaniem metody w klasie użytkowników o nazwie „subscribeUsers”? np. 'def self.subscribeUsers self.where (: subscribe_to_newsletter => true) end
redroot

3
@redroot zaletą jest to, że scopeskładnia jest znacznie czystsza, otrzymujesz ten sam wynik, ale tylko z jedną linią
Aldo 'xoen' Giambelluca

9
@redroot Kiedyś była duża zaleta w zakresie wydajności, ponieważ zakresy leniwie odpytywały bazę danych, podczas gdy metody robiły to chętnie. W Railsach 3 metody również stały się leniwe, więc teraz różnica jest bardziej składniowa. Źródło
evanrmurphy,

Link do dokumentacji API jest uszkodzony, zaktualizuj api.rubyonrails.org/classes/ActiveRecord/Scoping/Named/…
Lohith MV

Umożliwia także korzystanie z linku do
Benjineer

34

zasięg w aktywnym rekordzie jest podobny do metod klasowych, ale zwracają obiekt Relation, co oznacza, że ​​możesz wywołać inny zasięg lub metodę zapytania rekordu aktywnego.

Na przykład, jeśli masz model Zombie (stół zombie) z wymienionymi poniżej metodami zakresu,

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

I dzwonisz

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

To tłumaczy się poniżej w SQL,

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

Powyższy przykład oparty jest na składni rails 4


Nie mogę znaleźć przykładu zamówienia (: created_at,: desc) w żadnej dokumentacji. Czy to możliwe, że miałeś na myśli scope :recent, -> { order(created_at: :desc) }? apidock.com/rails/v4.2.9/ActiveRecord/QueryMethods/order
notapatch

7

Najlepszym sposobem na zrozumienie szczegółów jest przejście do dokumentacji API.

Otrzymasz pełne informacje i sposoby, w jakie możemy korzystać z Zakresów.

Dokumentacja API zakresu


7

Zakresy to nic innego jak metody klas.

Po co ich używać?

Zasięg umożliwia określenie często używanych zapytań (można je traktować jako skrót dla długich lub najczęściej używanych zapytań), do których można się odwoływać jako wywołania metod w obiektach lub modelach asocjacji. Dzięki tym zakresom możesz użyć wszystkich wcześniej omówionych metod, takich jak gdzie, łączy i zawiera. Wszystkie metody zakresu zwrócą obiekt ActiveRecord :: Relation, który pozwoli na wywołanie na nim dalszych metod (takich jak inne zakresy).

Aby zdefiniować prosty zakres, używamy metody scope wewnątrz klasy, przekazując zapytanie, które chcielibyśmy uruchomić, gdy ten zakres zostanie wywołany:

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

To jest dokładnie to samo, co definiowanie metody klasowej, a to, której używasz, zależy od osobistych preferencji:

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

Kliknij poniższy link, aby uzyskać pełny opis z przykładem. Mam nadzieję, że to Ci pomoże.

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


3
To nie jest dokładnie to samo, co definiowanie metody klasy . Metody klas zwracają się nilw kilku przypadkach, a zatem nie można ich łączyć w łańcuch w pewnych warunkach.
Arslan Ali

1
  • Wyobraź sobie, że masz model: Osoba .

Teraz wyobraź sobie:

  • chcą wszystkich ludzi na świecie, którzy mają rude włosy.
  • chcą wszystkich ludzi na świecie, którzy grają w krykieta

Możesz uzyskać te konkretne klasy ludzi, używając zakresu!

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.

To nie było takie trudne, prawda?

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.