Moved layout exemption logic into the view

This commit is contained in:
Joshua Peek
2008-08-31 11:34:46 -05:00
parent 8eec694598
commit 086c3520c4
5 changed files with 63 additions and 121 deletions

View File

@@ -397,9 +397,6 @@ module ActionController #:nodoc:
# Returns the name of the action this controller is processing.
attr_accessor :action_name
# Templates that are exempt from layouts
@@exempt_from_layout = Set.new([/\.rjs$/])
class << self
# Factory for the standard create, process loop where the controller is discarded after processing.
def process(request, response) #:nodoc:
@@ -517,13 +514,7 @@ module ActionController #:nodoc:
protected :filter_parameters
end
# Don't render layouts for templates with the given extensions.
def exempt_from_layout(*extensions)
regexps = extensions.collect do |extension|
extension.is_a?(Regexp) ? extension : /\.#{Regexp.escape(extension.to_s)}$/
end
@@exempt_from_layout.merge regexps
end
delegate :exempt_from_layout, :to => 'ActionView::Base'
end
public
@@ -1241,12 +1232,7 @@ module ActionController #:nodoc:
end
def template_exists?(template_name = default_template_name)
@template.file_exists?(template_name)
end
def template_exempt_from_layout?(template_name = default_template_name)
template_name = @template.pick_template(template_name).to_s if @template
@@exempt_from_layout.any? { |ext| template_name =~ ext }
@template.send(:_pick_template, template_name) ? true : false
rescue ActionView::MissingTemplate
false
end

View File

@@ -238,7 +238,7 @@ module ActionController #:nodoc:
private
def candidate_for_layout?(options)
options.values_at(:text, :xml, :json, :file, :inline, :partial, :nothing, :update).compact.empty? &&
!template_exempt_from_layout?(options[:template] || default_template_name(options[:action]))
!@template.send(:_exempt_from_layout?, options[:template] || default_template_name(options[:action]))
end
def pick_layout(options)
@@ -247,7 +247,7 @@ module ActionController #:nodoc:
when FalseClass
nil
when NilClass, TrueClass
active_layout if action_has_layout? && !template_exempt_from_layout?(default_template_name)
active_layout if action_has_layout? && !@template.send(:_exempt_from_layout?, default_template_name)
else
active_layout(layout)
end
@@ -272,7 +272,9 @@ module ActionController #:nodoc:
end
def layout_directory?(layout_name)
@template.file_exists?("#{File.join('layouts', layout_name)}.#{@template.template_format}")
@template.send(:_pick_template, "#{File.join('layouts', layout_name)}.#{@template.template_format}") ? true : false
rescue ActionView::MissingTemplate
false
end
end
end

View File

@@ -184,6 +184,17 @@ module ActionView #:nodoc:
"deprecated and has no effect. Please remove it from your config files.", caller)
end
# Templates that are exempt from layouts
@@exempt_from_layout = Set.new([/\.rjs$/])
# Don't render layouts for templates with the given extensions.
def self.exempt_from_layout(*extensions)
regexps = extensions.collect do |extension|
extension.is_a?(Regexp) ? extension : /\.#{Regexp.escape(extension.to_s)}$/
end
@@exempt_from_layout.merge(regexps)
end
# Specify whether RJS responses should be wrapped in a try/catch block
# that alert()s the caught exception (and then re-raises it).
@@debug_rjs = false
@@ -252,7 +263,7 @@ module ActionView #:nodoc:
ActiveSupport::Deprecation.warn("use_full_path option has been deprecated and has no affect.", caller)
end
pick_template(options[:file]).render_template(self, options[:locals])
_pick_template(options[:file]).render_template(self, options[:locals])
elsif options[:partial]
render_partial(options)
elsif options[:inline]
@@ -276,57 +287,6 @@ module ActionView #:nodoc:
end
end
def file_exists?(template_path)
pick_template(template_path) ? true : false
rescue MissingTemplate
false
end
# Gets the extension for an existing template with the given template_path.
# Returns the format with the extension if that template exists.
#
# pick_template('users/show')
# # => 'users/show.html.erb'
#
# pick_template('users/legacy')
# # => 'users/legacy.rhtml'
#
def pick_template(template_path)
return template_path if template_path.respond_to?(:render)
path = template_path.sub(/^\//, '')
if m = path.match(/(.*)\.(\w+)$/)
template_file_name, template_file_extension = m[1], m[2]
else
template_file_name = path
end
# OPTIMIZE: Checks to lookup template in view path
if template = self.view_paths["#{template_file_name}.#{template_format}"]
template
elsif template = self.view_paths[template_file_name]
template
elsif _first_render && template = self.view_paths["#{template_file_name}.#{_first_render.format_and_extension}"]
template
elsif template_format == :js && template = self.view_paths["#{template_file_name}.html"]
@template_format = :html
template
else
template = Template.new(template_path, view_paths)
if self.class.warn_cache_misses && logger
logger.debug "[PERFORMANCE] Rendering a template that was " +
"not found in view path. Templates outside the view path are " +
"not cached and result in expensive disk operations. Move this " +
"file into #{view_paths.join(':')} or add the folder to your " +
"view path list"
end
template
end
end
memoize :pick_template
private
attr_accessor :_first_render, :_last_render
@@ -351,6 +311,49 @@ module ActionView #:nodoc:
end
end
def _pick_template(template_path)
return template_path if template_path.respond_to?(:render)
path = template_path.sub(/^\//, '')
if m = path.match(/(.*)\.(\w+)$/)
template_file_name, template_file_extension = m[1], m[2]
else
template_file_name = path
end
# OPTIMIZE: Checks to lookup template in view path
if template = self.view_paths["#{template_file_name}.#{template_format}"]
template
elsif template = self.view_paths[template_file_name]
template
elsif _first_render && template = self.view_paths["#{template_file_name}.#{_first_render.format_and_extension}"]
template
elsif template_format == :js && template = self.view_paths["#{template_file_name}.html"]
@template_format = :html
template
else
template = Template.new(template_path, view_paths)
if self.class.warn_cache_misses && logger
logger.debug "[PERFORMANCE] Rendering a template that was " +
"not found in view path. Templates outside the view path are " +
"not cached and result in expensive disk operations. Move this " +
"file into #{view_paths.join(':')} or add the folder to your " +
"view path list"
end
template
end
end
memoize :_pick_template
def _exempt_from_layout?(template_path) #:nodoc:
template = _pick_template(template_path).to_s
@@exempt_from_layout.any? { |ext| template =~ ext }
rescue ActionView::MissingTemplate
return false
end
def _render_with_layout(options, local_assigns, &block) #:nodoc:
partial_layout = options.delete(:layout)

View File

@@ -196,7 +196,7 @@ module ActionView
path = "_#{partial_path}"
end
pick_template(path)
_pick_template(path)
end
memoize :_pick_partial_template
end

View File

@@ -79,53 +79,6 @@ class LayoutAutoDiscoveryTest < Test::Unit::TestCase
end
end
class ExemptFromLayoutTest < Test::Unit::TestCase
def setup
@controller = LayoutTest.new
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
end
def test_rjs_exempt_from_layout
assert @controller.send!(:template_exempt_from_layout?, 'test.rjs')
end
def test_rhtml_and_rxml_not_exempt_from_layout
assert !@controller.send!(:template_exempt_from_layout?, 'test.rhtml')
assert !@controller.send!(:template_exempt_from_layout?, 'test.rxml')
end
def test_other_extension_not_exempt_from_layout
assert !@controller.send!(:template_exempt_from_layout?, 'test.random')
end
def test_add_extension_to_exempt_from_layout
['rpdf', :rpdf].each do |ext|
assert_nothing_raised do
ActionController::Base.exempt_from_layout ext
end
assert @controller.send!(:template_exempt_from_layout?, "test.#{ext}")
end
end
def test_add_regexp_to_exempt_from_layout
ActionController::Base.exempt_from_layout /\.rdoc/
assert @controller.send!(:template_exempt_from_layout?, 'test.rdoc')
end
def test_rhtml_exempt_from_layout_status_should_prevent_layout_render
ActionController::Base.exempt_from_layout :rhtml
assert @controller.send!(:template_exempt_from_layout?, 'test.rhtml')
assert @controller.send!(:template_exempt_from_layout?, 'hello.rhtml')
get :hello
assert_equal 'hello.rhtml', @response.body
ActionController::Base.exempt_from_layout.delete(/\.rhtml$/)
end
end
class DefaultLayoutController < LayoutTest
end
@@ -179,8 +132,6 @@ class LayoutSetInResponseTest < Test::Unit::TestCase
ActionController::Base.exempt_from_layout :rhtml
@controller = RenderWithTemplateOptionController.new
assert @controller.send(:template_exempt_from_layout?, 'alt/hello.rhtml')
get :hello
assert_equal "alt/hello.rhtml", @response.body.strip