Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Refactor ActionView::Template

  ActionView::Template is now completely independent from template
  storage, which allows different back ends such as the database.
  ActionView::Template's only responsibility is to take in the
  template source (passed in from ActionView::Path), compile it,
  and render it.
  • Loading branch information...
commit cecafc52ee0a4a53c903ddbaba95683261f88e5f 1 parent da3c21e
Yehuda Katz + Carl Lerche authored
Showing with 343 additions and 284 deletions.
  1. +15 −5 actionpack/lib/action_controller/base/base.rb
  2. +4 −3 actionpack/lib/action_controller/base/render.rb
  3. +5 −5 actionpack/lib/action_controller/testing/assertions/response.rb
  4. +3 −1 actionpack/lib/action_view/base.rb
  5. +6 −6 actionpack/lib/action_view/paths.rb
  6. +7 −6 actionpack/lib/action_view/render/rendering.rb
  7. +2 −2 actionpack/lib/action_view/template/error.rb
  8. +1 −1  actionpack/lib/action_view/template/handlers.rb
  9. +45 −23 actionpack/lib/action_view/template/path.rb
  10. +189 −147 actionpack/lib/action_view/template/template.rb
  11. +4 −3 actionpack/lib/action_view/test_case.rb
  12. +1 −1  actionpack/test/abstract_controller/abstract_controller_test.rb
  13. +1 −1  actionpack/test/controller/helper_test.rb
  14. +13 −11 actionpack/test/controller/layout_test.rb
  15. +3 −3 actionpack/test/controller/render_test.rb
  16. +29 −20 actionpack/test/controller/view_paths_test.rb
  17. 0  actionpack/test/fixtures/layouts/{standard.erb → standard.html.erb}
  18. +1 −0  actionpack/test/fixtures/test/render_file_with_locals_and_default.erb
  19. +5 −31 actionpack/test/template/compiled_templates_test.rb
  20. +3 −11 actionpack/test/template/render_test.rb
  21. +3 −1 activesupport/lib/active_support/core_ext/module/delegation.rb
  22. +2 −2 railties/test/plugin_loader_test.rb
  23. +1 −1  railties/test/plugin_test_helper.rb
View
20 actionpack/lib/action_controller/base/base.rb
@@ -494,8 +494,18 @@ def filter_parameter_logging(*filter_words, &block)
end
protected :filter_parameters
end
+
+ @@exempt_from_layout = [ActionView::TemplateHandlers::RJS]
+
+ def exempt_from_layout(*types)
+ types.each do |type|
+ @@exempt_from_layout <<
+ ActionView::Template.handler_class_for_extension(type)
+ end
+
+ @@exempt_from_layout
+ end
- delegate :exempt_from_layout, :to => 'ActionView::Template'
end
public
@@ -856,13 +866,13 @@ def perform_action
return (performed? ? ret : default_render) if called
begin
- default_render
- rescue ActionView::MissingTemplate => e
- raise e unless e.action_name == action_name
- # If the path is the same as the action_name, the action is completely missing
+ view_paths.find_by_parts(action_name, {:formats => formats, :locales => [I18n.locale]}, controller_path)
+ rescue => e
raise UnknownAction, "No action responded to #{action_name}. Actions: " +
"#{action_methods.sort.to_sentence}", caller
end
+
+ default_render
end
# Returns true if a render or redirect has already been performed.
View
7 actionpack/lib/action_controller/base/render.rb
@@ -378,13 +378,14 @@ def render_for_name(name, layout, options)
# ==== Arguments
# parts<Array[String, Array[Symbol*], String, Boolean]>::
# Example: ["show", [:html, :xml], "users", false]
- def render_for_parts(parts, layout, options = {})
+ def render_for_parts(parts, layout_details, options = {})
parts[1] = {:formats => parts[1], :locales => [I18n.locale]}
tmp = view_paths.find_by_parts(*parts)
- layout = _pick_layout(*layout) unless tmp.exempt_from_layout?
-
+ layout = _pick_layout(*layout_details) unless
+ self.class.exempt_from_layout.include?(tmp.handler)
+
render_for_text(
@template._render_template_with_layout(tmp, layout, options, parts[3]))
end
View
10 actionpack/lib/action_controller/testing/assertions/response.rb
@@ -98,22 +98,22 @@ def assert_template(options = {}, message = nil)
clean_backtrace do
case options
when NilClass, String
- rendered = @controller.response.rendered[:template].to_s
+ rendered = (@controller.response.rendered[:template] || []).map { |t| t.identifier }
msg = build_message(message,
"expecting <?> but rendering with <?>",
- options, rendered)
+ options, rendered.join(', '))
assert_block(msg) do
if options.nil?
@controller.response.rendered[:template].blank?
else
- rendered.to_s.match(options)
+ rendered.any? { |t| t.match(options) }
end
end
when Hash
if expected_partial = options[:partial]
partials = @controller.response.rendered[:partials]
if expected_count = options[:count]
- found = partials.detect { |p, _| p.to_s.match(expected_partial) }
+ found = partials.detect { |p, _| p.identifier.match(expected_partial) }
actual_count = found.nil? ? 0 : found.second
msg = build_message(message,
"expecting ? to be rendered ? time(s) but rendered ? time(s)",
@@ -123,7 +123,7 @@ def assert_template(options = {}, message = nil)
msg = build_message(message,
"expecting partial <?> but action rendered <?>",
options[:partial], partials.keys)
- assert(partials.keys.any? { |p| p.to_s.match(expected_partial) }, msg)
+ assert(partials.keys.any? { |p| p.identifier.match(expected_partial) }, msg)
end
else
assert @controller.response.rendered[:partials].empty?,
View
4 actionpack/lib/action_view/base.rb
@@ -196,7 +196,9 @@ def self.cache_template_loading?
delegate :controller_path, :to => :controller, :allow_nil => true
delegate :request_forgery_protection_token, :template, :params, :session, :cookies, :response, :headers,
- :flash, :logger, :action_name, :controller_name, :to => :controller
+ :flash, :action_name, :controller_name, :to => :controller
+
+ delegate :logger, :to => :controller, :allow_nil => true
delegate :find_by_parts, :to => :view_paths
View
12 actionpack/lib/action_view/paths.rb
@@ -3,7 +3,7 @@ class PathSet < Array #:nodoc:
def self.type_cast(obj)
if obj.is_a?(String)
cache = !Object.const_defined?(:Rails) || Rails.configuration.cache_classes
- Template::FileSystemPath.new(obj, :cache => cache)
+ Template::FileSystemPathWithFallback.new(obj, :cache => cache)
else
obj
end
@@ -34,18 +34,18 @@ def unshift(*objs)
end
def find_by_parts(path, details = {}, prefix = nil, partial = false)
- template_path = path.sub(/^\//, '')
+ # template_path = path.sub(/^\//, '')
+ template_path = path
each do |load_path|
if template = load_path.find_by_parts(template_path, details, prefix, partial)
return template
end
end
-
- Template.new(path, self)
- rescue ActionView::MissingTemplate => e
+
+ # TODO: Have a fallback absolute path?
extension = details[:formats] || []
- raise ActionView::MissingTemplate.new(self, "#{prefix}/#{path}.{#{extension.join(",")}}")
+ raise ActionView::MissingTemplate.new(self, "#{prefix}/#{path} - #{details.inspect} - partial: #{!!partial}")
end
def find_by_parts?(path, extension = nil, prefix = nil, partial = false)
View
13 actionpack/lib/action_view/render/rendering.rb
@@ -46,8 +46,8 @@ def _render_content_with_layout(content, layout, locals)
locals ||= {}
if controller && layout
- response.layout = layout.path_without_format_and_extension if controller.respond_to?(:response)
- logger.info("Rendering template within #{layout.path_without_format_and_extension}") if logger
+ response.layout = layout.identifier if controller.respond_to?(:response)
+ logger.info("Rendering template within #{layout.identifier}") if logger
end
begin
@@ -76,7 +76,6 @@ def _render_template(template, local_assigns = {})
end
end
rescue Exception => e
- raise e if template.is_a?(InlineTemplate) || !template.filename
if TemplateError === e
e.sub_template_of(template)
raise e
@@ -86,7 +85,9 @@ def _render_template(template, local_assigns = {})
end
def _render_inline(inline, layout, options)
- content = _render_template(InlineTemplate.new(options[:inline], options[:type]), options[:locals] || {})
+ handler = Template.handler_class_for_extension(options[:type] || "erb")
+ template = Template.new(options[:inline], "inline #{options[:inline].inspect}", handler, {})
+ content = _render_template(template, options[:locals] || {})
layout ? _render_content_with_layout(content, layout, options[:locals]) : content
end
@@ -96,7 +97,7 @@ def _render_text(text, layout, options)
def _render_template_with_layout(template, layout = nil, options = {}, partial = false)
if controller && logger
- logger.info("Rendering #{template.path_without_extension}" +
+ logger.info("Rendering #{template.identifier}" +
(options[:status] ? " (#{options[:status]})" : ''))
end
@@ -107,7 +108,7 @@ def _render_template_with_layout(template, layout = nil, options = {}, partial =
_render_template(template, options[:locals] || {})
end
- return content unless layout && !template.exempt_from_layout?
+ return content unless layout
_render_content_with_layout(content, layout, options[:locals] || {})
end
end
View
4 actionpack/lib/action_view/template/error.rb
@@ -12,7 +12,7 @@ def initialize(template, assigns, original_exception)
end
def file_name
- @template.relative_path
+ @template.identifier
end
def message
@@ -30,7 +30,7 @@ def clean_backtrace
def sub_template_message
if @sub_templates
"Trace of template inclusion: " +
- @sub_templates.collect { |template| template.relative_path }.join(", ")
+ @sub_templates.collect { |template| template.identifier }.join(", ")
else
""
end
View
2  actionpack/lib/action_view/template/handlers.rb
@@ -46,7 +46,7 @@ def register_default_template_handler(extension, klass)
end
def handler_class_for_extension(extension)
- registered_template_handler(extension) || @@default_template_handlers
+ (extension && registered_template_handler(extension.to_sym)) || @@default_template_handlers
end
end
end
View
68 actionpack/lib/action_view/template/path.rb
@@ -1,3 +1,5 @@
+require "pathname"
+
module ActionView
class Template
# Abstract super class
@@ -26,13 +28,6 @@ def find_all_by_parts(name, details = {}, prefix = nil, partial = nil)
def find_templates(name, details, prefix, partial)
raise NotImplementedError
end
-
- # TODO: Refactor this to abstract out the file system
- def initialize_template(file)
- t = Template.new(file.split("#{self}/").last, self)
- t.load!
- t
- end
def valid_handlers
@valid_handlers ||= TemplateHandlers.extensions
@@ -44,10 +39,10 @@ def handler_matcher
/\.(?:#{e})$/
end
end
-
+
def handler_glob
- e = TemplateHandlers.extensions.join(',')
- ".{#{e}}"
+ e = TemplateHandlers.extensions.map{|h| ".#{h},"}.join
+ "{#{e}}"
end
def formats_glob
@@ -69,23 +64,19 @@ class FileSystemPath < Path
def initialize(path, options = {})
raise ArgumentError, "path already is a Path class" if path.is_a?(Path)
super(options)
- @path = path
+ @path = Pathname.new(path).expand_path
end
-
+
# TODO: This is the currently needed API. Make this suck less
# ==== <suck>
attr_reader :path
def to_s
- if defined?(RAILS_ROOT)
- path.to_s.sub(/^#{Regexp.escape(File.expand_path(RAILS_ROOT))}\//, '')
- else
- path.to_s
- end
+ path.to_s
end
def to_str
- path.to_str
+ path.to_s
end
def ==(path)
@@ -97,11 +88,15 @@ def eql?(path)
end
# ==== </suck>
- def find_templates(name, details, prefix, partial)
- if glob = parts_to_glob(name, details, prefix, partial)
+ def find_templates(name, details, prefix, partial, root = "#{@path}/")
+ if glob = details_to_glob(name, details, prefix, partial, root)
cached(glob) do
Dir[glob].map do |path|
- initialize_template(path) unless File.directory?(path)
+ next if File.directory?(path)
+ source = File.read(path)
+ identifier = Pathname.new(path).expand_path.to_s
+
+ Template.new(source, identifier, *path_to_details(path))
end.compact
end
end
@@ -109,7 +104,8 @@ def find_templates(name, details, prefix, partial)
private
- def parts_to_glob(name, details, prefix, partial)
+ # :api: plugin
+ def details_to_glob(name, details, prefix, partial, root)
path = ""
path << "#{prefix}/" unless prefix.empty?
path << (partial ? "_#{name}" : name)
@@ -123,8 +119,34 @@ def parts_to_glob(name, details, prefix, partial)
end
end
- "#{@path}/#{path}#{extensions}#{handler_glob}"
+ "#{root}#{path}#{extensions}#{handler_glob}"
+ end
+
+ # TODO: fix me
+ # :api: plugin
+ def path_to_details(path)
+ # [:erb, :format => :html, :locale => :en, :partial => true/false]
+ if m = path.match(%r'/(_)?[\w-]+(\.[\w-]+)*\.(\w+)$')
+ partial = m[1] == '_'
+ details = (m[2]||"").split('.').reject { |e| e.empty? }
+ handler = Template.handler_class_for_extension(m[3])
+
+ format = Mime[details.last] && details.pop.to_sym
+ locale = details.last && details.pop.to_sym
+
+ return handler, :format => format, :locale => locale, :partial => partial
+ end
end
end
+
+ class FileSystemPathWithFallback < FileSystemPath
+
+ def find_templates(name, details, prefix, partial)
+ templates = super
+ return super(name, details, prefix, partial, '') if templates.empty?
+ templates
+ end
+
+ end
end
end
View
336 actionpack/lib/action_view/template/template.rb
@@ -1,188 +1,230 @@
+# encoding: utf-8
+# This is so that templates compiled in this file are UTF-8
+
require 'set'
require "action_view/template/path"
-module ActionView #:nodoc:
+module ActionView
class Template
extend TemplateHandlers
- extend ActiveSupport::Memoizable
+ attr_reader :source, :identifier, :handler
- module Loading
- def load!
- @cached = true
- # freeze
- end
+ def initialize(source, identifier, handler, details)
+ @source = source
+ @identifier = identifier
+ @handler = handler
+ @details = details
end
- include Loading
- include Renderable
-
- # Templates that are exempt from layouts
- @@exempt_from_layout = Set.new([/\.rjs$/])
-
- # Don't render layouts for templates with the given extensions.
- def self.exempt_from_layout(*extensions)
- regexps = extensions.collect do |extension|
- extension.is_a?(Regexp) ? extension : /\.#{Regexp.escape(extension.to_s)}$/
- end
- @@exempt_from_layout.merge(regexps)
+ def render(view, locals, &blk)
+ method_name = compile(locals, view)
+ view.send(method_name, locals, &blk)
+ end
+
+ # TODO: Figure out how to abstract this
+ def variable_name
+ identifier[%r'_?(\w+)(\.\w+)*$', 1].to_sym
end
- attr_accessor :template_path, :filename, :load_path, :base_path
- attr_accessor :locale, :name, :format, :extension
- delegate :to_s, :to => :path
+ # TODO: Figure out how to abstract this
+ def counter_name
+ "#{variable_name}_counter".to_sym
+ end
+
+ # TODO: kill hax
+ def partial?
+ @details[:partial]
+ end
+
+ # TODO: Move out of Template
+ def mime_type
+ Mime::Type.lookup_by_extension(@details[:format]) if @details[:format]
+ end
+
+ private
- def initialize(template_path, load_paths = [])
- template_path = template_path.dup
- @load_path, @filename = find_full_path(template_path, load_paths)
- @base_path, @name, @locale, @format, @extension = split(template_path)
- @base_path.to_s.gsub!(/\/$/, '') # Push to split method
+ def compile(locals, view)
+ method_name = build_method_name(locals)
+
+ return method_name if view.respond_to?(method_name)
+
+ locals_code = locals.keys.map! { |key| "#{key} = local_assigns[:#{key}];" }.join
+
+ source = <<-end_src
+ def #{method_name}(local_assigns)
+ old_output_buffer = output_buffer;#{locals_code};#{@handler.call(self)}
+ ensure
+ self.output_buffer = old_output_buffer
+ end
+ end_src
+
+ begin
+ ActionView::Base::CompiledTemplates.module_eval(source, identifier, 0)
+ method_name
+ rescue Exception => e # errors from template code
+ if logger = (view && view.logger)
+ logger.debug "ERROR: compiling #{method_name} RAISED #{e}"
+ logger.debug "Function body: #{source}"
+ logger.debug "Backtrace: #{e.backtrace.join("\n")}"
+ end
- # Extend with partial super powers
- extend RenderablePartial if @name =~ /^_/
+ raise ActionView::TemplateError.new(self, {}, e)
+ end
+ end
+
+ def build_method_name(locals)
+ # TODO: is locals.keys.hash reliably the same?
+ "_render_template_#{@identifier.hash}_#{__id__}_#{locals.keys.hash}".gsub('-', "_")
end
+ end
+end
+
+if false
+ module ActionView #:nodoc:
+ class Template
+ extend TemplateHandlers
+ extend ActiveSupport::Memoizable
- def accessible_paths
- paths = []
+ module Loading
+ def load!
+ @cached = true
+ # freeze
+ end
+ end
+ include Loading
+
+ include Renderable
- if valid_extension?(extension)
- paths << path
- paths << path_without_extension
- if multipart?
- formats = format.split(".")
- paths << "#{path_without_format_and_extension}.#{formats.first}"
- paths << "#{path_without_format_and_extension}.#{formats.second}"
+ # Templates that are exempt from layouts
+ @@exempt_from_layout = Set.new([/\.rjs$/])
+
+ # Don't render layouts for templates with the given extensions.
+ def self.exempt_from_layout(*extensions)
+ regexps = extensions.collect do |extension|
+ extension.is_a?(Regexp) ? extension : /\.#{Regexp.escape(extension.to_s)}$/
end
- else
- # template without explicit template handler should only be reachable through its exact path
- paths << template_path
+ @@exempt_from_layout.merge(regexps)
end
- paths
- end
+ attr_accessor :template_path, :filename, :load_path, :base_path
+ attr_accessor :locale, :name, :format, :extension
+ delegate :to_s, :to => :path
+
+ def initialize(template_path, load_paths = [])
+ template_path = template_path.dup
+ @load_path, @filename = find_full_path(template_path, load_paths)
+ @name = template_path.to_s.split("/").last.split(".").first
+ # @base_path, @name, @locale, @format, @extension = split(template_path)
+ @base_path.to_s.gsub!(/\/$/, '') # Push to split method
+
+ # Extend with partial super powers
+ extend RenderablePartial if @name =~ /^_/
+ end
- def relative_path
- path = File.expand_path(filename)
- path.sub!(/^#{Regexp.escape(File.expand_path(RAILS_ROOT))}\//, '') if defined?(RAILS_ROOT)
- path
- end
- memoize :relative_path
+ def accessible_paths
+ paths = []
+
+ if valid_extension?(extension)
+ paths << path
+ paths << path_without_extension
+ if multipart?
+ formats = format.split(".")
+ paths << "#{path_without_format_and_extension}.#{formats.first}"
+ paths << "#{path_without_format_and_extension}.#{formats.second}"
+ end
+ else
+ # template without explicit template handler should only be reachable through its exact path
+ paths << template_path
+ end
+
+ paths
+ end
- def source
- File.read(filename)
- end
- memoize :source
+ def relative_path
+ path = File.expand_path(filename)
+ path.sub!(/^#{Regexp.escape(File.expand_path(RAILS_ROOT))}\//, '') if defined?(RAILS_ROOT)
+ path
+ end
+ memoize :relative_path
- def exempt_from_layout?
- @@exempt_from_layout.any? { |exempted| path =~ exempted }
- end
+ def source
+ File.read(filename)
+ end
+ memoize :source
- def path_without_extension
- [base_path, [name, locale, format].compact.join('.')].compact.join('/')
- end
- memoize :path_without_extension
+ def exempt_from_layout?
+ @@exempt_from_layout.any? { |exempted| path =~ exempted }
+ end
+
+ def path_without_extension
+ [base_path, [name, locale, format].compact.join('.')].compact.join('/')
+ end
+ memoize :path_without_extension
- def path_without_format_and_extension
- [base_path, [name, locale].compact.join('.')].compact.join('/')
- end
- memoize :path_without_format_and_extension
+ def path_without_format_and_extension
+ [base_path, [name, locale].compact.join('.')].compact.join('/')
+ end
+ memoize :path_without_format_and_extension
- def path
- [base_path, [name, locale, format, extension].compact.join('.')].compact.join('/')
- end
- memoize :path
+ def path
+ [base_path, [name, locale, format, extension].compact.join('.')].compact.join('/')
+ end
+ memoize :path
- def mime_type
- Mime::Type.lookup_by_extension(format) if format && defined?(::Mime)
- end
- memoize :mime_type
+ def mime_type
+ Mime::Type.lookup_by_extension(format) if format && defined?(::Mime)
+ end
+ memoize :mime_type
- def multipart?
- format && format.include?('.')
- end
+ def multipart?
+ format && format.include?('.')
+ end
- def content_type
- format && format.gsub('.', '/')
- end
+ def content_type
+ format && format.gsub('.', '/')
+ end
- private
+ private
- def format_and_extension
- (extensions = [format, extension].compact.join(".")).blank? ? nil : extensions
- end
- memoize :format_and_extension
-
- def mtime
- File.mtime(filename)
- end
- memoize :mtime
+ def format_and_extension
+ (extensions = [format, extension].compact.join(".")).blank? ? nil : extensions
+ end
+ memoize :format_and_extension
- def method_segment
- relative_path.to_s.gsub(/([^a-zA-Z0-9_])/) { $1.ord }
- end
- memoize :method_segment
+ def mtime
+ File.mtime(filename)
+ end
+ memoize :mtime
- def stale?
- File.mtime(filename) > mtime
- end
+ def method_segment
+ relative_path.to_s.gsub(/([^a-zA-Z0-9_])/) { $1.ord }
+ end
+ memoize :method_segment
- def recompile?
- !@cached
- end
+ def stale?
+ File.mtime(filename) > mtime
+ end
- def valid_extension?(extension)
- !Template.registered_template_handler(extension).nil?
- end
+ def recompile?
+ !@cached
+ end
- def valid_locale?(locale)
- I18n.available_locales.include?(locale.to_sym)
- end
+ def valid_extension?(extension)
+ !Template.registered_template_handler(extension).nil?
+ end
- def find_full_path(path, load_paths)
- load_paths = Array(load_paths) + [nil]
- load_paths.each do |load_path|
- file = load_path ? "#{load_path.to_str}/#{path}" : path
- return load_path, file if File.file?(file)
+ def valid_locale?(locale)
+ I18n.available_locales.include?(locale.to_sym)
end
- raise MissingTemplate.new(load_paths, path)
- end
- # Returns file split into an array
- # [base_path, name, locale, format, extension]
- def split(file)
- if m = file.to_s.match(/^(.*\/)?([^\.]+)\.(.*)$/)
- base_path = m[1]
- name = m[2]
- extensions = m[3]
- else
- return
- end
-
- locale = nil
- format = nil
- extension = nil
-
- if m = extensions.split(".")
- if valid_locale?(m[0]) && m[1] && valid_extension?(m[2]) # All three
- locale = m[0]
- format = m[1]
- extension = m[2]
- elsif m[0] && m[1] && valid_extension?(m[2]) # Multipart formats
- format = "#{m[0]}.#{m[1]}"
- extension = m[2]
- elsif valid_locale?(m[0]) && valid_extension?(m[1]) # locale and extension
- locale = m[0]
- extension = m[1]
- elsif valid_extension?(m[1]) # format and extension
- format = m[0]
- extension = m[1]
- elsif valid_extension?(m[0]) # Just extension
- extension = m[0]
- else # No extension
- format = m[0]
+ def find_full_path(path, load_paths)
+ load_paths = Array(load_paths) + [nil]
+ load_paths.each do |load_path|
+ file = load_path ? "#{load_path.to_str}/#{path}" : path
+ return load_path, file if File.file?(file)
end
+ raise MissingTemplate.new(load_paths, path)
end
-
- [base_path, name, locale, format, extension]
end
end
-end
+end
View
7 actionpack/lib/action_view/test_case.rb
@@ -10,9 +10,10 @@ def initialize(*args)
alias_method :_render_template_without_template_tracking, :_render_template
def _render_template(template, local_assigns = {})
- if template.respond_to?(:path) && !template.is_a?(InlineTemplate)
- @_rendered[:partials][template] += 1 if template.is_a?(RenderablePartial)
- @_rendered[:template] ||= template
+ if template.respond_to?(:identifier)
+ @_rendered[:partials][template] += 1 if template.partial?
+ @_rendered[:template] ||= []
+ @_rendered[:template] << template
end
_render_template_without_template_tracking(template, local_assigns)
end
View
2  actionpack/test/abstract_controller/abstract_controller_test.rb
@@ -139,7 +139,7 @@ class WithLayouts < PrefixedViews
private
def self.layout(formats)
begin
- view_paths.find_by_parts(name.underscore, {:formats => formats}t, "layouts")
+ view_paths.find_by_parts(name.underscore, {:formats => formats}, "layouts")
rescue ActionView::MissingTemplate
begin
view_paths.find_by_parts("application", {:formats => formats}, "layouts")
View
2  actionpack/test/controller/helper_test.rb
@@ -211,7 +211,7 @@ def setup
end
def test_helper_in_a
- assert_raise(NameError) { A.process(@request, @response) }
+ assert_raise(ActionView::TemplateError) { A.process(@request, @response) }
end
def test_helper_in_b
View
24 actionpack/test/controller/layout_test.rb
@@ -56,8 +56,8 @@ def test_controller_name_layout_name_match
def test_third_party_template_library_auto_discovers_layout
@controller = ThirdPartyTemplateLibraryController.new
get :hello
- assert_equal 'layouts/third_party_template_library.mab', @controller.active_layout(true).to_s
- assert_equal 'layouts/third_party_template_library', @response.layout
+ assert @controller.active_layout(true).identifier.include?('layouts/third_party_template_library.mab')
+ assert @response.layout.include?('layouts/third_party_template_library')
assert_response :success
assert_equal 'Mab', @response.body
end
@@ -72,7 +72,7 @@ def test_namespaced_controllers_auto_detect_layouts
def test_namespaced_controllers_auto_detect_layouts
@controller = MultipleExtensions.new
get :hello
- assert_equal 'layouts/multiple_extensions.html.erb', @controller.active_layout(true).to_s
+ assert @controller.active_layout(true).identifier.include?('layouts/multiple_extensions.html.erb')
assert_equal 'multiple_extensions.html.erb hello.rhtml', @response.body.strip
end
end
@@ -116,22 +116,24 @@ def hello
end
class LayoutSetInResponseTest < ActionController::TestCase
+ include ActionView::TemplateHandlers
+
def test_layout_set_when_using_default_layout
@controller = DefaultLayoutController.new
get :hello
- assert_equal 'layouts/layout_test', @response.layout
+ assert @response.layout.include?('layouts/layout_test')
end
def test_layout_set_when_set_in_controller
@controller = HasOwnLayoutController.new
get :hello
- assert_equal 'layouts/item', @response.layout
+ assert @response.layout.include?('layouts/item')
end
def test_layout_only_exception_when_included
@controller = OnlyLayoutController.new
get :hello
- assert_equal 'layouts/item', @response.layout
+ assert @response.layout.include?('layouts/item')
end
def test_layout_only_exception_when_excepted
@@ -143,7 +145,7 @@ def test_layout_only_exception_when_excepted
def test_layout_except_exception_when_included
@controller = ExceptLayoutController.new
get :hello
- assert_equal 'layouts/item', @response.layout
+ assert @response.layout.include?('layouts/item')
end
def test_layout_except_exception_when_excepted
@@ -155,7 +157,7 @@ def test_layout_except_exception_when_excepted
def test_layout_set_when_using_render
@controller = SetsLayoutInRenderController.new
get :hello
- assert_equal 'layouts/third_party_template_library', @response.layout
+ assert @response.layout.include?('layouts/third_party_template_library')
end
def test_layout_is_not_set_when_none_rendered
@@ -165,14 +167,14 @@ def test_layout_is_not_set_when_none_rendered
end
def test_exempt_from_layout_honored_by_render_template
- ActionController::Base.exempt_from_layout :rhtml
+ ActionController::Base.exempt_from_layout :erb
@controller = RenderWithTemplateOptionController.new
get :hello
assert_equal "alt/hello.rhtml", @response.body.strip
ensure
- ActionController::Base.exempt_from_layout.delete(/\.rhtml$/)
+ ActionController::Base.exempt_from_layout.delete(ERB)
end
def test_layout_is_picked_from_the_controller_instances_view_path
@@ -232,7 +234,7 @@ def test_symlinked_layout_is_rendered
@controller = LayoutSymlinkedTest.new
get :hello
assert_response 200
- assert_equal "layouts/symlinked/symlinked_layout", @response.layout
+ assert @response.layout.include?("layouts/symlinked/symlinked_layout")
end
end
end
View
6 actionpack/test/controller/render_test.rb
@@ -773,7 +773,7 @@ def test_line_offset
begin
get :render_line_offset
flunk "the action should have raised an exception"
- rescue RuntimeError => exc
+ rescue StandardError => exc
line = exc.backtrace.first
assert(line =~ %r{:(\d+):})
assert_equal "1", $1,
@@ -1736,7 +1736,7 @@ def test_logger_prints_layout_and_template_rendering_info
@controller.logger = MockLogger.new
get :layout_test
logged = @controller.logger.logged.find_all {|l| l =~ /render/i }
- assert_equal "Rendering test/hello_world", logged[0]
- assert_equal "Rendering template within layouts/standard", logged[1]
+ assert logged[0] =~ %r{Rendering.*test/hello_world}
+ assert logged[1] =~ %r{Rendering template within.*layouts/standard}
end
end
View
49 actionpack/test/controller/view_paths_test.rb
@@ -20,7 +20,7 @@ class Test::SubController < ActionController::Base
layout 'test/sub'
def hello_world; render(:template => 'test/hello_world'); end
end
-
+
def setup
TestController.view_paths = nil
@@ -42,30 +42,39 @@ def teardown
ActiveSupport::Deprecation.behavior = @old_behavior
end
+ def expand(array)
+ array.map {|x| File.expand_path(x)}
+ end
+
+ def assert_paths(*paths)
+ controller = paths.first.is_a?(Class) ? paths.shift : @controller
+ assert_equal expand(paths), controller.view_paths.map(&:to_s)
+ end
+
def test_template_load_path_was_set_correctly
- assert_equal [FIXTURE_LOAD_PATH], @controller.view_paths.map(&:to_s)
+ assert_paths FIXTURE_LOAD_PATH
end
def test_controller_appends_view_path_correctly
@controller.append_view_path 'foo'
- assert_equal [FIXTURE_LOAD_PATH, 'foo'], @controller.view_paths.map(&:to_s)
+ assert_paths(FIXTURE_LOAD_PATH, "foo")
@controller.append_view_path(%w(bar baz))
- assert_equal [FIXTURE_LOAD_PATH, 'foo', 'bar', 'baz'], @controller.view_paths.map(&:to_s)
-
+ assert_paths(FIXTURE_LOAD_PATH, "foo", "bar", "baz")
+
@controller.append_view_path(FIXTURE_LOAD_PATH)
- assert_equal [FIXTURE_LOAD_PATH, 'foo', 'bar', 'baz', FIXTURE_LOAD_PATH], @controller.view_paths.map(&:to_s)
+ assert_paths(FIXTURE_LOAD_PATH, "foo", "bar", "baz", FIXTURE_LOAD_PATH)
end
def test_controller_prepends_view_path_correctly
@controller.prepend_view_path 'baz'
- assert_equal ['baz', FIXTURE_LOAD_PATH], @controller.view_paths.map(&:to_s)
+ assert_paths("baz", FIXTURE_LOAD_PATH)
@controller.prepend_view_path(%w(foo bar))
- assert_equal ['foo', 'bar', 'baz', FIXTURE_LOAD_PATH], @controller.view_paths.map(&:to_s)
+ assert_paths "foo", "bar", "baz", FIXTURE_LOAD_PATH
@controller.prepend_view_path(FIXTURE_LOAD_PATH)
- assert_equal [FIXTURE_LOAD_PATH, 'foo', 'bar', 'baz', FIXTURE_LOAD_PATH], @controller.view_paths.map(&:to_s)
+ assert_paths FIXTURE_LOAD_PATH, "foo", "bar", "baz", FIXTURE_LOAD_PATH
end
def test_template_appends_view_path_correctly
@@ -73,11 +82,11 @@ def test_template_appends_view_path_correctly
class_view_paths = TestController.view_paths
@controller.append_view_path 'foo'
- assert_equal [FIXTURE_LOAD_PATH, 'foo'], @controller.view_paths.map(&:to_s)
+ assert_paths FIXTURE_LOAD_PATH, "foo"
@controller.append_view_path(%w(bar baz))
- assert_equal [FIXTURE_LOAD_PATH, 'foo', 'bar', 'baz'], @controller.view_paths.map(&:to_s)
- assert_equal class_view_paths, TestController.view_paths
+ assert_paths FIXTURE_LOAD_PATH, "foo", "bar", "baz"
+ assert_paths TestController, *class_view_paths
end
def test_template_prepends_view_path_correctly
@@ -85,11 +94,11 @@ def test_template_prepends_view_path_correctly
class_view_paths = TestController.view_paths
@controller.prepend_view_path 'baz'
- assert_equal ['baz', FIXTURE_LOAD_PATH], @controller.view_paths.map(&:to_s)
+ assert_paths "baz", FIXTURE_LOAD_PATH
@controller.prepend_view_path(%w(foo bar))
- assert_equal ['foo', 'bar', 'baz', FIXTURE_LOAD_PATH], @controller.view_paths.map(&:to_s)
- assert_equal class_view_paths, TestController.view_paths
+ assert_paths "foo", "bar", "baz", FIXTURE_LOAD_PATH
+ assert_paths TestController, *class_view_paths
end
def test_view_paths
@@ -130,12 +139,12 @@ class C < ActionController::Base; end
A.view_paths = ['a/path']
- assert_equal ['a/path'], A.view_paths.map(&:to_s)
- assert_equal A.view_paths, B.view_paths
- assert_equal original_load_paths, C.view_paths
-
+ assert_paths A, "a/path"
+ assert_paths A, *B.view_paths
+ assert_paths C, *original_load_paths
+
C.view_paths = []
assert_nothing_raised { C.view_paths << 'c/path' }
- assert_equal ['c/path'], C.view_paths.map(&:to_s)
+ assert_paths C, "c/path"
end
end
View
0  ...onpack/test/fixtures/layouts/standard.erb → ...k/test/fixtures/layouts/standard.html.erb
File renamed without changes
View
1  actionpack/test/fixtures/test/render_file_with_locals_and_default.erb
@@ -0,0 +1 @@
+<%= secret ||= 'one' %>
View
36 actionpack/test/template/compiled_templates_test.rb
@@ -5,37 +5,13 @@ class CompiledTemplatesTest < Test::Unit::TestCase
def setup
@compiled_templates = ActionView::Base::CompiledTemplates
@compiled_templates.instance_methods.each do |m|
- @compiled_templates.send(:remove_method, m) if m =~ /^_run_/
+ @compiled_templates.send(:remove_method, m) if m =~ /^_render_template_/
end
end
-
- def test_template_gets_compiled
- assert_equal 0, @compiled_templates.instance_methods.size
- assert_equal "Hello world!", render(:file => "test/hello_world.erb")
- assert_equal 1, @compiled_templates.instance_methods.size
- end
-
+
def test_template_gets_recompiled_when_using_different_keys_in_local_assigns
- assert_equal 0, @compiled_templates.instance_methods.size
- assert_equal "Hello world!", render(:file => "test/hello_world.erb")
- assert_equal "Hello world!", render(:file => "test/hello_world.erb", :locals => {:foo => "bar"})
- assert_equal 2, @compiled_templates.instance_methods.size
- end
-
- def test_compiled_template_will_not_be_recompiled_when_rendered_with_identical_local_assigns
- assert_equal 0, @compiled_templates.instance_methods.size
- assert_equal "Hello world!", render(:file => "test/hello_world.erb")
- ActionView::Template.any_instance.expects(:compile!).never
- assert_equal "Hello world!", render(:file => "test/hello_world.erb")
- end
-
- def test_compiled_template_will_always_be_recompiled_when_template_is_not_cached
- ActionView::Template.any_instance.expects(:recompile?).times(3).returns(true)
- assert_equal 0, @compiled_templates.instance_methods.size
- assert_equal "Hello world!", render(:file => "#{FIXTURE_LOAD_PATH}/test/hello_world.erb")
- ActionView::Template.any_instance.expects(:compile!).times(3)
- 3.times { assert_equal "Hello world!", render(:file => "#{FIXTURE_LOAD_PATH}/test/hello_world.erb") }
- assert_equal 1, @compiled_templates.instance_methods.size
+ assert_equal "one", render(:file => "test/render_file_with_locals_and_default.erb")
+ assert_equal "two", render(:file => "test/render_file_with_locals_and_default.erb", :locals => { :secret => "two" })
end
def test_template_changes_are_not_reflected_with_cached_templates
@@ -61,14 +37,12 @@ def render(*args)
def render_with_cache(*args)
view_paths = ActionController::Base.view_paths
- assert_equal ActionView::Template::FileSystemPath, view_paths.first.class
ActionView::Base.new(view_paths, {}).render(*args)
end
def render_without_cache(*args)
- path = ActionView::Template::FileSystemPath.new(FIXTURE_LOAD_PATH)
+ path = ActionView::Template::FileSystemPathWithFallback.new(FIXTURE_LOAD_PATH)
view_paths = ActionView::Base.process_view_paths(path)
- assert_equal ActionView::Template::FileSystemPath, view_paths.first.class
ActionView::Base.new(view_paths, {}).render(*args)
end
View
14 actionpack/test/template/render_test.rb
@@ -91,10 +91,6 @@ def test_render_file_not_using_full_path_with_dot_in_path
assert_equal "The secret is in the sauce\n", @view.render(:file => "test/dot.directory/render_file_with_ivar")
end
- def test_render_has_access_current_template
- assert_equal "test/template.erb", @view.render(:file => "test/template.erb")
- end
-
def test_render_update
# TODO: You should not have to stub out template because template is self!
@view.instance_variable_set(:@template, @view)
@@ -240,10 +236,6 @@ def test_render_ignores_templates_with_malformed_template_handlers
end
end
- def test_template_with_malformed_template_handler_is_reachable_through_its_exact_filename
- assert_equal "Don't render me!", @view.render(:file => 'test/malformed/malformed.html.erb~')
- end
-
def test_render_with_layout
assert_equal %(<title></title>\nHello world!\n),
@view.render(:file => "test/hello_world.erb", :layout => "layouts/yield")
@@ -269,7 +261,7 @@ class CachedViewRenderTest < ActiveSupport::TestCase
# Ensure view path cache is primed
def setup
view_paths = ActionController::Base.view_paths
- assert_equal ActionView::Template::FileSystemPath, view_paths.first.class
+ assert_equal ActionView::Template::FileSystemPathWithFallback, view_paths.first.class
setup_view(view_paths)
end
end
@@ -280,9 +272,9 @@ class LazyViewRenderTest < ActiveSupport::TestCase
# Test the same thing as above, but make sure the view path
# is not eager loaded
def setup
- path = ActionView::Template::FileSystemPath.new(FIXTURE_LOAD_PATH)
+ path = ActionView::Template::FileSystemPathWithFallback.new(FIXTURE_LOAD_PATH)
view_paths = ActionView::Base.process_view_paths(path)
- assert_equal ActionView::Template::FileSystemPath, view_paths.first.class
+ assert_equal ActionView::Template::FileSystemPathWithFallback, view_paths.first.class
setup_view(view_paths)
end
end
View
4 activesupport/lib/active_support/core_ext/module/delegation.rb
@@ -110,8 +110,10 @@ def delegate(*methods)
allow_nil = options[:allow_nil] && "#{to} && "
+ file, line = caller[0].split(":")
+
methods.each do |method|
- module_eval(<<-EOS, "(__DELEGATION__)", 1)
+ module_eval(<<-EOS, file, line.to_i)
def #{prefix}#{method}(*args, &block) # def customer_name(*args, &block)
#{allow_nil}#{to}.__send__(#{method.inspect}, *args, &block) # client && client.__send__(:name, *args, &block)
end # end
View
4 railties/test/plugin_loader_test.rb
@@ -132,8 +132,8 @@ def test_engine_controllers_and_action_mailers_should_have_their_view_path_set_w
@loader.send :add_engine_view_paths
- assert_equal [ File.join(plugin_fixture_path('engines/engine'), 'app', 'views') ], ActionController::Base.view_paths
- assert_equal [ File.join(plugin_fixture_path('engines/engine'), 'app', 'views') ], ActionMailer::Base.view_paths
+ assert_equal [ File.join(plugin_fixture_path('engines/engine'), 'app', 'views') ], ActionController::Base.view_paths.map { |p| p.to_s }
+ assert_equal [ File.join(plugin_fixture_path('engines/engine'), 'app', 'views') ], ActionMailer::Base.view_paths.map { |p| p.to_s }
end
def test_should_add_plugin_load_paths_to_Dependencies_load_once_paths
View
2  railties/test/plugin_test_helper.rb
@@ -12,7 +12,7 @@
class Test::Unit::TestCase
private
def plugin_fixture_root_path
- File.join(File.dirname(__FILE__), 'fixtures', 'plugins')
+ File.expand_path(File.join(File.dirname(__FILE__), 'fixtures', 'plugins'))
end
def only_load_the_following_plugins!(plugins)
Please sign in to comment.
Something went wrong with that request. Please try again.