Lookup compiled methods in CompiledTemplates instance methods set instead of using a "methods_names" hash
This commit is contained in:
parent
ce5d958f8f
commit
9828aecd2a
@ -189,10 +189,6 @@ module CompiledTemplates #:nodoc:
|
||||
end
|
||||
include CompiledTemplates
|
||||
|
||||
# Maps inline templates to their method names
|
||||
cattr_accessor :method_names
|
||||
@@method_names = {}
|
||||
|
||||
# Cache public asset paths
|
||||
cattr_reader :computed_public_paths
|
||||
@@computed_public_paths = {}
|
||||
|
@ -9,13 +9,8 @@ def initialize(view, source, locals = {}, type = nil)
|
||||
@extension = type
|
||||
@locals = locals || {}
|
||||
|
||||
@method_key = "inline_#{@source.hash.abs}"
|
||||
@method_segment = "inline_#{@source.hash.abs}"
|
||||
@handler = Template.handler_class_for_extension(@extension).new(@view)
|
||||
end
|
||||
|
||||
private
|
||||
def method_name_path_segment
|
||||
@method_key
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -4,15 +4,15 @@ module Renderable
|
||||
attr_accessor :locals
|
||||
|
||||
# TODO: These readers should be private
|
||||
attr_reader :filename, :source, :handler, :method_key, :method
|
||||
attr_reader :filename, :source, :handler
|
||||
|
||||
def render
|
||||
prepare!
|
||||
@handler.render(self)
|
||||
end
|
||||
|
||||
def method_name
|
||||
['_run', @extension, method_name_path_segment].compact.join('_').to_sym
|
||||
def method
|
||||
['_run', @extension, @method_segment].compact.join('_').to_sym
|
||||
end
|
||||
|
||||
private
|
||||
@ -23,7 +23,6 @@ def prepare!
|
||||
|
||||
if @handler.compilable?
|
||||
@handler.compile_template(self) # compile the given template, if necessary
|
||||
@method = @view.method_names[method_key] # Set the method name for this template and run it
|
||||
end
|
||||
|
||||
@prepared = true
|
||||
|
@ -19,7 +19,7 @@ def initialize(view, path, use_full_path = nil, locals = {})
|
||||
|
||||
set_extension_and_file_name
|
||||
|
||||
@method_key = @filename
|
||||
@method_segment = compiled_method_name_file_path_segment
|
||||
@locals = locals || {}
|
||||
@handler = self.class.handler_class_for_extension(@extension).new(@view)
|
||||
end
|
||||
@ -72,7 +72,7 @@ def raise_missing_template_exception
|
||||
raise MissingTemplate, "Missing #{template_type} #{full_template_path} in view path #{display_paths}"
|
||||
end
|
||||
|
||||
def method_name_path_segment
|
||||
def compiled_method_name_file_path_segment
|
||||
s = File.expand_path(@filename)
|
||||
s.sub!(/^#{Regexp.escape(File.expand_path(RAILS_ROOT))}/, '') if defined?(RAILS_ROOT)
|
||||
s.gsub!(/([^a-zA-Z0-9_])/) { $1.ord }
|
||||
|
@ -4,7 +4,7 @@ module Compilable
|
||||
def self.included(base)
|
||||
base.extend ClassMethod
|
||||
|
||||
# Map method names to the names passed in local assigns so far
|
||||
# Map method names to the compiled local assigns
|
||||
base.cattr_accessor :template_args
|
||||
base.template_args = {}
|
||||
end
|
||||
@ -17,23 +17,34 @@ def compilable?
|
||||
end
|
||||
|
||||
def render(template)
|
||||
@view.send :execute, template
|
||||
@view.send(:execute, template)
|
||||
end
|
||||
|
||||
# Compile and evaluate the template's code
|
||||
def compile_template(template)
|
||||
return false unless compile_template?(template)
|
||||
|
||||
render_symbol = assign_method_name(template)
|
||||
render_source = create_template_source(template, render_symbol)
|
||||
locals_code = ""
|
||||
locals_keys = cache_template_args(template.method, template.locals)
|
||||
locals_keys.each do |key|
|
||||
locals_code << "#{key} = local_assigns[:#{key}];"
|
||||
end
|
||||
|
||||
source = <<-end_src
|
||||
def #{template.method}(local_assigns)
|
||||
old_output_buffer = output_buffer;#{locals_code};#{compile(template)}
|
||||
ensure
|
||||
self.output_buffer = old_output_buffer
|
||||
end
|
||||
end_src
|
||||
|
||||
begin
|
||||
file_name = template.filename || 'compiled-template'
|
||||
ActionView::Base::CompiledTemplates.module_eval(render_source, file_name, 0)
|
||||
rescue Exception => e # errors from template code
|
||||
ActionView::Base::CompiledTemplates.module_eval(source, file_name, 0)
|
||||
rescue Exception => e # errors from template code
|
||||
if Base.logger
|
||||
Base.logger.debug "ERROR: compiling #{render_symbol} RAISED #{e}"
|
||||
Base.logger.debug "Function body: #{render_source}"
|
||||
Base.logger.debug "ERROR: compiling #{template.method} RAISED #{e}"
|
||||
Base.logger.debug "Function body: #{source}"
|
||||
Base.logger.debug "Backtrace: #{e.backtrace.join("\n")}"
|
||||
end
|
||||
|
||||
@ -47,7 +58,7 @@ def compile_template(template)
|
||||
# if local_assigns has a new key, which isn't supported by the compiled code yet.
|
||||
def compile_template?(template)
|
||||
# Unless the template has been complied yet, compile
|
||||
return true unless render_symbol = @view.method_names[template.method_key]
|
||||
return true unless Base::CompiledTemplates.instance_methods.include?(template.method.to_s)
|
||||
|
||||
# If template caching is disabled, compile
|
||||
return true unless Base.cache_template_loading
|
||||
@ -56,38 +67,17 @@ def compile_template?(template)
|
||||
return true if template.is_a?(InlineTemplate)
|
||||
|
||||
# Unless local assigns support, recompile
|
||||
return true unless supports_local_assigns?(render_symbol, template.locals)
|
||||
return true unless supports_local_assigns?(template.method, template.locals)
|
||||
|
||||
# Otherwise, use compiled method
|
||||
return false
|
||||
end
|
||||
|
||||
def assign_method_name(template)
|
||||
@view.method_names[template.method_key] ||= template.method_name
|
||||
end
|
||||
|
||||
# Method to create the source code for a given template.
|
||||
def create_template_source(template, render_symbol)
|
||||
body = compile(template)
|
||||
|
||||
def cache_template_args(render_symbol, local_assigns)
|
||||
self.template_args[render_symbol] ||= {}
|
||||
locals_keys = self.template_args[render_symbol].keys | template.locals.keys
|
||||
locals_keys = self.template_args[render_symbol].keys | local_assigns.keys
|
||||
self.template_args[render_symbol] = locals_keys.inject({}) { |h, k| h[k] = true; h }
|
||||
|
||||
locals_code = ""
|
||||
locals_keys.each do |key|
|
||||
locals_code << "#{key} = local_assigns[:#{key}];"
|
||||
end
|
||||
|
||||
source = <<-end_src
|
||||
def #{render_symbol}(local_assigns)
|
||||
old_output_buffer = output_buffer;#{locals_code};#{body}
|
||||
ensure
|
||||
self.output_buffer = old_output_buffer
|
||||
end
|
||||
end_src
|
||||
|
||||
return source
|
||||
locals_keys
|
||||
end
|
||||
|
||||
# Return true if the given template was compiled for a superset of the keys in local_assigns
|
||||
|
Loading…
Reference in New Issue
Block a user