Rails расширяет модели без изменения базового файла

#ruby-on-rails

#ruby-on-rails

Вопрос:

У меня есть два приложения Rails 2.3, мы будем называть их admin и frontend. В admin у меня есть все мои модели, указанные в app/models . В интерфейсе у меня есть символические ссылки на эти модели. Я хотел бы добавить к модели методы, специфичные для интерфейса, которые отображаются только для приложения интерфейса, а не для приложения администратора.

Сначала я попытался просто добавить config.autoload_paths = "#{RAILS_ROOT}/app/augments/address.rb" с:

 class Address
  def hello
    "hello world"
  end
end
  

Но это просто не было загружено. Вызовы Address.first.hello будут встречены undefined method 'hello' .

Если мне потребуется файл, который делает это:

 Address.class_eval do
  def hello
    "hello world"
  end
end
  

Он загружается один раз, и при первом попадании в разработку он работает, но при всех последующих перезагрузках он терпит неудачу. Это связано с config.cache_classes = false в разработке.

Полурабочее решение — запустить это из ApplicationController:

 class ApplicationController < ActionController::Base
  Address.class_eval do
    def hello
      "hello world"
    end
  end
end
  

Который перезагружается и работает каждый раз в dev andprod, но не работает для script / runner или script / console. (Если это единственное решение, я уверен, что мы могли бы извлечь это в модуль и include ModelExtensions в ApplicationController.)

Есть ли что-то, что я могу добавить в environment.rb или инициализатор, который будет перезагружаться каждый раз при разработке?

Ответ №1:

Чтобы расширить свой класс, вы должны использовать module и включить его в свою модель. Что-то вроде этого:

 module  Address
  def hello
    "hello world"
  end
end
  

Это старая, но всегда интересная статья по этому аргументу: http://weblog.jamisbuck.org/2007/1/17/concerns-in-activerecord

Чтобы включить модуль только во внешний интерфейс, вы должны проверить, существует ли модуль с:

 Class A
  include Address if defined? Address
end
  

Комментарии:

1. Да, но я не хочу на самом деле добавлять include AddressModelExtensions в мой address.rb, потому что это не сработало бы для моего приложения admin , поскольку модуль находится только в интерфейсе

2. ммм … да, я понял. Просто вопрос, почему вы должны использовать два разных приложения?

3. Разделение кода и загрузка. Кроме того, они будут отображаться отдельно в NewRelic, и мы потенциально можем масштабировать их отдельно.

4. Возможно, вам нужно выполнить поиск условного включения в вашей модели. Что-то вроде включить адрес, если Address.nil? . Я знаю, что это не работает … но что-то подобное

5. Вы можете проверить обновленный ответ. Я добавил определенный? и теперь должно сработать.