2009-10-05 5 views
5

Tengo un código en un complemento de motor que incluye algunos modelos. En mi aplicación quiero extender uno de estos modelos. He logrado agregar métodos de instancia y clase al modelo en cuestión al incluir un módulo dentro de un inicializador.Extienda el modelo en el complemento con "has_many" usando un módulo

Sin embargo, parece que no puedo agregar asociaciones, devoluciones de llamada, etc. Obtengo un error de 'método no encontrado'.

/libs/qwerty/core.rb

module Qwerty 
    module Core 
    module Extensions 

     module User 
     # Instance Methods Go Here 

     # Class Methods 
     module ClassMethods 
      has_many :hits, :uniq => true # no method found 

      before_validation_on_create :generate_code # no method found 

      def something # works! 
      "something" 
      end 
     end 

     def self.included(base) 
      base.extend(ClassMethods) 
     end 
     end 
    end 
    end 
end 

/initializers/qwerty.rb

require 'qwerty/core/user' 

User.send :include, Qwerty::Core::Extensions::User 

Respuesta

6

Creo que esto debería funcionar

module Qwerty 
    module Core 
    module Extensions 
     module User 
     # Instance Methods Go Here 

     # Class Methods 
     module ClassMethods 
      def relate 
      has_many :hits, :uniq => true # no method found 

      before_validation_on_create :generate_code # no method found 
      end 

      def something # works! 
      "something" 
      end 
     end 

     def self.included(base) 
      base.extend(ClassMethods).relate 
     end 
     end 
    end 
    end 
end 

El código anterior es causa equivocada la validación y la asociación son requeridas para la carga del módulo, y este módulo no sabe nada sobre ActiveRecord. Ese es un aspecto general de Ruby, el código dentro de la clase o cuerpos de módulo se llama directamente cuando se carga. No quieres eso. Para evitarlo, puede usar la solución anterior.

+0

Gotcha: ¡Cuando se hace una 'recarga'! en la consola, la clase se vuelve a cargar, pero como el módulo (en mi caso) se llama desde un inicializador, el módulo no se vuelve a aplicar. – Kris

+0

Además, en este momento parece que el código en el módulo solo se incluye al usar la consola, cuando se llama al mismo código desde un controlador falla. Me gustaría publicar un ejemplo de código, pero una respuesta no parece correcta (después de todo, no es un foro) ... – Kris

+0

CONTROLLER: render: text => User.new.respond_to? ('Hits') y return # => falso CONSOLA: User.new.respond_to? ('hits') # => true PREEMPT: He reiniciado el servidor :) – Kris

14

Debería poder hacer esto. Un poco más conciso en mi humilde opinión.

module Qwerty::Core::Extensions::User 
    def self.included(base) 
    base.class_eval do 
     has_many :hits, :uniq => true 
     before_validation_on_create :generate_code 
    end 
    end 
end 
+0

Esta es la respuesta correcta. – kikito

4

En Rails 3, esto suena como un buen caso de uso para ActiveSupport :: preocupación:

module Qwerty::Core::Extensions::User 

    extend ActiveSupport::Concern 

    included do 
    has_many :hits, :uniq => true 
    before_validation_on_create :generate_code 
    end 
end 

class User 
    include Querty::Core::Extensions::User 
    # ... 
end 

Aquí están los ActiveSupport::Concern docs y el más útil blog article en él he encontrado.

Cuestiones relacionadas