2009-10-05 8 views
5

J'ai un peu de code dans un plugin de style moteur qui comprend certains modèles. Dans mon application, je veux étendre l'un de ces modèles. J'ai réussi à ajouter des méthodes d'instance et de classe au modèle en question en incluant un module dans un initialiseur.Étendre le modèle dans le plugin avec "has_many" en utilisant un module

Cependant, je n'arrive pas à ajouter des associations, des rappels, etc. Je reçois une erreur «méthode introuvable».

/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 

Répondre

6

Je pense que cela devrait fonctionner

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 

L'ancien code est mauvaise cause la validation et l'association sont appelées lors du chargement du module, et ce module ne sait rien sur ActiveRecord. C'est un aspect général de Ruby, le code à l'intérieur de la classe ou des corps de modules est appelé directement lors du chargement. Tu ne veux pas ça. Pour contourner cela, vous pouvez utiliser la solution ci-dessus.

+0

Gotcha: Lorsque vous faites un 'recharger!' dans la console, la classe est rechargée mais comme le module (dans mon cas) est appelé depuis un initialiseur, le module n'est pas réappliqué. – Kris

+0

En outre plus pour le moment il semble que le code dans le module est inclus seulement en utilisant la console, quand le même code est appelé d'un contrôleur il échoue. Je voudrais poster un exemple de code mais une réponse ne semble pas correcte (ce n'est pas un forum après tout) ... – Kris

+0

CONTROLLER: render: text => User.new.respond_to? ('Hits') et return # => false CONSOLE: User.new.respond_to? ('hits') # => true PREEMPT: J'ai redémarré le serveur :) – Kris

14

Vous devriez être en mesure de le faire. Un peu plus concis à mon humble avis.

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

C'est totalement la bonne réponse. – kikito

4

Dans Rails 3, cela ressemble à un bon cas d'utilisation pour ActiveSupport de Concern:

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 

Voici les ActiveSupport::Concern docs et blog article les plus utiles à ce que j'ai trouvé.

Questions connexes