Skip to content

Instantly share code, notes, and snippets.

@remvee
Created May 31, 2011 11:48
Show Gist options
  • Select an option

  • Save remvee/1000375 to your computer and use it in GitHub Desktop.

Select an option

Save remvee/1000375 to your computer and use it in GitHub Desktop.
inheritable rails views
# Make controller render and render partial fall back to ancestor
# controllers. Very hackish because it overrides rails private
# methods. Tested on rails 2.3.5 till 2.3.11.
module InheritableViewsHelper
def render_partial_with_inheritance(options = {})
if [String, Symbol, NilClass].find{|k| k === options[:partial]}
if options[:partial].include?('/')
render_partial_without_inheritance(options)
else
err = nil
controller.class.all_controller_paths.each do |path|
begin
return render_partial_without_inheritance(options.merge(:partial => "#{path}/#{options[:partial]}"))
rescue ActionView::MissingTemplate => ex
err ||= ex
end
end
raise err if err # re-raise first missing template error
end
else
render_partial_without_inheritance(options)
end
end
def self.included(other)
other.alias_method_chain :render_partial, :inheritance
other.memoize :render_partial_with_inheritance
end
end
ActionView::Base.send(:include, InheritableViewsHelper)
module InheritableViewsController
def default_template_with_inheritance(action_name = self.action_name)
self.class.all_controller_paths.each do |path|
template = self.view_paths.find_template("#{path}/#{action_name}", default_template_format) rescue nil
return template if template
end
default_template_without_inheritance(action_name) # fall back to normal behaviour
end
def self.included(other)
other.alias_method_chain :default_template, :inheritance
other.extend ClassMethods
end
module ClassMethods
# Insert path to inherit views from.
def inherit_views_from(*controller_names)
@inherited_controller_paths =
controller_names + (@inherited_controller_paths || [])
end
# List controller paths to get views from. The first being the
# most significant.
def all_controller_paths
[controller_path] +
(@inherited_controller_paths || []) +
(superclass.respond_to?(:all_controller_paths) && superclass.all_controller_paths || [])
end
end
end
ActionController::Base.send(:include, InheritableViewsController)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment