Skip to content

Instantly share code, notes, and snippets.

@dblack
Created January 18, 2009 19:05
Show Gist options
  • Save dblack/48742 to your computer and use it in GitHub Desktop.
Save dblack/48742 to your computer and use it in GitHub Desktop.
# To use this, put it in per_action_middleware.rb,
# add PerActionMiddleware to the class_eval at the end
# of base.rb, and add this line to action_controller.rb:
#
# autoload :PerActionMiddleware, 'action_controller/per_action_middleware'
#
# I don't like the dummy module thing but at least this seems to do
# the trick on the initializations.
module PerActionMiddleware
end
module ActionController
class Base
class << self
alias _call call
def call(env)
action = env["rack.routing_args"]["action"]
@@app ||= prepare_mw_stack(action)
@@app.call(env)
end
def middles
@middles ||= []
end
def middle(app, *options)
options = options.pop || {}
middles.push(app)
Array(options[:only]).each {|action| middleware_whitelist[app] << action.to_sym }
Array(options[:except]).each {|action| middleware_blacklist[app] << action.to_sym }
end
def middleware_whitelist
@middleware_whitelist ||= Hash.new {|h,k| h[k] = [] }
end
def middleware_blacklist
@middleware_blacklist ||= Hash.new {|h,k| h[k] = [] }
end
def can_use_middleware?(mw, action)
return true if middleware_whitelist[mw].include?(action.to_sym)
return false if middleware_blacklist[mw].include?(action.to_sym)
return true if middleware_whitelist[mw].empty?
end
def prepare_mw_stack(action)
@@middle_stack ||= {}
return @@app if @app
@@middle_stack[action] ||= MiddlewareStack.new do |middleware|
self.middles.each do |mw|
middleware.use(mw) if can_use_middleware?(mw, action)
end
end
@@middle_stack[action].build(lambda {|env| _call(env)})
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment