2012-03-15 15 views
10

Przyjrzałem się ponad 10 stronom, próbując znaleźć zalety zakresu w stosunku do każdej innej metody klasy ActiveRecord, która zwraca ActiveRecord :: Relation.Jaka jest prawdziwa korzyść z obiektywów?

Poniżej na przykład, dlaczego są zakresy lepsze niż alternatywa pod nim, które robią to samo:

#scope :pat1, lambda {{:conditions => ["name like ?", 'J%']}}  
    #scope :pat2, lambda {{:conditions => ["id > 5"]}} 

    def self.pat1 
    where("name like ?", 'J%') 
    end 

    def self.pat2 
    where("id > 5") 
    end 

    def patx 
    self.class.pat1.pat2.first 
    end 

Dokumentacja kółko mówi, że zakresy są korzystne, ponieważ mogą one być przykuty ...

"Wszystkie metody zasięgu zwrócą obiekt ActiveRecord :: Relation, który pozwoli na wywołanie na nim dalszych metod (na przykład innych zakresów)." - guides.rubyonrails.org

„Głównym powodem zakresy są lepsze od zwykłych metod klasy jest to, że mogą one być przykuty z innymi metodami” http://ruby.railstutorial.org

... ale alternatywą powyżej mogą być również przykuty jej wytwarzania takie same wyniki.

Próbuję się dowiedzieć, czy dzieje się tu coś nowego w cesarskim ubraniu. Nawet z punktu widzenia syntaktycznego wydaje się, że nie ma żadnej korzyści. Czy są szybsze - niektóre źródła niejasno to sugerują.

Odpowiedz

3

Zasięgi ActiveRecord to tak naprawdę tylko cukier składniowy zawarty w najlepszej praktyce, jak już wspomniano.

W dniach 2.x Railsów, kiedy nazywano je "named_scope", liczyły się trochę więcej. Pozwoliły one na łatwe powiązanie warunków generowania zapytania. Dzięki usprawnieniom Railsów 3.x z Arelem łatwo jest tworzyć funkcje dla relacji z zapytaniami, jak zauważyłeś. Zakresy zapewniają proste i eleganckie rozwiązania dla wstępnie zdefiniowanych zapytań łańcuchowych. Posiadanie wszystkich zakresów na górze modelu poprawia czytelność i pomaga pokazać, w jaki sposób model jest używany.

+0

Arel Zakładam, że oznacza ActiveRecord :: Relation. OK. Korzyści syntaktyczne wydają mi się dyskusyjne. Ale jeśli robili coś, czego standardowe metody nie mogły wykonać w poprzednich wersjach, to to wyjaśnia. – Mark

+2

Z szynami o lepszej składni jest ważne. Nie dla bazy kodu w dniu 1 (lub nawet 100), ale dla podstawy kodu w dniu 1000. –

2

Tak, to syntaktyczne skróty, które w zasadzie reprezentują metody, które znalazłeś.
Dlaczego lepiej?
Najbardziej bezpośrednim efektem jest to, że kod 2-wierszowy jest łatwiejszy do odczytania i obsługi niż 9 linii kodu.

Szyny zawsze szukają podejścia SUCHEGO, a tutaj powtarzające się znaki def self.method end przesłaniają rzeczywisty kod.

+0

Dziękuję Tobie i Seanowi Hillowi za potwierdzenie, że nie jest to kwestia szybkości. Powyższy link railstutorial.org wyraźnie zaczyna się od stwierdzenia, że ​​ich alternatywna implementacja za pomocą zakresów jest jakoś szybsza, ale najwyraźniej nie jest z nimi powiązana za pomocą zakresów. – Mark

3

Kiedy piszesz zakres, zasadniczo robi to samo. Oto co źródło Szyny wygląda następująco:

def scope(name, scope_options = {}) 
     name = name.to_sym 
     valid_scope_name?(name) 
     extension = Module.new(&Proc.new) if block_given? 

     scope_proc = lambda do |*args| 
     options = scope_options.respond_to?(:call) ? unscoped { scope_options.call(*args) } : scope_options 
     options = scoped.apply_finder_options(options) if options.is_a?(Hash) 

     relation = scoped.merge(options) 

     extension ? relation.extending(extension) : relation 
     end 

     singleton_class.send(:redefine_method, name, &scope_proc) 
    end 

Korzyści dla zakresów w tym przypadku jest to, że są one idiomatyczne sposób definiowania zapytań, w niektórych przypadkach mniej linii kodu, a można zrobić rozszerzeń.

Przykład w źródle wygląda następująco:

scope :red, where(:color => 'red') do 
    def dom_id 
    'red_shirts' 
    end 
end 

który pozwala zadzwonić Model.red.dom_id.

0

Istnieje kilka bardzo interesujących różnic między zakresami i metodami klas, które zwracają relacje.

  1. Łatwiej radzić sobie z parametrami zerowymi dla zakresów z prostym param.present? czeku dla metod klasy trzeba wyraźnie zwrócić relację non-nil jeśli param spowodowałoby nil relację.

  2. Zakresy są łatwiejsze do rozszerzenia niż metody klas. Po prostu prześlij blok (na przykład aby poradzić sobie z paginacją), aby dodać metody. Metody klasowe mogą być rozszerzone, ale nie tak elegancko.

Pełen wybiegiem zobaczyć this post from Plataformatec.

Powiązane problemy