Включить модуль в класс ruby ​​в инициализаторе Rails - PullRequest
1 голос
/ 12 октября 2011

Внутри инициализатора в Rails я пытаюсь включить модуль в рельсы Модель

User.send :include, Something

Это работает для первого запроса, но не для второго / третьего / и т.д. из-за перегрузки модели рельсов. Я пытался использовать ActionDispatch::Callbacks.to_prepare ( ActionDispatch :: Callbacks.to_prepare , я использую Rails 3.0.9)

ActionDispatch::Callbacks.to_prepare do
  User.send :include, Something
end

но я продолжаю получать ошибку NoMethod от пользовательского экземпляра, когда пытаюсь вызвать метод, определенный в модуле моего модуля, во втором / третьем / и т. Д. запрос.

У меня такой вопрос: есть ли способ надежно включить модуль в модель Rails в инициализаторе без каких-либо проблем при разработке?

Обновление: невозможно

Очевидно, что это невозможно сделать без промежуточного программного обеспечения. Если вы не согласны, добавьте ответ ниже. Это не было приемлемым решением для моего варианта использования, поэтому я даже не пробовал его. Удачи.

Редактировать: Обновленная информация об отладке

Я немного поигрался с ActionDispatch::Callbacks.to_prepare и заметил кое-что странное, когда положил это в свой инициализатор:

ActionDispatch::Callbacks.to_prepare do
  puts "to_prepare ==:#{User.object_id}"
end

и это в моем контроллере

puts "controller ==:#{User.object_id}"

по первому запросу я получаю это:

to_prepare ==: 2297196200
controller ==: 2297196200
to_prepare ==: 2297196200
to_prepare ==: 2324202920
to_prepare ==: 2318560780

по второму запросу я получаю это:

to_prepare ==: 2326823900
controller ==: 2326823900
to_prepare ==: 2317901920
to_prepare ==: 2326746040
to_prepare ==: 2314369160

Первое, что я заметил, было многократное обращение к to_prepare, что странно. Второе, что я заметил, было в первом запросе (который работает), то object_id непосредственно до и после вызова контроллера одинаковы, и их нет в последующих вызовах. Если бы кто-нибудь мог пролить свет на то, почему это происходит и как обойти это, это было бы очень ценно.

1 Ответ

1 голос
/ 13 октября 2011

Помогает ли использование хука config.after_initialize? Эта проблема связана со средой разработки из-за перезагрузки класса.

Единственное, что почти наверняка сработает, это внедрить ваш модуль через промежуточное ПО, хотя трудно понять, подходит ли это решение для всего, что вы делаете.

class AddYourModuleMiddleware
  def initialize(app)
    @app = app
  end

  def call(env)
    User.send(:include, YourModule) unless User < YourModule
    @app.call(env)
  end
end

Добавьте его в цепочку промежуточного ПО с помощью config.middleware.use AddYourModuleMiddleware или, альтернативно, поместив use AddYourMiddleware в начале ApplicationController.

...