问题
I want to add a filter to the ApplicationController
but I want to do it within my gem.
What I want to avoid is the following:
class ApplicationController < ActionController::Base
include MyGem
end
I do not want that. I don't want to have to include my module in the source code.
I am having issues though.
Here is the relevant code:
lib/correlation_id/controller_extension
module CorrelationId
module ControllerExtension
def self.included(klass)
klass.class_eval do
after_filter :pass_correlation_id
end
end
def pass_correlation_id
correlation_id = request.headers['Correlation-ID'] || SecureRandom.uuid
headers['Correlation-ID'] = correlation_id
end
end
end
ApplicationController.send :include, CorrelationId::ControllerExtension
lib/correlation_id.rb
require 'correlation_id/controller_extension'
module CorrelationId
end
Now, when I'm in the test/dummy
directory, which is a test rails app for my gem, I try to boot up the server using rails s
and I get the following error:
/correlation_id/lib/correlation_id/controller_extension.rb:17:in `<top (required)>': uninitialized constant ApplicationController (NameError)
I'm clearly having problems with referencing ApplicationController to monkey-patch it.
How would I manage this? I want my gem to be self-contained.
回答1:
The following code works. What I did was prematurely create ApplicationController
with the appropriate inheritance. Note, many people use the rails-api
gem, so I factored in them to ensure the fact that it would work.
Also, note: You must inherit from a class because otherwise ApplicationController
will be a usual class that doesn't understand what after_filter
is.
module CorrelationId
module ControllerExtension
def self.included(klass)
klass.class_eval do
after_filter :pass_correlation_id
end
end
def pass_correlation_id
correlation_id = request.headers['Correlation-ID'] || SecureRandom.uuid
headers['Correlation-ID'] = correlation_id
end
def self.base_controller_inheritance
if Gem::Specification.find_all_by_name('rails-api').any?
ActionController::API
else
ActionController::Base
end
end
end
end
class ApplicationController < CorrelationId::ControllerExtension.base_controller_inheritance
include CorrelationId::ControllerExtension
end
I imagine there might be a better way to check if they are using ActionController::API
and if so, please do share, but as of now, this seems like the most solid way to do it.
来源:https://stackoverflow.com/questions/24831530/how-to-keep-my-gem-self-contained-without-having-to-edit-any-core-source-rails