Gar*_*ver 18 gem ruby-on-rails applicationcontroller ruby-on-rails-3 load-order
我想我会想出一个灵活的方法来扩展Rails 3.x gem中的ApplicationController.
在我的宝石中lib/my_namespace/my_controller.rb,我有:
class MyNamespace::MyController < ApplicationController
before_filter :some_method
after_filter :another_method
def initialize
# getting classname of the subclass to use for lookup of the associated model, etc.
# and storing the model_class in an instance variable
# ...
end
# define :some_method, :another_method, etc.
# ...
private
attr_accessor :subclass_defined_during_initialize # etc.
# etc.
end
Run Code Online (Sandbox Code Playgroud)
但是当加载Gem时,app/controllers/application_controller.rb尚未加载,因此失败:
/path/to/rvm/gemset/gems/activesupport-3.2.6/lib/active_support/dependencies.rb:251:
in `require': cannot load such file -- my_gem_name/application_controller (LoadError)
Run Code Online (Sandbox Code Playgroud)
作为一种解决方法,我在我的gem中定义了ApplicationController lib/gem_namespace/application_controller.rb:
class ApplicationController < ActionController::Base
end
Run Code Online (Sandbox Code Playgroud)
我假设即使我在那里定义它,它也会在我的Rails 3应用程序中重新定义app/controllers/application_controller.rb,这样扩展的应用程序中的两个控制器ApplicationController和扩展的控制器MyNamespace::MyController将直接或间接扩展定义的ApplicationController app/controllers/application_controller.rb.
但是,我们注意到在加载gem之后,扩展的控制器ApplicationController无法访问定义的方法app/controllers/application_controller.rb.此外,该ApplicationHelper (app/helpers/application_helper.rb)模块不再被其他辅助模块加载.
我如何ApplicationController在gem中的控制器中进行扩展,以便定义a before_filter和after_filterto并使用initialize访问类的名称来确定它可以在其方法中存储和使用的关联模型的类?
2012/10/22更新:
这是我想出的:
在lib/your_gem_name/railtie.rb:
module YourGemsModuleName
class Railtie < Rails::Railtie
initializer "your_gem_name.action_controller" do
ActiveSupport.on_load(:action_controller) do
puts "Extending #{self} with YourGemsModuleName::Controller"
# ActionController::Base gets a method that allows controllers to include the new behavior
include YourGemsModuleName::Controller # ActiveSupport::Concern
end
end
end
Run Code Online (Sandbox Code Playgroud)
并在lib/your_gem_name/controller.rb:
module YourGemsModuleName
module Controller
extend ActiveSupport::Concern
# note: don't specify included or ClassMethods if unused
included do
# anything you would want to do in every controller, for example: add a class attribute
class_attribute :class_attribute_available_on_every_controller, instance_writer: false
end
module ClassMethods
# notice: no self.method_name here, because this is being extended because ActiveSupport::Concern was extended
def make_this_controller_fantastic
before_filter :some_instance_method_available_on_every_controller # to be available on every controller
after_filter :another_instance_method_available_on_every_controller # to be available on every controller
include FantasticStuff
end
end
# instance methods to go on every controller go here
def some_instance_method_available_on_every_controller
puts "a method available on every controller!"
end
def another_instance_method_available_on_every_controller
puts "another method available on every controller!"
end
module FantasticStuff
extend ActiveSupport::Concern
# note: don't specify included or ClassMethods if unused
included do
class_attribute :class_attribute_only_available_on_fantastic_controllers, instance_writer: false
end
module ClassMethods
# class methods available only if make_this_controller_fantastic is specified in the controller
def some_fanastic_class_method
put "a fantastic class method!"
end
end
# instance methods available only if make_this_controller_fantastic is specified in the controller
def some_fantastic_instance_method
puts "a fantastic instance method!"
end
def another_fantastic_instance_method
puts "another fantastic instance method!"
end
end
end
end
Run Code Online (Sandbox Code Playgroud)
对于这种特定类型的功能,我建议在gem中创建一个模块,并在Application Controller中包含该模块
class ApplicationController < ActionController::Base
include MyCoolModule
end
Run Code Online (Sandbox Code Playgroud)
要在过滤器之前添加等(将其添加到您的模块)
def self.included(base)
base.send(:before_filter, my_method)
end
Run Code Online (Sandbox Code Playgroud)
更新:你可以做到base.before_filter :my_method更清洁.
| 归档时间: |
|
| 查看次数: |
11249 次 |
| 最近记录: |