0

J'ai une application qui définit certains modèles. Je veux étendre la fonctionnalité de certains modèles (par exemple ajouter des méthodes, ajouter des associations) de l'application à mon moteur. J'ai essayé d'ajouter un modèle dans le moteur avec le même nom que le modèle de mon application et Rails les fusionnera automatiquement, mais cela ne fonctionne pas.Extension du modèle d'application dans les rails moteur

par exemple: (modèle de demande)

class Article < ActiveRecord:Base 
def from_application 
    puts "application" 
end 
end 

(Inside my Engine) 
module MyEngine 
    class Article < ::Article 
    has_many :metrics, :class_name => 'Metric' 
    end 
end 

association has_many ne s'appliquer à mes articles modèle lorsque je tente d'accéder @ articles.metrics. Des idées ?

+0

Je pense que class_eval est ce que vous cherchez. Je n'ai aucune expérience avec cela, mais lisez ceci récemment: http://edgeguides.rubyonrails.org/engines.html # overriding-models-and-controllers – siax

+0

@Arun Kumar M, avez-vous votre modèle de métrique avoir une association belongs_to avec Articles. A quoi ressemble votre migration et votre table Metric contient-elle l'article_id. Quel est le message d'erreur exact que vous obtenez? –

+0

@OlalekanSogunle Oui, je le fais! J'ai vérifié deux fois :) –

Répondre

0

Avez-vous votre modèle de métrique avoir une association belongs_to avec Articles.

Vous pouvez donner à l'autre côté de l'association, Metrics a belongs_to Articles pour que cela fonctionne correctement. Assurez-vous également d'avoir une migration pour contenir articles_id sur la table de métriques. Tout devrait bien fonctionner.

+0

Oui, je le fais! J'ai l'association –

1

Vous avez la bonne idée et êtes proche. Mais votre implémentation est un peu éteinte.

En règle générale, votre moteur doit avoir aucune connaissance de votre application hôte. De cette façon, votre moteur et l'application hôte restent lâchement couplés. Par conséquent, les classes de votre moteur doivent et non hériter des classes de votre application hôte. (BTW, votre approche ne fonctionne pas, je crois, à cause de la façon dont ruby ​​fait des recherches constantes, mais c'est une discussion différente.)

À la place, utilisez le included hook. Dans l'application hôte, vous faites quelque chose comme:

class Article < ActiveRecord:Base 
    include FooEngine::BarModule 

    def from_application 
     puts "application" 
    end 

    end 

Et à l'intérieur du moteur:

module FooEngine 
    module BarModule 
     def self.included(base) 
     base.class_eval do 
      has_many :metrics, :class_name => 'Metric' 
     end 
     end 
    end 
    end 

Lorsque l'interpréteur Ruby va inclure FooEngine::BarModule dans Article, il va chercher et exécuter (si trouvé) la méthode self.included dans FooEngine::BarModule, en passant dans la classe Article comme base.

Vous appelez ensuite class_eval sur la base (Article) qui RÉOUVERTURE la classe Article afin que vous puissiez ajouter des méthodes ou quelqu'affaires singe que vous êtes à (définir de nouvelles méthodes in situ, d'inclure ou d'autres modules prolongez , etc.).

Dans votre exemple, vous appelez la méthode has_many, qui créera les diverses méthodes d'association fournies par has_many. Si (a) vous allez ajouter beaucoup de fonctionnalités liées aux métriques via votre moteur, (b) vous voulez que beaucoup de classes utilisent les fonctionnalités liées aux métriques, et (c) vous voulez certaines des fonctionnalités à varier d'une classe à l'autre (où inclus), vous pourriez envisager de créer un acts_as_having_metrics (ou similaire). Une fois que vous êtes sur cette voie, c'est un tout nouveau monde de métaprogrammation merveilleuse.

Bonne chance.