mirror of https://github.com/rails/rails
Ensure the template format is always passed to the template finder. Now we can cleanup some nasty stuff.
This commit is contained in:
parent
f5b7f0911b
commit
858a420ce1
|
@ -570,7 +570,9 @@ module ActionMailer #:nodoc:
|
|||
end
|
||||
|
||||
def candidate_for_layout?(options)
|
||||
!@template.send(:_exempt_from_layout?, default_template_name)
|
||||
!self.view_paths.find_template(default_template_name, default_template_format).exempt_from_layout?
|
||||
rescue ActionView::MissingTemplate
|
||||
return true
|
||||
end
|
||||
|
||||
def template_root
|
||||
|
|
|
@ -10,11 +10,14 @@ require 'action_mailer/test_case'
|
|||
ActiveSupport::Deprecation.debug = true
|
||||
|
||||
# Bogus template processors
|
||||
ActionView::Template.register_template_handler :haml, lambda { |template| "Look its HAML!" }
|
||||
ActionView::Template.register_template_handler :bak, lambda { |template| "Lame backup" }
|
||||
ActionView::Template.register_template_handler :haml, lambda { |template| "Look its HAML!".inspect }
|
||||
ActionView::Template.register_template_handler :bak, lambda { |template| "Lame backup".inspect }
|
||||
|
||||
$:.unshift "#{File.dirname(__FILE__)}/fixtures/helpers"
|
||||
ActionMailer::Base.template_root = "#{File.dirname(__FILE__)}/fixtures"
|
||||
|
||||
FIXTURE_LOAD_PATH = File.join(File.dirname(__FILE__), 'fixtures')
|
||||
ActionMailer::Base.template_root = FIXTURE_LOAD_PATH
|
||||
ActionMailer::Base.template_root.load
|
||||
|
||||
class MockSMTP
|
||||
def self.deliveries
|
||||
|
|
|
@ -502,7 +502,7 @@ module ActionController #:nodoc:
|
|||
protected :filter_parameters
|
||||
end
|
||||
|
||||
delegate :exempt_from_layout, :to => 'ActionView::Base'
|
||||
delegate :exempt_from_layout, :to => 'ActionView::Template'
|
||||
end
|
||||
|
||||
public
|
||||
|
@ -860,7 +860,7 @@ module ActionController #:nodoc:
|
|||
raise DoubleRenderError, "Can only render or redirect once per action" if performed?
|
||||
|
||||
if options.nil?
|
||||
return render(:file => default_template_name, :layout => true)
|
||||
return render(:file => default_template, :layout => true)
|
||||
elsif !extra_options.is_a?(Hash)
|
||||
raise RenderError, "You called render with invalid options : #{options.inspect}, #{extra_options.inspect}"
|
||||
else
|
||||
|
@ -898,7 +898,7 @@ module ActionController #:nodoc:
|
|||
render_for_text(@template.render(options.merge(:layout => layout)), options[:status])
|
||||
|
||||
elsif action_name = options[:action]
|
||||
render_for_file(default_template_name(action_name.to_s), options[:status], layout)
|
||||
render_for_file(default_template(action_name.to_s), options[:status], layout)
|
||||
|
||||
elsif xml = options[:xml]
|
||||
response.content_type ||= Mime::XML
|
||||
|
@ -933,7 +933,7 @@ module ActionController #:nodoc:
|
|||
render_for_text(nil, options[:status])
|
||||
|
||||
else
|
||||
render_for_file(default_template_name, options[:status], layout)
|
||||
render_for_file(default_template, options[:status], layout)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1164,7 +1164,8 @@ module ActionController #:nodoc:
|
|||
|
||||
private
|
||||
def render_for_file(template_path, status = nil, layout = nil, locals = {}) #:nodoc:
|
||||
logger.info("Rendering #{template_path}" + (status ? " (#{status})" : '')) if logger
|
||||
path = template_path.respond_to?(:path_without_format_and_extension) ? template_path.path_without_format_and_extension : template_path
|
||||
logger.info("Rendering #{path}" + (status ? " (#{status})" : '')) if logger
|
||||
render_for_text @template.render(:file => template_path, :locals => locals, :layout => layout), status
|
||||
end
|
||||
|
||||
|
@ -1241,10 +1242,17 @@ module ActionController #:nodoc:
|
|||
elsif respond_to? :method_missing
|
||||
method_missing action_name
|
||||
default_render unless performed?
|
||||
elsif template_exists?
|
||||
default_render
|
||||
else
|
||||
raise UnknownAction, "No action responded to #{action_name}. Actions: #{action_methods.sort.to_sentence}", caller
|
||||
begin
|
||||
default_render
|
||||
rescue ActionView::MissingTemplate => e
|
||||
# Was the implicit template missing, or was it another template?
|
||||
if e.path == default_template_name
|
||||
raise UnknownAction, "No action responded to #{action_name}. Actions: #{action_methods.sort.to_sentence}", caller
|
||||
else
|
||||
raise e
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1290,10 +1298,8 @@ module ActionController #:nodoc:
|
|||
@_session.close if @_session && @_session.respond_to?(:close)
|
||||
end
|
||||
|
||||
def template_exists?(template_name = default_template_name)
|
||||
@template.send(:_pick_template, template_name) ? true : false
|
||||
rescue ActionView::MissingTemplate
|
||||
false
|
||||
def default_template(action_name = self.action_name)
|
||||
self.view_paths.find_template(default_template_name(action_name), default_template_format)
|
||||
end
|
||||
|
||||
def default_template_name(action_name = self.action_name)
|
||||
|
|
|
@ -178,9 +178,15 @@ module ActionController #:nodoc:
|
|||
find_layout(layout, format)
|
||||
end
|
||||
|
||||
def layout_list #:nodoc:
|
||||
Array(view_paths).sum([]) { |path| Dir["#{path}/layouts/**/*"] }
|
||||
end
|
||||
|
||||
def find_layout(layout, *formats) #:nodoc:
|
||||
return layout if layout.respond_to?(:render)
|
||||
view_paths.find_template(layout.to_s =~ /layouts\// ? layout : "layouts/#{layout}", *formats)
|
||||
rescue ActionView::MissingTemplate
|
||||
nil
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -188,7 +194,7 @@ module ActionController #:nodoc:
|
|||
inherited_without_layout(child)
|
||||
unless child.name.blank?
|
||||
layout_match = child.name.underscore.sub(/_controller$/, '').sub(/^controllers\//, '')
|
||||
child.layout(layout_match, {}, true) if child.find_layout(layout_match, :all)
|
||||
child.layout(layout_match, {}, true) unless child.layout_list.grep(%r{layouts/#{layout_match}(\.[a-z][0-9a-z]*)+$}).empty?
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -225,8 +231,16 @@ module ActionController #:nodoc:
|
|||
|
||||
private
|
||||
def candidate_for_layout?(options)
|
||||
options.values_at(:text, :xml, :json, :file, :inline, :partial, :nothing, :update).compact.empty? &&
|
||||
!@template.__send__(:_exempt_from_layout?, options[:template] || default_template_name(options[:action]))
|
||||
template = options[:template] || default_template(options[:action])
|
||||
if options.values_at(:text, :xml, :json, :file, :inline, :partial, :nothing, :update).compact.empty?
|
||||
begin
|
||||
!self.view_paths.find_template(template, default_template_format).exempt_from_layout?
|
||||
rescue ActionView::MissingTemplate
|
||||
true
|
||||
end
|
||||
end
|
||||
rescue ActionView::MissingTemplate
|
||||
false
|
||||
end
|
||||
|
||||
def pick_layout(options)
|
||||
|
@ -235,7 +249,7 @@ module ActionController #:nodoc:
|
|||
when FalseClass
|
||||
nil
|
||||
when NilClass, TrueClass
|
||||
active_layout if action_has_layout? && !@template.__send__(:_exempt_from_layout?, default_template_name)
|
||||
active_layout if action_has_layout? && candidate_for_layout?(:template => default_template_name)
|
||||
else
|
||||
active_layout(layout)
|
||||
end
|
||||
|
|
|
@ -3,7 +3,10 @@ module ActionView #:nodoc:
|
|||
end
|
||||
|
||||
class MissingTemplate < ActionViewError #:nodoc:
|
||||
attr_reader :path
|
||||
|
||||
def initialize(paths, path, template_format = nil)
|
||||
@path = path
|
||||
full_template_path = path.include?('.') ? path : "#{path}.erb"
|
||||
display_paths = paths.compact.join(":")
|
||||
template_type = (path =~ /layouts/i) ? 'layout' : 'template'
|
||||
|
@ -172,17 +175,6 @@ module ActionView #:nodoc:
|
|||
delegate :logger, :to => 'ActionController::Base'
|
||||
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
|
||||
|
||||
@@debug_rjs = false
|
||||
##
|
||||
# :singleton-method:
|
||||
|
@ -190,12 +182,6 @@ module ActionView #:nodoc:
|
|||
# that alert()s the caught exception (and then re-raises it).
|
||||
cattr_accessor :debug_rjs
|
||||
|
||||
@@warn_cache_misses = false
|
||||
##
|
||||
# :singleton-method:
|
||||
# A warning will be displayed whenever an action results in a cache miss on your view paths.
|
||||
cattr_accessor :warn_cache_misses
|
||||
|
||||
attr_internal :request
|
||||
|
||||
delegate :request_forgery_protection_token, :template, :params, :session, :cookies, :response, :headers,
|
||||
|
@ -257,7 +243,8 @@ module ActionView #:nodoc:
|
|||
if options[:layout]
|
||||
_render_with_layout(options, local_assigns, &block)
|
||||
elsif options[:file]
|
||||
_pick_template(options[:file]).render_template(self, options[:locals])
|
||||
tempalte = self.view_paths.find_template(options[:file], template_format)
|
||||
tempalte.render_template(self, options[:locals])
|
||||
elsif options[:partial]
|
||||
render_partial(options)
|
||||
elsif options[:inline]
|
||||
|
@ -315,45 +302,6 @@ 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.find_template(template_file_name, template_format)
|
||||
template
|
||||
elsif (first_render = @_render_stack.first) && first_render.respond_to?(:format_and_extension) &&
|
||||
(template = self.view_paths["#{template_file_name}.#{first_render.format_and_extension}"])
|
||||
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)
|
||||
|
||||
|
|
|
@ -228,7 +228,7 @@ module ActionView
|
|||
path = "_#{partial_path}"
|
||||
end
|
||||
|
||||
_pick_template(path)
|
||||
self.view_paths.find_template(path, self.template_format)
|
||||
end
|
||||
memoize :_pick_partial_template
|
||||
end
|
||||
|
|
|
@ -2,13 +2,6 @@ module ActionView #:nodoc:
|
|||
class PathSet < Array #:nodoc:
|
||||
def self.type_cast(obj)
|
||||
if obj.is_a?(String)
|
||||
if Base.warn_cache_misses && defined?(Rails) && Rails.initialized?
|
||||
Base.logger.debug "[PERFORMANCE] Processing view path during a " +
|
||||
"request. This an expense disk operation that should be done at " +
|
||||
"boot. You can manually process this view path with " +
|
||||
"ActionView::Base.process_view_paths(#{obj.inspect}) and set it " +
|
||||
"as your view path"
|
||||
end
|
||||
Path.new(obj)
|
||||
else
|
||||
obj
|
||||
|
@ -92,7 +85,7 @@ module ActionView #:nodoc:
|
|||
else
|
||||
Dir.glob("#{@path}/#{path}*").each do |file|
|
||||
template = create_template(file)
|
||||
if path == template.path_without_extension || path == template.path
|
||||
if template.accessible_paths.include?(path)
|
||||
return template
|
||||
end
|
||||
end
|
||||
|
@ -115,8 +108,9 @@ module ActionView #:nodoc:
|
|||
|
||||
templates_in_path do |template|
|
||||
template.load!
|
||||
@paths[template.path] = template
|
||||
@paths[template.path_without_extension] ||= template
|
||||
template.accessible_paths.each do |path|
|
||||
@paths[path] = template
|
||||
end
|
||||
end
|
||||
|
||||
@paths.freeze
|
||||
|
@ -143,28 +137,19 @@ module ActionView #:nodoc:
|
|||
each { |path| path.reload! }
|
||||
end
|
||||
|
||||
def [](template_path)
|
||||
each do |path|
|
||||
if template = path[template_path]
|
||||
return template
|
||||
end
|
||||
end
|
||||
nil
|
||||
end
|
||||
def find_template(original_template_path, format = nil)
|
||||
return original_template_path if original_template_path.respond_to?(:render)
|
||||
template_path = original_template_path.sub(/^\//, '')
|
||||
|
||||
def find_template(path, *formats)
|
||||
if formats && formats.first == :all
|
||||
formats = Mime::EXTENSION_LOOKUP.values.map(&:to_sym)
|
||||
end
|
||||
formats.each do |format|
|
||||
if template = self["#{path}.#{format}"]
|
||||
each do |load_path|
|
||||
if format && (template = load_path["#{template_path}.#{format}"])
|
||||
return template
|
||||
elsif template = load_path[template_path]
|
||||
return template
|
||||
end
|
||||
end
|
||||
if template = self[path]
|
||||
return template
|
||||
end
|
||||
nil
|
||||
|
||||
Template.new(original_template_path, self)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -22,6 +22,11 @@ module ActionView
|
|||
end
|
||||
memoize :compiled_source
|
||||
|
||||
def method_name_without_locals
|
||||
['_run', extension, method_segment].compact.join('_')
|
||||
end
|
||||
memoize :method_name_without_locals
|
||||
|
||||
def render(view, local_assigns = {})
|
||||
compile(local_assigns)
|
||||
|
||||
|
@ -46,9 +51,12 @@ module ActionView
|
|||
|
||||
def method_name(local_assigns)
|
||||
if local_assigns && local_assigns.any?
|
||||
local_assigns_keys = "locals_#{local_assigns.keys.map { |k| k.to_s }.sort.join('_')}"
|
||||
method_name = method_name_without_locals.dup
|
||||
method_name << "_locals_#{local_assigns.keys.map { |k| k.to_s }.sort.join('_')}"
|
||||
else
|
||||
method_name = method_name_without_locals
|
||||
end
|
||||
['_run', extension, method_segment, local_assigns_keys].compact.join('_').to_sym
|
||||
method_name.to_sym
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -4,6 +4,17 @@ module ActionView #:nodoc:
|
|||
extend ActiveSupport::Memoizable
|
||||
include Renderable
|
||||
|
||||
# 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
|
||||
|
||||
attr_accessor :filename, :load_path, :base_path, :name, :format, :extension
|
||||
delegate :to_s, :to => :path
|
||||
|
||||
|
@ -17,6 +28,18 @@ module ActionView #:nodoc:
|
|||
extend RenderablePartial if @name =~ /^_/
|
||||
end
|
||||
|
||||
def accessible_paths
|
||||
paths = []
|
||||
paths << path
|
||||
paths << path_without_extension
|
||||
if multipart?
|
||||
formats = format.split(".")
|
||||
paths << "#{path_without_format_and_extension}.#{formats.first}"
|
||||
paths << "#{path_without_format_and_extension}.#{formats.second}"
|
||||
end
|
||||
paths
|
||||
end
|
||||
|
||||
def format_and_extension
|
||||
(extensions = [format, extension].compact.join(".")).blank? ? nil : extensions
|
||||
end
|
||||
|
@ -57,6 +80,10 @@ module ActionView #:nodoc:
|
|||
end
|
||||
memoize :relative_path
|
||||
|
||||
def exempt_from_layout?
|
||||
@@exempt_from_layout.any? { |exempted| path =~ exempted }
|
||||
end
|
||||
|
||||
def mtime
|
||||
File.mtime(filename)
|
||||
end
|
||||
|
@ -94,6 +121,7 @@ module ActionView #:nodoc:
|
|||
|
||||
def load!
|
||||
@loaded = true
|
||||
compile({})
|
||||
freeze
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue