Rails 3.0 Engine - выполнение кода в ActionController - PullRequest
5 голосов
/ 12 августа 2010

Я модернизирую свой плагин Rails, чтобы он стал двигателем, который работает с последней версией 3.0RC1, и у меня возникли некоторые затруднения с поиском лучшего (и наиболее правильного) способа расширения ActionController. Я видел этот пост от DHH и этот вопрос здесь, на SO, но мой вопрос больше о том, как правильно вызвать код в ActionController.

Например, мне нужно вызвать следующее в контроллере моего двигателя:

class ApplicationController < ActionController::Base
  helper :all

  before_filter :require_one_user
  after_filter :store_location

  private
    def require_one_user
      # Code goes here
    end

    def store_location
      # Code goes here
    end
end

Я знаю, как правильно включить две мои частные функции, но я не могу найти способ заставить его правильно вызывать helper, before_filter и after_filter.

Я был бы очень признателен за некоторые ссылки или способ заставить эту работу. Я попытался назвать свой контроллер чем-то иным, чем ApplicationController, и заставить реально ApplicationController его расширить, но, похоже, это тоже не работает. Я действительно за любое решение, которое делает жизнь пользователя двигателя максимально простой. В идеале им не нужно было бы расширять мой класс, но они имели бы всю функциональность, встроенную в их собственные ApplicationController.

Ответы [ 2 ]

10 голосов
/ 16 августа 2010

Возможно, вы также захотите взглянуть на инициализаторы внутри вашего подкласса движка, поэтому вам не нужно включать помощники вида в ваш класс контроллера. И это даст вам контроль над порядком загрузки этих модулей.

Вот что я использовал:


module MyEngine  
  class Engine < Rails::Engine  
    initializer 'my_engine.helper' do |app|  
      ActionView::Base.send :include, MyEngineHelper  
    end  

    initializer 'my_engine.controller' do |app|  
      ActiveSupport.on_load(:action_controller) do  
         include MyEngineActionControllerExtension  
      end
    end
  end
end

Кроме того, еще одна опция для расширения контроллера действий использует модуль mixin. Это позволит вам использовать before_filter, after_filter и т.д ..


module MyEngineActionControllerExtension
  def self.included(base)
    base.send(:include, InstanceMethods) 
    base.before_filter :my_method_1
    base.after_filter :my_method_2
  end

  module InstanceMethods
   #...........
  end
end

Еще одна вещь ... если вы создаете каталоги rails по умолчанию на верхнем уровне вашего драгоценного камня, вам не нужно беспокоиться о необходимости помощников или контроллеров. Ваш подкласс движка имеет к ним доступ. Поэтому я добавляю свой контроллер приложений и вспомогательные расширения приложений здесь:

/myengine/app/helpers/myengine_application_helper_extension.rb
/myengine/app/controllers/my_engine_action_controller_extension.rb

Мне нравится эта настройка, потому что она похожа на application_controller и application_helper в вашем приложении rails. Опять же, это всего лишь личные предпочтения, но я стараюсь сохранить все, что напрямую связано с рельсами, например контроллеры, помощники и модели внутри / my_engine / app и все, что связано с плагином в целом, внутри / my_engine / lib

Ознакомьтесь с этим руководством Хосе Валима для получения дополнительной информации об инициализаторах: https://gist.github.com/e139fa787aa882c0aa9c (engine_name устарело сейчас, но большая часть этого документа выглядит актуальной)

3 голосов
/ 14 августа 2010

Итак, я наконец-то нашел решение и надеюсь, что оно поможет кому-то еще.

Вам нужно создать файл в вашем каталоге lib, потому что вы на самом деле собираетесь расширить класс. Я сделал myplugin/lib/extensions/action_controller_base.rb.

Затем внутри вашего myplugin/lib/myplugin.rb файла сделайте следующее:

require 'extensions/action_controller_base.rb'

Внутри myplugin/lib/extensions/action_controller_base.rb положить следующее:

require 'action_controller'  # Make sure ActionController::Base is defined

ActionController::Base.class_eval {
  private
    def my_method_1
      # Code Goes Here
    end

    def my_method_2
      # Code Goes Here
    end
}

ActionController::Base.instance_eval {
  helper_method :my_method_1, :my_method_2

  before_filter :my_method_1
  after_filter :my_method_2
}

Если вам нужны помощники вида, создайте их в каталоге myplugin/lib/helpers (или что-либо внутри lib, имя «помощники» также не имеет значения) и добавьте в конец myplugin/lib/extensions/action_controller_base.rb следующее: 1016 *

require 'helpers/helper_file_1'
require 'helpers/helper_file_2'

ActionView::Base.send :include, MyHelper1
ActionView::Base.send :include, MyHelper2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...