aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_view/compiled_templates.rb
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib/action_view/compiled_templates.rb')
-rw-r--r--actionpack/lib/action_view/compiled_templates.rb70
1 files changed, 70 insertions, 0 deletions
diff --git a/actionpack/lib/action_view/compiled_templates.rb b/actionpack/lib/action_view/compiled_templates.rb
new file mode 100644
index 0000000000..9488432ba2
--- /dev/null
+++ b/actionpack/lib/action_view/compiled_templates.rb
@@ -0,0 +1,70 @@
+
+module ActionView
+
+ # CompiledTemplates modules hold methods that have been compiled.
+ # Templates are compiled into these methods so that they do not need to be
+ # re-read and re-parsed each request.
+ #
+ # Each template may be compiled into one or more methods. Each method accepts a given
+ # set of parameters which is used to implement local assigns passing.
+ #
+ # To use a compiled template module, create a new instance and include it into the class
+ # in which you want the template to be rendered.
+ class CompiledTemplates < Module
+ attr_reader :method_names
+
+ def initialize
+ @method_names = Hash.new do |hash, key|
+ hash[key] = "__compiled_method_#{(hash.length + 1)}"
+ end
+ @mtimes = {}
+ end
+
+ # Return the full key for the given identifier and argument names
+ def full_key(identifier, arg_names)
+ [identifier, arg_names]
+ end
+
+ # Return the selector for this method or nil if it has not been compiled
+ def selector(identifier, arg_names)
+ key = full_key(identifier, arg_names)
+ method_names.key?(key) ? method_names[key] : nil
+ end
+ alias :compiled? :selector
+
+ # Return the time at which the method for the given identifier and argument names was compiled.
+ def mtime(identifier, arg_names)
+ @mtimes[full_key(identifier, arg_names)]
+ end
+
+ # Compile the provided source code for the given argument names and with the given initial line number.
+ # The identifier should be unique to this source.
+ #
+ # The file_name, if provided will appear in backtraces. If not provded, the file_name defaults
+ # to the identifier.
+ #
+ # This method will return the selector for the compiled version of this method.
+ def compile_source(identifier, arg_names, source, initial_line_number = 0, file_name = nil)
+ file_name ||= identifier
+ name = method_names[full_key(identifier, arg_names)]
+ arg_desc = arg_names.empty? ? '' : "(#{arg_names * ', '})"
+ fake_file_name = "#{file_name}#{arg_desc}" # Include the arguments for this version (for now)
+
+ method_def = wrap_source(name, arg_names, source)
+
+ begin
+ module_eval(method_def, fake_file_name, initial_line_number)
+ @mtimes[full_key(identifier, arg_names)] = Time.now
+ rescue Object => e
+ e.blame_file! identifier
+ raise
+ end
+ name
+ end
+
+ # Wrap the provided source in a def ... end block.
+ def wrap_source(name, arg_names, source)
+ "def #{name}(#{arg_names * ', '})\n#{source}\nend"
+ end
+ end
+end