2011-09-06 16 views
16

Chcę wysychają kilka modeli przesuwając wspólnych zakresów do modułu, coś jak:Współużytkowane lunety przez moduł?

module CommonScopes 
    extend ActiveSupport::Concern 

    module ClassMethods 
    scope :ordered_for_display, order("#{self.to_s.tableize}.rank asc") 
    end 
end 

chcę też tworzyć wspólnych specyfikacji, które umożliwiają testowanie modułu. Niestety, gdy próbuję włączyć zakres współdzielony do mojego modelu, otrzymuję:

undefined method `order' for CommonScopes::ClassMethods:Module 

Jakieś pomysły? Dzięki!

Odpowiedz

13

można użyć instance_eval

module CommonScopes 
    extend ActiveSupport::Concern 

    def self.included(klass) 
    klass.instance_eval do 
     scope :ordered_for_display, order("#{self.to_s.tableize}.rank asc") 
    end 
    end 
end 
+0

Nie sądzisz, że lambdas powinien być teraz preferowany? – mdemolin

+0

@mdemolin Wierzę, że wywołanie 'scope' bez lambda jest przestarzałe w szynach 4. – Gazler

+1

dokładnie to, co mówiłem :) (ale myślę, że jest to po prostu preferowana składnia na razie, i nie jest już przestarzała) – mdemolin

2

Ponieważ metoda scope nazywa się natychmiast, gdy moduł jest analizowany przez Ruby i nie jest dostępny z modułem CommonScopes ..

Ale można zastąpić rozmowy zakres metodą Klasa:

module CommonScopes 
    extend ActiveSupport::Concern 

    module ClassMethods 
    def ordered_for_display 
     order("#{self.to_s.tableize}.rank asc") 
    end 
    end 
end 
37

jak w szynach 4 scope syntax można po prostu użyć lambda, aby opóźnić wykonanie kodu (działa również w szynach 3):

module CommonScopes 
    extend ActiveSupport::Concern 

    included do 
    scope :ordered_for_display, -> { order("#{self.to_s.tableize}.rank asc") } 
    end 
end 
+0

To jest lepszy sposób. –

Powiązane problemy