aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_view
diff options
context:
space:
mode:
authorMichael Koziarski <michael@koziarski.com>2008-02-06 04:26:40 +0000
committerMichael Koziarski <michael@koziarski.com>2008-02-06 04:26:40 +0000
commit692dbbf79387b56e241e1acd05f74f7d71ff79a6 (patch)
tree7d1c1c9f7a8baa517b525a0d02821fd47ca34daf /actionpack/lib/action_view
parent8bc9018882c55cea06d062a9d2d4a32f92b2dc47 (diff)
downloadrails-692dbbf79387b56e241e1acd05f74f7d71ff79a6.tar.gz
rails-692dbbf79387b56e241e1acd05f74f7d71ff79a6.tar.bz2
rails-692dbbf79387b56e241e1acd05f74f7d71ff79a6.zip
Introduce a Template class to ActionView. Closes #11024 [lifofifo]
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@8805 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
Diffstat (limited to 'actionpack/lib/action_view')
-rw-r--r--actionpack/lib/action_view/base.rb68
-rw-r--r--actionpack/lib/action_view/template.rb65
-rw-r--r--actionpack/lib/action_view/template_error.rb8
-rw-r--r--actionpack/lib/action_view/template_handler.rb5
-rw-r--r--actionpack/lib/action_view/template_handlers/compilable.rb40
5 files changed, 104 insertions, 82 deletions
diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb
index b362bb9555..9217d5ae0c 100644
--- a/actionpack/lib/action_view/base.rb
+++ b/actionpack/lib/action_view/base.rb
@@ -150,8 +150,8 @@ module ActionView #:nodoc:
class Base
include ERB::Util
- attr_reader :first_render, :finder
- attr_accessor :base_path, :assigns, :template_extension
+ attr_reader :finder
+ attr_accessor :base_path, :assigns, :template_extension, :first_render
attr_accessor :controller
attr_reader :logger, :response, :headers
@@ -173,12 +173,6 @@ module ActionView #:nodoc:
# Should be +false+ for development environments. Defaults to +true+.
@@cache_template_extensions = true
cattr_accessor :cache_template_extensions
-
- # Specify whether local_assigns should be able to use string keys.
- # Defaults to +true+. String keys are deprecated and will be removed
- # shortly.
- @@local_assigns_support_string_keys = true
- cattr_accessor :local_assigns_support_string_keys
# Specify whether RJS responses should be wrapped in a try/catch block
# that alert()s the caught exception (and then re-raises it).
@@ -282,41 +276,16 @@ If you are rendering a subtemplate, you must now use controller-like partial syn
END_ERROR
end
- # Clear the forward slash at the beginning if exists
- template_path = template_path.sub(/^\//, '') if use_full_path
-
- @first_render ||= template_path
- template_path_without_extension, template_extension = @finder.path_and_extension(template_path)
- if use_full_path
- if template_extension
- template_file_name = @finder.pick_template(template_path_without_extension, template_extension)
- else
- template_extension = @finder.pick_template_extension(template_path).to_s
- unless template_extension
- raise ActionViewError, "No template found for #{template_path} in #{@finder.view_paths.inspect}"
- end
- template_file_name = @finder.pick_template(template_path, template_extension)
- template_extension = template_extension.gsub(/^.+\./, '') # strip off any formats
- end
- else
- template_file_name = template_path
- end
-
- template_source = nil # Don't read the source until we know that it is required
-
- if template_file_name.blank?
- raise ActionViewError, "Couldn't find template file for #{template_path} in #{@finder.view_paths.inspect}"
- end
+ template = Template.new(self, template_path, use_full_path, local_assigns)
begin
- render_template(template_extension, template_source, template_file_name, local_assigns)
+ render_template(template)
rescue Exception => e
if TemplateError === e
- e.sub_template_of(template_file_name)
+ e.sub_template_of(template.filename)
raise e
else
- raise TemplateError.new(@finder.find_base_path_for("#{template_path_without_extension}.#{template_extension}") ||
- @finder.view_paths.first, template_file_name, @assigns, template_source, e)
+ raise TemplateError.new(template, @assigns, e)
end
end
end
@@ -350,22 +319,22 @@ If you are rendering a subtemplate, you must now use controller-like partial syn
elsif options[:partial]
render_partial(options[:partial], ActionView::Base::ObjectWrapper.new(options[:object]), options[:locals])
elsif options[:inline]
- render_template(options[:type], options[:inline], nil, options[:locals])
+ template = Template.new(self, options[:inline], false, options[:locals], true, options[:type])
+ render_template(template)
end
end
end
# Renders the +template+ which is given as a string as either erb or builder depending on <tt>template_extension</tt>.
# The hash in <tt>local_assigns</tt> is made available as local variables.
- def render_template(template_extension, template, file_path = nil, local_assigns = {}) #:nodoc:
- handler = self.class.handler_class_for_extension(template_extension).new(self)
- @current_render_extension = template_extension
+ def render_template(template) #:nodoc:
+ handler = template.handler
+ @current_render_extension = template.extension
if handler.compilable?
- compile_and_render_template(handler, template, file_path, local_assigns)
+ compile_and_render_template(handler, template)
else
- template ||= handler.read_template_file(file_path, template_extension) # Make sure that a lazyily-read template is loaded.
- handler.render(template, local_assigns)
+ handler.render(template.source, template.locals)
end
end
@@ -407,18 +376,15 @@ If you are rendering a subtemplate, you must now use controller-like partial syn
# Either, but not both, of template and file_path may be nil. If file_path is given, the template
# will only be read if it has to be compiled.
#
- def compile_and_render_template(handler, template = nil, file_path = nil, local_assigns = {}) #:nodoc:
- # convert string keys to symbols if requested
- local_assigns = local_assigns.symbolize_keys if @@local_assigns_support_string_keys
-
+ def compile_and_render_template(handler, template) #:nodoc:
# compile the given template, if necessary
- handler.compile_template(template, file_path, local_assigns)
+ handler.compile_template(template)
# Get the method name for this template and run it
- method_name = @@method_names[file_path || template]
+ method_name = @@method_names[template.method_key]
evaluate_assigns
- send(method_name, local_assigns) do |*name|
+ send(method_name, template.locals) do |*name|
instance_variable_get "@content_for_#{name.first || 'layout'}"
end
end
diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb
new file mode 100644
index 0000000000..a814d7b4e5
--- /dev/null
+++ b/actionpack/lib/action_view/template.rb
@@ -0,0 +1,65 @@
+module ActionView #:nodoc:
+ class Template #:nodoc:
+
+ attr_accessor :locals
+ attr_reader :handler, :path, :source, :extension, :filename, :path_without_extension
+
+ def initialize(view, path_or_source, use_full_path, locals = {}, inline = false, inline_type = nil)
+ @view = view
+ @finder = @view.finder
+
+ unless inline
+ # Clear the forward slash at the beginning if exists
+ @path = use_full_path ? path_or_source.sub(/^\//, '') : path_or_source
+ @view.first_render ||= @path
+ @source = nil # Don't read the source until we know that it is required
+ set_extension_and_file_name(use_full_path)
+ else
+ @source = path_or_source
+ @extension = inline_type
+ end
+ @locals = locals || {}
+ end
+
+ def source
+ @source ||= File.read(self.filename)
+ end
+
+ def method_key
+ @method_key ||= (@filename || @source)
+ end
+
+ def handler
+ @handler ||= @view.class.handler_class_for_extension(@extension).new(@view)
+ end
+
+ def base_path_for_exception
+ @finder.find_base_path_for("#{@path_without_extension}.#{@extension}") || @finder.view_paths.first
+ end
+
+ private
+
+ def set_extension_and_file_name(use_full_path)
+ @path_without_extension, @extension = @finder.path_and_extension(@path)
+ if use_full_path
+ if @extension
+ @filename = @finder.pick_template(@path_without_extension, @extension)
+ else
+ @extension = @finder.pick_template_extension(@path).to_s
+ unless @extension
+ raise ActionViewError, "No template found for #{@path} in #{@finder.view_paths.inspect}"
+ end
+ @filename = @finder.pick_template(@path, @extension)
+ @extension = @extension.gsub(/^.+\./, '') # strip off any formats
+ end
+ else
+ @filename = @path
+ end
+
+ if @filename.blank?
+ raise ActionViewError, "Couldn't find template file for #{@path} in #{@finder.view_paths.inspect}"
+ end
+ end
+
+ end
+end
diff --git a/actionpack/lib/action_view/template_error.rb b/actionpack/lib/action_view/template_error.rb
index 54e4cf099d..33357d50cb 100644
--- a/actionpack/lib/action_view/template_error.rb
+++ b/actionpack/lib/action_view/template_error.rb
@@ -6,10 +6,10 @@ module ActionView
attr_reader :original_exception
- def initialize(base_path, file_path, assigns, source, original_exception)
- @base_path, @assigns, @source, @original_exception =
- base_path, assigns.dup, source, original_exception
- @file_path = file_path
+ def initialize(template, assigns, original_exception)
+ @base_path = template.base_path_for_exception
+ @assigns, @source, @original_exception = assigns.dup, template.source, original_exception
+ @file_path = template.filename
@backtrace = compute_backtrace
end
diff --git a/actionpack/lib/action_view/template_handler.rb b/actionpack/lib/action_view/template_handler.rb
index 70fa02674f..687c0db4c6 100644
--- a/actionpack/lib/action_view/template_handler.rb
+++ b/actionpack/lib/action_view/template_handler.rb
@@ -30,10 +30,5 @@ module ActionView
# Called by CacheHelper#cache
def cache_fragment(block, name = {}, options = nil)
end
-
- # This method reads a template file.
- def read_template_file(template_path, extension)
- File.read(template_path)
- end
end
end
diff --git a/actionpack/lib/action_view/template_handlers/compilable.rb b/actionpack/lib/action_view/template_handlers/compilable.rb
index 6ab4f69558..110c90af0a 100644
--- a/actionpack/lib/action_view/template_handlers/compilable.rb
+++ b/actionpack/lib/action_view/template_handlers/compilable.rb
@@ -26,17 +26,15 @@ module ActionView
end
# Compile and evaluate the template's code
- def compile_template(template, file_name, local_assigns)
- return unless compile_template?(template, file_name, local_assigns)
+ def compile_template(template)
+ return unless compile_template?(template)
- template ||= read_template_file(file_name, nil)
-
- render_symbol = assign_method_name(template, file_name)
- render_source = create_template_source(template, render_symbol, local_assigns.keys)
+ render_symbol = assign_method_name(template)
+ render_source = create_template_source(template, render_symbol)
line_offset = self.template_args[render_symbol].size + self.line_offset
begin
- file_name = 'compiled-template' if file_name.blank?
+ file_name = template.filename || 'compiled-template'
ActionView::Base::CompiledTemplates.module_eval(render_source, file_name, -line_offset)
rescue Exception => e # errors from template code
if @view.logger
@@ -45,8 +43,7 @@ module ActionView
@view.logger.debug "Backtrace: #{e.backtrace.join("\n")}"
end
- raise ActionView::TemplateError.new(@view.finder.extract_base_path_from(file_name) ||
- @view.finder.view_paths.first, file_name || template, @view.assigns, template, e)
+ raise ActionView::TemplateError.new(template, @view.assigns, e)
end
self.compile_time[render_symbol] = Time.now
@@ -59,27 +56,26 @@ module ActionView
# 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,
# or if the file has changed on disk and checking file mods hasn't been disabled.
- def compile_template?(template, file_name, local_assigns)
- method_key = file_name || template
+ def compile_template?(template)
+ method_key = template.method_key
render_symbol = @view.method_names[method_key]
compile_time = self.compile_time[render_symbol]
- if compile_time && supports_local_assigns?(render_symbol, local_assigns)
- if file_name && !@view.cache_template_loading
- template_changed_since?(file_name, compile_time)
+ if compile_time && supports_local_assigns?(render_symbol, template.locals)
+ if template.filename && !@view.cache_template_loading
+ template_changed_since?(template.filename, compile_time)
end
else
true
end
end
- def assign_method_name(template, file_name)
- method_key = file_name || template
- @view.method_names[method_key] ||= compiled_method_name(template, file_name)
+ def assign_method_name(template)
+ @view.method_names[template.method_key] ||= compiled_method_name(template)
end
- def compiled_method_name(template, file_name)
- ['_run', self.class.to_s.demodulize.underscore, compiled_method_name_file_path_segment(file_name)].compact.join('_').to_sym
+ def compiled_method_name(template)
+ ['_run', self.class.to_s.demodulize.underscore, compiled_method_name_file_path_segment(template.filename)].compact.join('_').to_sym
end
def compiled_method_name_file_path_segment(file_name)
@@ -94,11 +90,11 @@ module ActionView
end
# Method to create the source code for a given template.
- def create_template_source(template, render_symbol, locals)
- body = compile(template)
+ def create_template_source(template, render_symbol)
+ body = compile(template.source)
self.template_args[render_symbol] ||= {}
- locals_keys = self.template_args[render_symbol].keys | locals
+ locals_keys = self.template_args[render_symbol].keys | template.locals.keys
self.template_args[render_symbol] = locals_keys.inject({}) { |h, k| h[k] = true; h }
locals_code = ""