提交 ebf9b373 编写于 作者: R Rick Olson

Add some performance enhancements to ActionView.

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@6736 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
上级 fa3618d3
*SVN* *SVN*
* Add some performance enhancements to ActionView.
* Cache base_paths in @@cached_base_paths
* Cache template extensions in @@cached_template_extension
* Remove unnecessary rescues
* Assume that rendered partials go by the HTML format by default * Assume that rendered partials go by the HTML format by default
def my_partial def my_partial
......
...@@ -1213,14 +1213,14 @@ def template_public?(template_name = default_template_name) ...@@ -1213,14 +1213,14 @@ def template_public?(template_name = default_template_name)
end end
def template_exempt_from_layout?(template_name = default_template_name) def template_exempt_from_layout?(template_name = default_template_name)
extension = @template.pick_template_extension(template_name) rescue nil extension = @template && @template.pick_template_extension(template_name)
name_with_extension = !template_name.include?('.') && extension ? "#{template_name}.#{extension}" : template_name name_with_extension = !template_name.include?('.') && extension ? "#{template_name}.#{extension}" : template_name
extension == :rjs || @@exempt_from_layout.any? { |ext| name_with_extension =~ ext } extension == :rjs || @@exempt_from_layout.any? { |ext| name_with_extension =~ ext }
end end
def assert_existence_of_template_file(template_name) def assert_existence_of_template_file(template_name)
unless template_exists?(template_name) || ignore_missing_templates unless template_exists?(template_name) || ignore_missing_templates
full_template_path = template_name.include?('.') ? template_name : @template.send(:full_template_path, template_name, "#{@template.send(:template_format)}.erb") full_template_path = template_name.include?('.') ? template_name : @template.full_template_path(template_name, "#{@template.template_format}.erb")
template_type = (template_name =~ /layouts/i) ? 'layout' : 'template' template_type = (template_name =~ /layouts/i) ? 'layout' : 'template'
raise(MissingTemplate, "Missing #{template_type} #{full_template_path}") raise(MissingTemplate, "Missing #{template_type} #{full_template_path}")
end end
......
...@@ -214,7 +214,6 @@ def layout_directory_exists_cache ...@@ -214,7 +214,6 @@ def layout_directory_exists_cache
# weblog/standard, but <tt>layout "standard"</tt> will return layouts/standard. # weblog/standard, but <tt>layout "standard"</tt> will return layouts/standard.
def active_layout(passed_layout = nil) def active_layout(passed_layout = nil)
layout = passed_layout || self.class.default_layout layout = passed_layout || self.class.default_layout
active_layout = case layout active_layout = case layout
when String then layout when String then layout
when Symbol then send(layout) when Symbol then send(layout)
......
...@@ -170,7 +170,7 @@ class Base ...@@ -170,7 +170,7 @@ class Base
@@cache_template_loading = false @@cache_template_loading = false
cattr_accessor :cache_template_loading cattr_accessor :cache_template_loading
# Specify whether file extension lookup should be cached. # Specify whether file extension lookup should be cached, and whether template base path lookup should be cached.
# Should be +false+ for development environments. Defaults to +true+. # Should be +false+ for development environments. Defaults to +true+.
@@cache_template_extensions = true @@cache_template_extensions = true
cattr_accessor :cache_template_extensions cattr_accessor :cache_template_extensions
...@@ -208,13 +208,17 @@ module CompiledTemplates #:nodoc: ...@@ -208,13 +208,17 @@ module CompiledTemplates #:nodoc:
# If for a given path, path.ext1 and path.ext2 exist on the file system, the order of extensions # If for a given path, path.ext1 and path.ext2 exist on the file system, the order of extensions
# used by pick_template_extension determines whether ext1 or ext2 will be stored. # used by pick_template_extension determines whether ext1 or ext2 will be stored.
@@cached_template_extension = {} @@cached_template_extension = {}
# Maps template paths / extensions to
@@cached_base_paths = {}
@@templates_requiring_setup = Set.new(%w(builder rxml rjs))
# Order of template handers checked by #file_exists? depending on the current #template_format # Order of template handers checked by #file_exists? depending on the current #template_format
DEFAULT_TEMPLATE_HANDLER_PREFERENCE = %w(erb rhtml builder rxml javascript delegate) DEFAULT_TEMPLATE_HANDLER_PREFERENCE = [:erb, :rhtml, :builder, :rxml, :javascript, :delegate]
TEMPLATE_HANDLER_PREFERENCES = { TEMPLATE_HANDLER_PREFERENCES = {
:js => %w(javascript erb rhtml builder rxml delegate), :js => [:javascript, :erb, :rhtml, :builder, :rxml, :delegate],
:xml => %w(builder rxml erb rhtml javascript delegate), :xml => [:builder, :rxml, :erb, :rhtml, :javascript, :delegate],
:delegate => %w(delegate) :delegate => [:delegate]
} }
class ObjectWrapper < Struct.new(:value) #:nodoc: class ObjectWrapper < Struct.new(:value) #:nodoc:
...@@ -262,6 +266,9 @@ def render_file(template_path, use_full_path = true, local_assigns = {}) #:nodoc ...@@ -262,6 +266,9 @@ def render_file(template_path, use_full_path = true, local_assigns = {}) #:nodoc
template_file_name = full_template_path(template_path_without_extension, template_extension) template_file_name = full_template_path(template_path_without_extension, template_extension)
else else
template_extension = pick_template_extension(template_path).to_s template_extension = pick_template_extension(template_path).to_s
unless template_extension
raise ActionViewError, "No #{template_handler_preferences.to_sentence} template found for #{template_path} in #{@view_paths.inspect}"
end
template_file_name = full_template_path(template_path, template_extension) template_file_name = full_template_path(template_path, template_extension)
template_extension = template_extension.gsub(/^\w+\./, '') # strip off any formats template_extension = template_extension.gsub(/^\w+\./, '') # strip off any formats
end end
...@@ -341,10 +348,31 @@ def compile_and_render_template(extension, template = nil, file_path = nil, loca ...@@ -341,10 +348,31 @@ def compile_and_render_template(extension, template = nil, file_path = nil, loca
end end
end end
# Gets the full template path with base path for the given template_path and extension.
#
# full_template_path('users/show', 'html.erb')
# # => '~/rails/app/views/users/show.html.erb
#
def full_template_path(template_path, extension)
if @@cache_template_extensions
(@@cached_base_paths[template_path] ||= {})[extension.to_s] = find_full_template_path(template_path, extension)
else
find_full_template_path(template_path, extension)
end
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_extension('users/show')
# # => 'html.erb'
#
# pick_template_extension('users/legacy')
# # => "rhtml"
#
def pick_template_extension(template_path)#:nodoc: def pick_template_extension(template_path)#:nodoc:
if @@cache_template_extensions if @@cache_template_extensions
formatted_template_path = "#{template_path}.#{template_format}" (@@cached_template_extension[template_path] ||= {})[template_format] ||= find_template_extension_for(template_path)
@@cached_template_extension[formatted_template_path] ||= find_template_extension_for(template_path)
else else
find_template_extension_for(template_path) find_template_extension_for(template_path)
end end
...@@ -356,43 +384,31 @@ def delegate_template_exists?(template_path)#:nodoc: ...@@ -356,43 +384,31 @@ def delegate_template_exists?(template_path)#:nodoc:
end end
def erb_template_exists?(template_path)#:nodoc: def erb_template_exists?(template_path)#:nodoc:
template_exists?(template_path, :erb) && :erb template_exists?(template_path, :erb)
end end
def builder_template_exists?(template_path)#:nodoc: def builder_template_exists?(template_path)#:nodoc:
template_exists?(template_path, :builder) && :builder template_exists?(template_path, :builder)
end end
def rhtml_template_exists?(template_path)#:nodoc: def rhtml_template_exists?(template_path)#:nodoc:
template_exists?(template_path, :rhtml) && :rhtml template_exists?(template_path, :rhtml)
end end
def rxml_template_exists?(template_path)#:nodoc: def rxml_template_exists?(template_path)#:nodoc:
template_exists?(template_path, :rxml) && :rxml template_exists?(template_path, :rxml)
end end
def javascript_template_exists?(template_path)#:nodoc: def javascript_template_exists?(template_path)#:nodoc:
template_exists?(template_path, :rjs) && :rjs template_exists?(template_path, :rjs)
end end
def file_exists?(template_path)#:nodoc: def file_exists?(template_path)#:nodoc:
template_file_name, template_file_extension = path_and_extension(template_path) template_file_name, template_file_extension = path_and_extension(template_path)
if template_file_extension if template_file_extension
template_exists?(template_file_name, template_file_extension) && template_file_extension template_exists?(template_file_name, template_file_extension)
else else
formatted_template_path = "#{template_path}.#{template_format}" pick_template_extension(template_path)
return true if cached_template_extension(formatted_template_path)
template_handler_preferences.each do |template_type|
if extension = send("#{template_type}_template_exists?", formatted_template_path)
return "#{template_format}.#{extension}"
end
end
template_handler_preferences.each do |template_type|
if extension = send("#{template_type}_template_exists?", template_path)
return extension
end
end
nil
end end
end end
...@@ -403,7 +419,9 @@ def file_public?(template_path)#:nodoc: ...@@ -403,7 +419,9 @@ def file_public?(template_path)#:nodoc:
# symbolized version of the :format parameter of the request, or :html by default. # symbolized version of the :format parameter of the request, or :html by default.
def template_format def template_format
@template_format ||= controller.request.parameters[:format].to_sym rescue :html return @template_format if @template_format
format = controller && controller.respond_to?(:request) && controller.request.parameters[:format]
@template_format = format.blank? ? :html : format.to_sym
end end
def template_handler_preferences def template_handler_preferences
...@@ -411,16 +429,16 @@ def template_handler_preferences ...@@ -411,16 +429,16 @@ def template_handler_preferences
end end
private private
def full_template_path(template_path, extension) def find_full_template_path(template_path, extension)
file_name = "#{template_path}.#{extension}" file_name = "#{template_path}.#{extension}"
base_path = find_base_path_for(file_name) base_path = find_base_path_for(file_name)
"#{base_path}/#{file_name}" base_path.blank? ? "" : "#{base_path}/#{file_name}"
end end
# Asserts the existence of a template. # Asserts the existence of a template.
def template_exists?(template_path, extension) def template_exists?(template_path, extension)
file_path = full_template_path(template_path, extension) file_path = full_template_path(template_path, extension)
@@method_names.has_key?(file_path) || FileTest.exists?(file_path) !file_path.blank? && @@method_names.has_key?(file_path) || FileTest.exists?(file_path)
end end
# Splits the path and extension from the given template_path and returns as an array. # Splits the path and extension from the given template_path and returns as an array.
...@@ -428,12 +446,6 @@ def path_and_extension(template_path) ...@@ -428,12 +446,6 @@ def path_and_extension(template_path)
template_path_without_extension = template_path.sub(/\.(\w+)$/, '') template_path_without_extension = template_path.sub(/\.(\w+)$/, '')
[ template_path_without_extension, $1 ] [ template_path_without_extension, $1 ]
end end
# Caches the extension for the given formatted template path. The extension may have the format
# too, such as 'html.erb'.
def cached_template_extension(formatted_template_path)
@@cache_template_extensions && @@cached_template_extension[formatted_template_path]
end
# Returns the view path that contains the given relative template path. # Returns the view path that contains the given relative template path.
def find_base_path_for(template_file_name) def find_base_path_for(template_file_name)
...@@ -447,11 +459,26 @@ def extract_base_path_from(full_path) ...@@ -447,11 +459,26 @@ def extract_base_path_from(full_path)
# Determines the template's file extension, such as rhtml, rxml, or rjs. # Determines the template's file extension, such as rhtml, rxml, or rjs.
def find_template_extension_for(template_path) def find_template_extension_for(template_path)
if extension = file_exists?(template_path) find_template_extension_from_handler(template_path, true) || find_template_extension_from_handler(template_path)
return extension end
else
raise ActionViewError, "No erb, builder, rhtml, rxml, rjs or delegate template found for #{template_path} in #{@view_paths.inspect}" def find_template_extension_from_handler(template_path, formatted = nil)
checked_template_path = formatted ? "#{template_path}.#{template_format}" : template_path
template_handler_preferences.each do |template_type|
extension =
case template_type
when :javascript
template_exists?(checked_template_path, :rjs) && :rjs
when :delegate
delegate_template_exists?(checked_template_path)
else
template_exists?(checked_template_path, template_type) && template_type
end
if extension
return formatted ? "#{template_format}.#{extension}" : extension.to_s
end
end end
nil
end end
# This method reads a template file. # This method reads a template file.
...@@ -537,11 +564,7 @@ def create_template_source(extension, template, render_symbol, locals) ...@@ -537,11 +564,7 @@ def create_template_source(extension, template, render_symbol, locals)
end end
def template_requires_setup?(extension) #:nodoc: def template_requires_setup?(extension) #:nodoc:
templates_requiring_setup.include? extension.to_s @@templates_requiring_setup.include? extension.to_s
end
def templates_requiring_setup #:nodoc:
%w(builder rxml rjs)
end end
def assign_method_name(extension, template, file_name) def assign_method_name(extension, template, file_name)
......
...@@ -66,6 +66,7 @@ def test_third_party_template_library_auto_discovers_layout ...@@ -66,6 +66,7 @@ def test_third_party_template_library_auto_discovers_layout
@controller = ThirdPartyTemplateLibraryController.new @controller = ThirdPartyTemplateLibraryController.new
get :hello get :hello
assert_equal 'layouts/third_party_template_library', @controller.active_layout assert_equal 'layouts/third_party_template_library', @controller.active_layout
assert_equal 'layouts/third_party_template_library', @response.layout
assert_equal 'Mab', @response.body assert_equal 'Mab', @response.body
end end
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册