After not being able to find a resource for the order of the current Rails4 Controller Callbacks, I ran all the callbacks to see what ran when.
I made an action with the same name as the filter, and had it output to logger.error.
class HomeController < ApplicationController
after_action :after_action
before_action :before_action
append_after_action :append_after_action
append_before_action :append_before_action
prepend_after_action :prepend_after_action
prepend_before_action :prepend_before_action
around_action :around_action
prepend_around_action :prepend_around_action
append_around_action :append_around_action
def after_action
logger.error("after_action #{Time.now}")
end
def append_after_action
logger.error("append_after_action #{Time.now}")
end
def append_around_action
logger.error("append_around_action #{Time.now}")
yield
end
def append_before_action
logger.error("append_before_action #{Time.now}")
end
def around_action
logger.error("around_action #{Time.now}")
yield
end
def before_action
logger.error("before_action #{Time.now}")
end
def prepend_after_action
logger.error("prepend_after_action #{Time.now}")
end
def prepend_around_action
logger.error("prepend_around_action #{Time.now}")
yield
end
def prepend_before_action
logger.error("prepend_before_action #{Time.now}")
end
end
The output looked like this:
Started GET "/home/index" for 127.0.0.1 at 2014-03-12 15:41:02 -0700
Processing by HomeController#index as HTML
prepend_around_action 2014-03-12 15:41:02 -0700
prepend_before_action 2014-03-12 15:41:02 -0700
before_action 2014-03-12 15:41:02 -0700
append_before_action 2014-03-12 15:41:02 -0700
around_action 2014-03-12 15:41:02 -0700
append_around_action 2014-03-12 15:41:02 -0700
Rendered layouts/application.html.erb (0.5ms)
Rendered home/index.html.erb (0.5ms)
append_after_action 2014-03-12 15:41:02 -0700
after_action 2014-03-12 15:41:02 -0700
prepend_after_action 2014-03-12 15:41:02 -0700
Completed 200 OK in 12ms (Views: 9.8ms | ActiveRecord: 0.0ms)
Well balls, I needed something that ran after all my code but ran before I rendered the view, and none of the filters seemed to do that.
I found a type of answer on StackOverflow.
It called for injecting your own render action, and setting up a before_action
filter that would set an instance variable to true for the action(s) you want to have your filter run on.
before_action :set_global_modal, only: [:index]
def render(*args)
build_global_modal if @do_global
super
end
def set_global_modal
@do_global = true
end
It worked good for my situation. The only gotcha was that the monkeypatched render method will run for all of your renders in that controller. So just be sure to only run it in the controller you need it for and not have it in your ApplicationController, or every action in your entire program is going get routed through there.
If somebody has a better way to do this, let me know - cause this does seem kinda broken.