Tôi nghĩ rằng tôi muốn tìm ra một cách khéo léo để mở rộng ApplicationController trong một gem Rails 3.x.Tôi có thể mở rộng ApplicationController bằng đá quý bằng cách nào?
Trong đá quý của tôi lib/my_namespace/my_controller.rb
, tôi đã có:
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
nhưng khi Gem được nạp, app/controllers/application_controller.rb
chưa được nạp, vì vậy nó không thành công:
/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)
Là một workaround, tôi đã định nghĩa ApplicationController trong đá quý của tôi lib/gem_namespace/application_controller.rb
là:
class ApplicationController < ActionController::Base
end
I giả định rằng mặc dù tôi đã định nghĩa nó ở đó, nó sẽ được định nghĩa lại trong ứng dụng Rails 3 của tôi là app/controllers/application_controller.rb
, như vậy cả hai bộ điều khiển trong ứng dụng mở rộng ApplicationController
và bộ điều khiển mở rộng MyNamespace::MyController
sẽ trực tiếp hoặc gián tiếp mở rộng ApplicationController được định nghĩa trong app/controllers/application_controller.rb
.
Tuy nhiên, chúng tôi nhận thấy rằng sau khi tải đá quý, bộ điều khiển mở rộng ApplicationController
không thể truy cập các phương thức được xác định trong app/controllers/application_controller.rb
. Ngoài ra, mô-đun ApplicationHelper
(app/helpers/application_helper.rb)
không còn được tải bởi các mô-đun trợ giúp khác.
Làm thế nào tôi có thể mở rộng ApplicationController
trong bộ điều khiển trong đá quý của tôi với mục đích xác định một before_filter
và after_filter
đến và sử dụng initialize
để truy cập tên của lớp để xác định lớp mô hình liên quan của nó sau đó có thể lưu trữ và sử dụng trong phương pháp của nó?
Cập nhật 2012/10/22:
Đây là những gì tôi đã đưa ra:
Trong 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
và trong 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
Tuyệt vời! Bao gồm một mô-đun thực sự là ý tưởng tốt nhất, sau đó. Cảm ơn sự giúp đỡ của bạn! –
[Cuộc trò chuyện liên quan trong Diễn đàn Rails] (https://web.archive.org/web/20130216193936/http://railsforum.com/viewtopic.php?pid=153813) –