2011-09-06 17 views
16

quiero secar varios modelos desplazando ámbitos compartidos en un módulo, algo así como:¿Ámbitos compartidos a través del módulo?

module CommonScopes 
    extend ActiveSupport::Concern 

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

también quiero crear especificaciones comunes que ponen a prueba el módulo. Desafortunadamente cuando trato de incluir el alcance compartido en mi modelo me sale:

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

¿Alguna idea? ¡Gracias!

Respuesta

13

puede utilizar 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

¿No crees que las lambdas deberían preferirse ahora? – mdemolin

+0

@mdemolin Creo que llamar 'scope' sin un lambda está obsoleto en los rieles 4. – Gazler

+1

exactamente lo que estaba diciendo :) (pero creo que es la sintaxis preferida por ahora, y no desaprobada aún) – mdemolin

2

Debido a que su método scope se llama inmediatamente cuando su módulo se analiza por Ruby y que no es accesible desde su módulo CommonScopes ..

Pero puede reemplazar su llamada alcance por un método de la clase:

module CommonScopes 
    extend ActiveSupport::Concern 

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

Al igual que en los carriles 4 scope syntax simplemente puede utilizar una lambda para retrasar la ejecución del código (también funciona en rieles 3):

module CommonScopes 
    extend ActiveSupport::Concern 

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

Es mejor manera. –

Cuestiones relacionadas