0

У меня есть приложение, которое определяет некоторые модели. Я хочу расширить функциональность некоторых моделей (например, добавлять методы, добавлять ассоциации) из приложения в свой движок. Я попытался добавить модель в движок с тем же именем, что и модель моего приложения, и Rails автоматически объединит их, однако это не сработает.Расширение модели приложения в рельсовом двигателе

например: (модель приложения)

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 

has_many ассоциация не получает применительно к моей модели статей, когда я пытаюсь получить доступ к @ articles.metrics. Есть идеи ?

+0

Я думаю, что class_eval - это то, что вы ищете. У меня нет опыта с этим, но прочитайте это недавно: http://edgeguides.rubyonrails.org/engines.html # overriding-models-and-controllers – siax

+0

@Arun Kumar M, у вас есть ваша модель показателей, которая имеет отношение к статьям. Как выглядит ваша миграция, и ваша таблица Metric поддерживает статью article_id. Какое точное сообщение об ошибке вы получаете? –

+0

@ OlalekanSogunle Да, я делаю! Я дважды проверил это :) –

ответ

0

У вас есть ваша метрика модели have принадлежит к статьям.

Возможно, вы захотите предоставить другую сторону ассоциации, Metrics a belongs_to Articles, чтобы эта работа работала должным образом. Кроме того, убедитесь, что у вас есть перенос для хранения articles_id в таблице показателей. Все должно работать нормально.

+0

Да, я делаю! У меня есть ассоциация –

1

У вас есть правильная идея и они близки. Но ваша реализация немного не работает.

Как правило, ваш двигатель должен иметь no Знание вашего хост-приложения. Таким образом, ваш движок и хост-приложение остаются слабо связанными. Итак, классы в вашем движке должны не унаследовать от классов в вашем хост-приложении. (Кстати, ваш подход не работает, я считаю, из-за того, как рубин постоянно ищет, но это другое обсуждение.)

Вместо этого используйте included hook. В хост-приложение, вы делаете что-то вроде:

class Article < ActiveRecord:Base 
    include FooEngine::BarModule 

    def from_application 
     puts "application" 
    end 

    end 

И внутри двигателя:

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

Когда интерпретатор рубин идет включить FooEngine::BarModule в Article, он будет искать и запустить (если он найден) метод self.included в FooEngine::BarModule, переходящий в Article класс как base.

Затем вызовите class_eval на base (Article), который вновь открывает Article класс, так что вы можете добавить методы или любой другой обезьяны бизнес вы до (определить новые методы на месте, включают в себя или расширить другие модули , и т.д.).

В вашем примере вы вызываете метод has_many, который будет создавать различные методы ассоциации, предоставляемые has_many.

Если (а) вы добавите множество функций, связанных с метрикой, через ваш движок, (b) вы хотите, чтобы многие классы использовали связанные с метрикой функции, и (c) вы хотите некоторые из функций, которые могут варьироваться от класса к классу (включая включены), вы можете подумать о создании acts_as_having_metrics (или аналогичного). Когда вы идете по этому пути, это совершенно новый мир чудесного метапрограммирования.

Удачи.