aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_view
diff options
context:
space:
mode:
authorEmilio Tagua <miloops@gmail.com>2009-06-23 18:13:46 -0300
committerEmilio Tagua <miloops@gmail.com>2009-06-23 18:13:46 -0300
commitb9088dce07f8525cdb84a1312a77b81db79067d6 (patch)
tree72ace069842b074981ba814ef1c335271176ce27 /actionpack/lib/action_view
parent4864f92ee34e840307d968fa8b04972b6d786fe8 (diff)
parent4417a19b035d73eb46a5e06e296a4b1c8091bef1 (diff)
downloadrails-b9088dce07f8525cdb84a1312a77b81db79067d6.tar.gz
rails-b9088dce07f8525cdb84a1312a77b81db79067d6.tar.bz2
rails-b9088dce07f8525cdb84a1312a77b81db79067d6.zip
Merge commit 'rails/master'
Diffstat (limited to 'actionpack/lib/action_view')
-rw-r--r--actionpack/lib/action_view/base.rb55
-rw-r--r--actionpack/lib/action_view/helpers/active_record_helper.rb59
-rw-r--r--actionpack/lib/action_view/helpers/capture_helper.rb31
-rw-r--r--actionpack/lib/action_view/paths.rb2
-rw-r--r--actionpack/lib/action_view/render/partials.rb7
-rw-r--r--actionpack/lib/action_view/render/rendering.rb70
-rw-r--r--actionpack/lib/action_view/template/handlers/builder.rb3
-rw-r--r--actionpack/lib/action_view/template/handlers/rjs.rb1
-rw-r--r--actionpack/lib/action_view/template/path.rb152
-rw-r--r--actionpack/lib/action_view/template/resolver.rb150
-rw-r--r--actionpack/lib/action_view/template/template.rb4
-rw-r--r--actionpack/lib/action_view/template/text.rb2
12 files changed, 255 insertions, 281 deletions
diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb
index 4ab568b44c..45184f58fb 100644
--- a/actionpack/lib/action_view/base.rb
+++ b/actionpack/lib/action_view/base.rb
@@ -170,12 +170,13 @@ module ActionView #:nodoc:
attr_accessor :base_path, :assigns, :template_extension, :formats
attr_accessor :controller
+ attr_internal :captures
attr_accessor :output_buffer
class << self
delegate :erb_trim_mode=, :to => 'ActionView::TemplateHandlers::ERB'
- delegate :logger, :to => 'ActionController::Base'
+ delegate :logger, :to => 'ActionController::Base', :allow_nil => true
end
@@debug_rjs = false
@@ -229,38 +230,27 @@ module ActionView #:nodoc:
def initialize(view_paths = [], assigns_for_first_render = {}, controller = nil, formats = nil)#:nodoc:
@formats = formats || [:html]
- @assigns = assigns_for_first_render
- @assigns_added = nil
+ @assigns = assigns_for_first_render.each { |key, value| instance_variable_set("@#{key}", value) }
@controller = controller
@helpers = ProxyModule.new(self)
+ @_content_for = Hash.new {|h,k| h[k] = "" }
self.view_paths = view_paths
-
- @_first_render = nil
- @_current_render = nil
end
+ attr_internal :template
attr_reader :view_paths
def view_paths=(paths)
@view_paths = self.class.process_view_paths(paths)
end
- # Access the current template being rendered.
- # Returns a ActionView::Template object.
- def template
- @_current_render
- end
-
- def template=(template) #:nodoc:
- @_first_render ||= template
- @_current_render = template
- end
-
def with_template(current_template)
+ _evaluate_assigns_and_ivars
last_template, self.template = template, current_template
+ last_formats, self.formats = formats, [current_template.mime_type.to_sym] + Mime::SET.symbols
yield
ensure
- self.template = last_template
+ self.template, self.formats = last_template, last_formats
end
def punctuate_body!(part)
@@ -271,30 +261,19 @@ module ActionView #:nodoc:
# Evaluates the local assigns and controller ivars, pushes them to the view.
def _evaluate_assigns_and_ivars #:nodoc:
- unless @assigns_added
- @assigns.each { |key, value| instance_variable_set("@#{key}", value) }
- _copy_ivars_from_controller
- @assigns_added = true
- end
+ @assigns_added ||= _copy_ivars_from_controller
end
- private
+ private
- def _copy_ivars_from_controller #:nodoc:
- if @controller
- variables = @controller.instance_variable_names
- variables -= @controller.protected_instance_variables if @controller.respond_to?(:protected_instance_variables)
- variables.each { |name| instance_variable_set(name, @controller.instance_variable_get(name)) }
- end
+ def _copy_ivars_from_controller #:nodoc:
+ if @controller
+ variables = @controller.instance_variable_names
+ variables -= @controller.protected_instance_variables if @controller.respond_to?(:protected_instance_variables)
+ variables.each { |name| instance_variable_set(name, @controller.instance_variable_get(name)) }
end
+ true
+ end
- def _set_controller_content_type(content_type) #:nodoc:
- # TODO: Remove this method when new base is switched
- unless defined?(ActionController::Http)
- if controller.respond_to?(:response)
- controller.response.content_type ||= content_type
- end
- end
- end
end
end
diff --git a/actionpack/lib/action_view/helpers/active_record_helper.rb b/actionpack/lib/action_view/helpers/active_record_helper.rb
index 8b70200654..75cc651968 100644
--- a/actionpack/lib/action_view/helpers/active_record_helper.rb
+++ b/actionpack/lib/action_view/helpers/active_record_helper.rb
@@ -122,9 +122,9 @@ module ActionView
options.reverse_merge!(:prepend_text => '', :append_text => '', :css_class => 'formError')
if (obj = (object.respond_to?(:errors) ? object : instance_variable_get("@#{object}"))) &&
- (errors = obj.errors.on(method))
+ (errors = obj.errors[method])
content_tag("div",
- "#{options[:prepend_text]}#{ERB::Util.html_escape(errors.is_a?(Array) ? errors.first : errors)}#{options[:append_text]}",
+ "#{options[:prepend_text]}#{ERB::Util.html_escape(errors.first)}#{options[:append_text]}",
:class => options[:css_class]
)
else
@@ -247,59 +247,22 @@ module ActionView
end
end
- alias_method :tag_without_error_wrapping, :tag
- def tag(name, options)
- if object.respond_to?(:errors) && object.errors.respond_to?(:on)
- error_wrapping(tag_without_error_wrapping(name, options), object.errors.on(@method_name))
- else
- tag_without_error_wrapping(name, options)
- end
- end
-
- alias_method :content_tag_without_error_wrapping, :content_tag
- def content_tag(name, value, options)
- if object.respond_to?(:errors) && object.errors.respond_to?(:on)
- error_wrapping(content_tag_without_error_wrapping(name, value, options), object.errors.on(@method_name))
- else
- content_tag_without_error_wrapping(name, value, options)
- end
- end
-
- alias_method :to_date_select_tag_without_error_wrapping, :to_date_select_tag
- def to_date_select_tag(options = {}, html_options = {})
- if object.respond_to?(:errors) && object.errors.respond_to?(:on)
- error_wrapping(to_date_select_tag_without_error_wrapping(options, html_options), object.errors.on(@method_name))
- else
- to_date_select_tag_without_error_wrapping(options, html_options)
- end
- end
-
- alias_method :to_datetime_select_tag_without_error_wrapping, :to_datetime_select_tag
- def to_datetime_select_tag(options = {}, html_options = {})
- if object.respond_to?(:errors) && object.errors.respond_to?(:on)
- error_wrapping(to_datetime_select_tag_without_error_wrapping(options, html_options), object.errors.on(@method_name))
- else
- to_datetime_select_tag_without_error_wrapping(options, html_options)
+ %w(tag content_tag to_date_select_tag to_datetime_select_tag to_time_select_tag).each do |meth|
+ without = "#{meth}_without_error_wrapping"
+ define_method "#{meth}_with_error_wrapping" do |*args|
+ error_wrapping(send(without, *args))
end
+ alias_method_chain meth, :error_wrapping
end
- alias_method :to_time_select_tag_without_error_wrapping, :to_time_select_tag
- def to_time_select_tag(options = {}, html_options = {})
- if object.respond_to?(:errors) && object.errors.respond_to?(:on)
- error_wrapping(to_time_select_tag_without_error_wrapping(options, html_options), object.errors.on(@method_name))
+ def error_wrapping(html_tag)
+ if object.respond_to?(:errors) && object.errors.respond_to?(:full_messages) && object.errors[@method_name].any?
+ Base.field_error_proc.call(html_tag, self)
else
- to_time_select_tag_without_error_wrapping(options, html_options)
+ html_tag
end
end
- def error_wrapping(html_tag, has_error)
- has_error ? Base.field_error_proc.call(html_tag, self) : html_tag
- end
-
- def error_message
- object.errors.on(@method_name)
- end
-
def column_type
object.send(:column_for_attribute, @method_name).type
end
diff --git a/actionpack/lib/action_view/helpers/capture_helper.rb b/actionpack/lib/action_view/helpers/capture_helper.rb
index b4197479a0..c90acc5ac2 100644
--- a/actionpack/lib/action_view/helpers/capture_helper.rb
+++ b/actionpack/lib/action_view/helpers/capture_helper.rb
@@ -111,15 +111,32 @@ module ActionView
#
# WARNING: content_for is ignored in caches. So you shouldn't use it
# for elements that will be fragment cached.
- #
- # The deprecated way of accessing a content_for block is to use an instance variable
- # named <tt>@content_for_#{name_of_the_content_block}</tt>. The preferred usage is now
- # <tt><%= yield :footer %></tt>.
def content_for(name, content = nil, &block)
- ivar = "@content_for_#{name}"
content = capture(&block) if block_given?
- instance_variable_set(ivar, "#{instance_variable_get(ivar)}#{content}")
- nil
+ return @_content_for[name] << content if content
+ @_content_for[name]
+ end
+
+ # content_for? simply checks whether any content has been captured yet using content_for
+ # Useful to render parts of your layout differently based on what is in your views.
+ #
+ # ==== Examples
+ #
+ # Perhaps you will use different css in you layout if no content_for :right_column
+ #
+ # <%# This is the layout %>
+ # <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ # <head>
+ # <title>My Website</title>
+ # <%= yield :script %>
+ # </head>
+ # <body class="<%= content_for?(:right_col) ? 'one-column' : 'two-column' %>">
+ # <%= yield %>
+ # <%= yield :right_col %>
+ # </body>
+ # </html>
+ def content_for?(name)
+ @_content_for[name].present?
end
# Use an alternate output buffer for the duration of the block.
diff --git a/actionpack/lib/action_view/paths.rb b/actionpack/lib/action_view/paths.rb
index 95c56faf9c..074b475819 100644
--- a/actionpack/lib/action_view/paths.rb
+++ b/actionpack/lib/action_view/paths.rb
@@ -3,7 +3,7 @@ module ActionView #:nodoc:
def self.type_cast(obj)
if obj.is_a?(String)
cache = !defined?(Rails) || !Rails.respond_to?(:configuration) || Rails.configuration.cache_classes
- Template::FileSystemPathWithFallback.new(obj, :cache => cache)
+ FileSystemResolverWithFallback.new(obj, :cache => cache)
else
obj
end
diff --git a/actionpack/lib/action_view/render/partials.rb b/actionpack/lib/action_view/render/partials.rb
index eacf117bea..87314fff67 100644
--- a/actionpack/lib/action_view/render/partials.rb
+++ b/actionpack/lib/action_view/render/partials.rb
@@ -245,13 +245,6 @@ module ActionView
end
end
- def _render_partial_with_block(layout, block, options)
- @_proc_for_layout = block
- concat(_render_partial(options.merge(:partial => layout)))
- ensure
- @_proc_for_layout = nil
- end
-
def _render_partial_with_layout(layout, options)
if layout
prefix = controller && !layout.include?("/") ? controller.controller_path : nil
diff --git a/actionpack/lib/action_view/render/rendering.rb b/actionpack/lib/action_view/render/rendering.rb
index fe785e7b20..162e38c484 100644
--- a/actionpack/lib/action_view/render/rendering.rb
+++ b/actionpack/lib/action_view/render/rendering.rb
@@ -51,32 +51,60 @@ module ActionView
end
begin
- original_content_for_layout = @content_for_layout if defined?(@content_for_layout)
- @content_for_layout = content
+ old_content, @_content_for[:layout] = @_content_for[:layout], content
- @cached_content_for_layout = @content_for_layout
+ @cached_content_for_layout = @_content_for[:layout]
_render_template(layout, locals)
ensure
- @content_for_layout = original_content_for_layout
+ @_content_for[:layout] = old_content
end
end
+ # You can think of a layout as a method that is called with a block. This method
+ # returns the block that the layout is called with. If the user calls yield :some_name,
+ # the block, by default, returns content_for(:some_name). If the user calls yield,
+ # the default block returns content_for(:layout).
+ #
+ # The user can override this default by passing a block to the layout.
+ #
+ # ==== Example
+ #
+ # # The template
+ # <% render :layout => "my_layout" do %>Content<% end %>
+ #
+ # # The layout
+ # <html><% yield %></html>
+ #
+ # In this case, instead of the default block, which would return content_for(:layout),
+ # this method returns the block that was passed in to render layout, and the response
+ # would be <html>Content</html>.
+ #
+ # Finally, the block can take block arguments, which can be passed in by yield.
+ #
+ # ==== Example
+ #
+ # # The template
+ # <% render :layout => "my_layout" do |customer| %>Hello <%= customer.name %><% end %>
+ #
+ # # The layout
+ # <html><% yield Struct.new(:name).new("David") %></html>
+ #
+ # In this case, the layout would receive the block passed into <tt>render :layout</tt>,
+ # and the Struct specified in the layout would be passed into the block. The result
+ # would be <html>Hello David</html>.
+ def layout_proc(name)
+ @_default_layout ||= proc { |*names| @_content_for[names.first || :layout] }
+ !@_content_for.key?(name) && @_proc_for_layout || @_default_layout
+ end
+
def _render_template(template, local_assigns = {})
with_template(template) do
- _evaluate_assigns_and_ivars
- _set_controller_content_type(template.mime_type) if template.respond_to?(:mime_type)
-
template.render(self, local_assigns) do |*names|
- if !instance_variable_defined?(:"@content_for_#{names.first}") &&
- instance_variable_defined?(:@_proc_for_layout) && (proc = @_proc_for_layout)
- capture(*names, &proc)
- elsif instance_variable_defined?(ivar = :"@content_for_#{names.first || :layout}")
- instance_variable_get(ivar)
- end
+ capture(*names, &layout_proc(names.first))
end
end
rescue Exception => e
- if TemplateError === e
+ if e.is_a?(TemplateError)
e.sub_template_of(template)
raise e
else
@@ -101,20 +129,18 @@ module ActionView
end
def _render_template_with_layout(template, layout = nil, options = {}, partial = false)
- if controller && logger
- logger.info("Rendering #{template.identifier}" +
- (options[:status] ? " (#{options[:status]})" : ''))
- end
-
+ logger && logger.info("Rendering #{template.identifier}#{' (#{options[:status]})' if options[:status]}")
+
+ locals = options[:locals] || {}
+
content = if partial
object = partial unless partial == true
_render_partial_object(template, options, object)
else
- _render_template(template, options[:locals] || {})
+ _render_template(template, locals)
end
- return content unless layout
- _render_content_with_layout(content, layout, options[:locals] || {})
+ layout ? _render_content_with_layout(content, layout, locals) : content
end
end
end \ No newline at end of file
diff --git a/actionpack/lib/action_view/template/handlers/builder.rb b/actionpack/lib/action_view/template/handlers/builder.rb
index f412228752..abe140af0b 100644
--- a/actionpack/lib/action_view/template/handlers/builder.rb
+++ b/actionpack/lib/action_view/template/handlers/builder.rb
@@ -8,8 +8,7 @@ module ActionView
self.default_format = Mime::XML
def compile(template)
- "_set_controller_content_type(Mime::XML);" +
- "xml = ::Builder::XmlMarkup.new(:indent => 2);" +
+ "xml = ::Builder::XmlMarkup.new(:indent => 2);" +
"self.output_buffer = xml.target!;" +
template.source +
";xml.target!;"
diff --git a/actionpack/lib/action_view/template/handlers/rjs.rb b/actionpack/lib/action_view/template/handlers/rjs.rb
index a36744c2b7..b1d15dc209 100644
--- a/actionpack/lib/action_view/template/handlers/rjs.rb
+++ b/actionpack/lib/action_view/template/handlers/rjs.rb
@@ -6,7 +6,6 @@ module ActionView
self.default_format = Mime::JS
def compile(template)
- "@formats = [:html];" +
"controller.response.content_type ||= Mime::JS;" +
"update_page do |page|;#{template.source}\nend"
end
diff --git a/actionpack/lib/action_view/template/path.rb b/actionpack/lib/action_view/template/path.rb
deleted file mode 100644
index 478bf96c9a..0000000000
--- a/actionpack/lib/action_view/template/path.rb
+++ /dev/null
@@ -1,152 +0,0 @@
-require "pathname"
-
-module ActionView
- class Template
- # Abstract super class
- class Path
- def initialize(options)
- @cache = options[:cache]
- @cached = {}
- end
-
- # Normalizes the arguments and passes it on to find_template
- def find_by_parts(*args)
- find_all_by_parts(*args).first
- end
-
- def find_all_by_parts(name, details = {}, prefix = nil, partial = nil)
- details[:locales] = [I18n.locale]
- name = name.to_s.gsub(handler_matcher, '').split("/")
- find_templates(name.pop, details, [prefix, *name].compact.join("/"), partial)
- end
-
- private
-
- # This is what child classes implement. No defaults are needed
- # because Path guarentees that the arguments are present and
- # normalized.
- def find_templates(name, details, prefix, partial)
- raise NotImplementedError
- end
-
- def valid_handlers
- @valid_handlers ||= TemplateHandlers.extensions
- end
-
- def handler_matcher
- @handler_matcher ||= begin
- e = valid_handlers.join('|')
- /\.(?:#{e})$/
- end
- end
-
- def handler_glob
- e = TemplateHandlers.extensions.map{|h| ".#{h},"}.join
- "{#{e}}"
- end
-
- def formats_glob
- @formats_glob ||= begin
- formats = Mime::SET.map { |m| m.symbol }
- '{' + formats.map { |l| ".#{l}," }.join + '}'
- end
- end
-
- def cached(key)
- return yield unless @cache
- return @cached[key] if @cached.key?(key)
- @cached[key] = yield
- end
- end
-
- class FileSystemPath < Path
-
- def initialize(path, options = {})
- raise ArgumentError, "path already is a Path class" if path.is_a?(Path)
- super(options)
- @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
- path.to_s
- end
-
- def to_str
- path.to_s
- end
-
- def ==(path)
- to_str == path.to_str
- end
-
- def eql?(path)
- to_str == path.to_str
- end
- # ==== </suck>
-
- 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|
- 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
- end
-
- private
-
- # :api: plugin
- def details_to_glob(name, details, prefix, partial, root)
- path = ""
- path << "#{prefix}/" unless prefix.empty?
- path << (partial ? "_#{name}" : name)
-
- extensions = ""
- [:locales, :formats].each do |k|
- extensions << if exts = details[k]
- '{' + exts.map {|e| ".#{e},"}.join + '}'
- else
- k == :formats ? formats_glob : ''
- end
- end
-
- "#{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 \ No newline at end of file
diff --git a/actionpack/lib/action_view/template/resolver.rb b/actionpack/lib/action_view/template/resolver.rb
new file mode 100644
index 0000000000..d15f53a11b
--- /dev/null
+++ b/actionpack/lib/action_view/template/resolver.rb
@@ -0,0 +1,150 @@
+require "pathname"
+require "action_view/template/template"
+
+module ActionView
+ # Abstract superclass
+ class Resolver
+ def initialize(options)
+ @cache = options[:cache]
+ @cached = {}
+ end
+
+ # Normalizes the arguments and passes it on to find_template
+ def find_by_parts(*args)
+ find_all_by_parts(*args).first
+ end
+
+ def find_all_by_parts(name, details = {}, prefix = nil, partial = nil)
+ details[:locales] = [I18n.locale]
+ name = name.to_s.gsub(handler_matcher, '').split("/")
+ find_templates(name.pop, details, [prefix, *name].compact.join("/"), partial)
+ end
+
+ private
+
+ # This is what child classes implement. No defaults are needed
+ # because Resolver guarantees that the arguments are present and
+ # normalized.
+ def find_templates(name, details, prefix, partial)
+ raise NotImplementedError
+ end
+
+ def valid_handlers
+ @valid_handlers ||= TemplateHandlers.extensions
+ end
+
+ def handler_matcher
+ @handler_matcher ||= begin
+ e = valid_handlers.join('|')
+ /\.(?:#{e})$/
+ end
+ end
+
+ def handler_glob
+ e = TemplateHandlers.extensions.map{|h| ".#{h},"}.join
+ "{#{e}}"
+ end
+
+ def formats_glob
+ @formats_glob ||= begin
+ '{' + Mime::SET.symbols.map { |l| ".#{l}," }.join + '}'
+ end
+ end
+
+ def cached(key)
+ return yield unless @cache
+ return @cached[key] if @cached.key?(key)
+ @cached[key] = yield
+ end
+ end
+
+ class FileSystemResolver < Resolver
+
+ def initialize(path, options = {})
+ raise ArgumentError, "path already is a Resolver class" if path.is_a?(Resolver)
+ super(options)
+ @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
+ path.to_s
+ end
+
+ def to_str
+ path.to_s
+ end
+
+ def ==(path)
+ to_str == path.to_str
+ end
+
+ def eql?(path)
+ to_str == path.to_str
+ end
+ # ==== </suck>
+
+ 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|
+ 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
+ end
+
+ private
+
+ # :api: plugin
+ def details_to_glob(name, details, prefix, partial, root)
+ path = ""
+ path << "#{prefix}/" unless prefix.empty?
+ path << (partial ? "_#{name}" : name)
+
+ extensions = ""
+ [:locales, :formats].each do |k|
+ extensions << if exts = details[k]
+ '{' + exts.map {|e| ".#{e},"}.join + '}'
+ else
+ k == :formats ? formats_glob : ''
+ end
+ end
+
+ "#{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 FileSystemResolverWithFallback < FileSystemResolver
+
+ def find_templates(name, details, prefix, partial)
+ templates = super
+ return super(name, details, prefix, partial, '') if templates.empty?
+ templates
+ end
+
+ end
+end \ No newline at end of file
diff --git a/actionpack/lib/action_view/template/template.rb b/actionpack/lib/action_view/template/template.rb
index e7ea42c2eb..fac50cd692 100644
--- a/actionpack/lib/action_view/template/template.rb
+++ b/actionpack/lib/action_view/template/template.rb
@@ -2,7 +2,7 @@
# This is so that templates compiled in this file are UTF-8
require 'set'
-require "action_view/template/path"
+require "action_view/template/resolver"
module ActionView
class Template
@@ -20,7 +20,7 @@ module ActionView
handler.respond_to?(:default_format) ? handler.default_format.to_sym.to_s : "html"
end
@mime_type = Mime::Type.lookup_by_extension(format.to_s)
- @details[:formats] = Array.wrap(format && format.to_sym)
+ @details[:formats] = Array.wrap(format.to_sym)
end
def render(view, locals, &blk)
diff --git a/actionpack/lib/action_view/template/text.rb b/actionpack/lib/action_view/template/text.rb
index fd57b1677e..81944ff546 100644
--- a/actionpack/lib/action_view/template/text.rb
+++ b/actionpack/lib/action_view/template/text.rb
@@ -3,7 +3,7 @@ module ActionView #:nodoc:
def initialize(string, content_type = Mime[:html])
super(string.to_s)
- @content_type = Mime[content_type]
+ @content_type = Mime[content_type] || content_type
end
def details