Rails 3, find current view while in the layout
I have a scenario where I would like to have the name of the view that will be rendering while I'm in the layout file. I can find solutions to find which layout will be wrapping the current view from the view, but not the other wa开发者_如何学Pythony around. How can I find which view is rendering?
In Rails 3.0.3, I was able to see the name of the controller and action using controller_name and action_name. But those are not publicly documented (at least the action name) so I wouldn't depend on it long-term.
It might be better to monkey patch template render. In an initializer:
module ActionView::Rendering
alias_method :_render_template_original, :_render_template
def _render_template(template, layout = nil, options = {})
@last_template = template
_render_template_original(template, layout, options)
end
end
Then use @last_template in your layout.
The following solution works in Rails 3.1. Place this code in an initializer. (The rails 3.0.3 answer is not working any more in Rails 3.1)
This enables an @active_template variable for every controller. This is an instance of an ActionViewTemplate class.
The method active_template_virtual_path method returns the template as a name in the following form "controller/action"
class ActionController::Base
attr_accessor :active_template
def active_template_virtual_path
self.active_template.virtual_path if self.active_template
end
end
class ActionView::TemplateRenderer
alias_method :_render_template_original, :render_template
def render_template(template, layout_name = nil, locals = {})
@view.controller.active_template = template if @view.controller
result = _render_template_original( template, layout_name, locals)
@view.controller.active_template = nil if @view.controller
return result
end
end
I like the following approach, as you can reduce code size a good bit in a lot of cases. Include this in your application_controller.rb:
before_filter :instantiate_controller_and_action_names
caches_action :instantiate_controller_and_action_names
def instantiate_controller_and_action_names
@current_action = action_name
@current_controller = controller_name
end
Then, if your views correspond to an action, you just do:
dosomething if @current_action == 'new'
精彩评论