Browse files

Synchronize template compiling

  • Loading branch information...
1 parent 9828aec commit 7b9e8ae2734089555e5bfdb9e9c80d92f43551a2 @josh josh committed Jul 6, 2008
Showing with 34 additions and 31 deletions.
  1. +34 −31 actionpack/lib/action_view/template_handlers/compilable.rb
View
65 actionpack/lib/action_view/template_handlers/compilable.rb
@@ -4,9 +4,10 @@ module Compilable
def self.included(base)
base.extend ClassMethod
+ @@mutex = Mutex.new
+
# Map method names to the compiled local assigns
- base.cattr_accessor :template_args
- base.template_args = {}
+ @@template_args = {}
end
module ClassMethod
@@ -22,41 +23,43 @@ def render(template)
# Compile and evaluate the template's code
def compile_template(template)
- return false unless compile_template?(template)
-
- locals_code = ""
- locals_keys = cache_template_args(template.method, template.locals)
- locals_keys.each do |key|
- locals_code << "#{key} = local_assigns[:#{key}];"
- end
+ return false unless recompile_template?(template)
- 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(source, file_name, 0)
- rescue Exception => e # errors from template code
- if Base.logger
- Base.logger.debug "ERROR: compiling #{template.method} RAISED #{e}"
- Base.logger.debug "Function body: #{source}"
- Base.logger.debug "Backtrace: #{e.backtrace.join("\n")}"
+ @@mutex.synchronize do
+ locals_code = ""
+ locals_keys = cache_template_args(template.method, template.locals)
+ locals_keys.each do |key|
+ locals_code << "#{key} = local_assigns[:#{key}];"
end
- raise ActionView::TemplateError.new(template, @view.assigns, e)
+ 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(source, file_name, 0)
+ rescue Exception => e # errors from template code
+ if Base.logger
+ Base.logger.debug "ERROR: compiling #{template.method} RAISED #{e}"
+ Base.logger.debug "Function body: #{source}"
+ Base.logger.debug "Backtrace: #{e.backtrace.join("\n")}"
+ end
+
+ raise ActionView::TemplateError.new(template, @view.assigns, e)
+ end
end
end
private
# Method to check whether template compilation is necessary.
# The template will be compiled if the inline template or file has not been compiled yet,
# if local_assigns has a new key, which isn't supported by the compiled code yet.
- def compile_template?(template)
+ def recompile_template?(template)
# Unless the template has been complied yet, compile
return true unless Base::CompiledTemplates.instance_methods.include?(template.method.to_s)
@@ -74,16 +77,16 @@ def compile_template?(template)
end
def cache_template_args(render_symbol, local_assigns)
- self.template_args[render_symbol] ||= {}
- 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 }
+ @@template_args[render_symbol] ||= {}
+ locals_keys = @@template_args[render_symbol].keys | local_assigns.keys
+ @@template_args[render_symbol] = locals_keys.inject({}) { |h, k| h[k] = true; h }
locals_keys
end
# Return true if the given template was compiled for a superset of the keys in local_assigns
def supports_local_assigns?(render_symbol, local_assigns)
local_assigns.empty? ||
- ((args = self.template_args[render_symbol]) && local_assigns.all? { |k,_| args.has_key?(k) })
+ ((args = @@template_args[render_symbol]) && local_assigns.all? { |k,_| args.has_key?(k) })
end
end
end

0 comments on commit 7b9e8ae

Please sign in to comment.