-
-
Save kneath/3914835 to your computer and use it in GitHub Desktop.
| # Given a controller in need of refactoring into multiple controllers, how | |
| # can I redirect to new controller actions based upon a feature flag? | |
| # | |
| # The current code "works" but doesn't exercise the controller action. | |
| # | |
| # Rails 2.3 or 3.0 methods accepted | |
| class BetterController | |
| def overview | |
| # .. a small amount of auth/permissions code | |
| end | |
| end | |
| class PoorlyNamedController | |
| def show | |
| if feature_flag? | |
| render :template => 'better/overview', :layout => 'new_layout' | |
| return | |
| end | |
| # ... tons of code here in a horrible method that needs to be split | |
| # into multiple methods across many controllers | |
| end | |
| end |
request.env["PATH_INFO"] = "/better/overview"Then return a response which has
[404, {"X-Cascade" => "pass"}, []]So what I have right now gets very close, unfortunately this app is in the middle of being both Rails 2.GitHub and Rails 3.GitHub, so it's hard to nail down what's going on.
# This is NOT to be meant for constant use, but is useful when you want
# to refactor a controller method into many controllers or into an action
# in another controller and want to do it staff-only for a while.
#
# controller - The controller Class you wish to render.
# action - The controller action Symbol you wish to render.
def render_in_controller(controller, action)
c = controller.new
c.request = @_request
c.response = @_response
c.params = params
c.send(action)
c.response.body
endThis works, except the response body is always nil. Calling render :template => 'better/overview' after calling render_in_controller works exactly as expected. I'd just love if it let the controller action figure out what to render.
# This is NOT to be meant for constant use, but is useful when you want
# to refactor a controller method into many controllers or into an action
# in another controller and want to do it staff-only for a while.
#
# controller - The controller Class you wish to render.
# action - The controller action Symbol you wish to render.
def render_in_controller(controller, action)
c = controller.new
c.request = @_request
c.response = @_response
c.params = params
c.process(action)
c.response.body
end def index
render :inline => render_in_controller(TestersController, 'index')
return
endThis works with 2.3: http://www.railsonwave.com/2008/10/25/how-to-call-a-controller-s-action-from-a-different-controller
I had to change Inflector to ActiveSupport::Inflector for it to work for me though.
Man that's reallly close. Still it's trying to call the same action name (not the action name I'm sending it). I added the action name into the .process call in request, response, options[:action] but still wants the same name.
Thanks a ton though, this is getting very close!
def internal_redirect_to(options={})
params.merge!(options)
request.env['action_controller.request.path_parameters']['controller'] = params[:controller]
request.env['action_controller.request.path_parameters']['action'] = params[:action]
(c = ActionController.const_get(ActiveSupport::Inflector.classify("#{params[:controller]}_controller")).new).process(request,response)
c.instance_variables.each{|v| self.instance_variable_set(v,c.instance_variable_get(v))}
end
render :controller => 'foo', :action => 'bar'?