aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack
diff options
context:
space:
mode:
authorYehuda Katz + Carl Lerche <ykatz+clerche@engineyard.com>2009-04-22 17:16:28 -0700
committerYehuda Katz and Carl Lerche <wycats@gmail.com>2009-04-22 17:24:41 -0700
commit0a132c2fe13fb2b8d5dade9cf6abd70601376287 (patch)
treecf9194a0a9df3cf36e7a1ffbe8b8e16274c94ee9 /actionpack
parentb2d6fdae353be4fca41d7ac1839f30d9737162fd (diff)
downloadrails-0a132c2fe13fb2b8d5dade9cf6abd70601376287.tar.gz
rails-0a132c2fe13fb2b8d5dade9cf6abd70601376287.tar.bz2
rails-0a132c2fe13fb2b8d5dade9cf6abd70601376287.zip
Refactor ActionView::Path
* Decouple from ActionController and ActionMailer * Bring back localization support. * Prepare to decouple templates from the filesystem. * Prepare to decouple localization from ActionView * Fix ActionMailer to take advantage of ActionView::Path
Diffstat (limited to 'actionpack')
-rw-r--r--actionpack/lib/action_controller/abstract/layouts.rb4
-rw-r--r--actionpack/lib/action_controller/abstract/renderer.rb2
-rw-r--r--actionpack/lib/action_controller/base/layout.rb2
-rw-r--r--actionpack/lib/action_controller/base/render.rb7
-rw-r--r--actionpack/lib/action_view/paths.rb6
-rw-r--r--actionpack/lib/action_view/render/partials.rb7
-rw-r--r--actionpack/lib/action_view/render/rendering.rb4
-rw-r--r--actionpack/lib/action_view/template/handlers.rb4
-rw-r--r--actionpack/lib/action_view/template/path.rb151
-rw-r--r--actionpack/lib/action_view/template/template.rb2
-rw-r--r--actionpack/test/abstract_controller/abstract_controller_test.rb4
-rw-r--r--actionpack/test/template/render_test.rb20
12 files changed, 131 insertions, 82 deletions
diff --git a/actionpack/lib/action_controller/abstract/layouts.rb b/actionpack/lib/action_controller/abstract/layouts.rb
index 478b301a26..0039e67c5a 100644
--- a/actionpack/lib/action_controller/abstract/layouts.rb
+++ b/actionpack/lib/action_controller/abstract/layouts.rb
@@ -38,7 +38,7 @@ module AbstractController
else
self.class_eval %{
def _layout
- if view_paths.find_by_parts?("#{_implied_layout_name}", formats, "layouts")
+ if view_paths.find_by_parts?("#{_implied_layout_name}", {:formats => formats}, "layouts")
"#{_implied_layout_name}"
else
super
@@ -62,7 +62,7 @@ module AbstractController
raise ArgumentError, "String, false, or nil expected; you passed #{name.inspect}"
end
- name && view_paths.find_by_parts(name, formats, "layouts")
+ name && view_paths.find_by_parts(name, {:formats => formats}, "layouts")
end
def _default_layout(require_layout = false)
diff --git a/actionpack/lib/action_controller/abstract/renderer.rb b/actionpack/lib/action_controller/abstract/renderer.rb
index a86eef889e..e31accbbfc 100644
--- a/actionpack/lib/action_controller/abstract/renderer.rb
+++ b/actionpack/lib/action_controller/abstract/renderer.rb
@@ -29,7 +29,7 @@ module AbstractController
def render_to_body(options = {})
name = options[:_template_name] || action_name
- template = options[:_template] || view_paths.find_by_parts(name.to_s, formats, options[:_prefix])
+ template = options[:_template] || view_paths.find_by_parts(name.to_s, {:formats => formats}, options[:_prefix])
_render_template(template, options)
end
diff --git a/actionpack/lib/action_controller/base/layout.rb b/actionpack/lib/action_controller/base/layout.rb
index 4fcef6c5d9..1ad5191c73 100644
--- a/actionpack/lib/action_controller/base/layout.rb
+++ b/actionpack/lib/action_controller/base/layout.rb
@@ -182,7 +182,7 @@ module ActionController #:nodoc:
def memoized_find_layout(layout, formats) #:nodoc:
return layout if layout.nil? || layout.respond_to?(:render)
prefix = layout.to_s =~ /layouts\// ? nil : "layouts"
- view_paths.find_by_parts(layout.to_s, formats, prefix)
+ view_paths.find_by_parts(layout.to_s, {:formats => formats}, prefix)
end
def find_layout(*args)
diff --git a/actionpack/lib/action_controller/base/render.rb b/actionpack/lib/action_controller/base/render.rb
index 606df58518..52934076e6 100644
--- a/actionpack/lib/action_controller/base/render.rb
+++ b/actionpack/lib/action_controller/base/render.rb
@@ -374,8 +374,13 @@ module ActionController
render_for_file(name.sub(/^\//, ''), [layout, true], options)
end
end
-
+
+ # ==== Arguments
+ # parts<Array[String, Array[Symbol*], String, Boolean]>::
+ # Example: ["show", [:html, :xml], "users", false]
def render_for_parts(parts, layout, 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?
diff --git a/actionpack/lib/action_view/paths.rb b/actionpack/lib/action_view/paths.rb
index 1d0279889c..e48088f344 100644
--- a/actionpack/lib/action_view/paths.rb
+++ b/actionpack/lib/action_view/paths.rb
@@ -33,18 +33,18 @@ module ActionView #:nodoc:
super(*objs.map { |obj| self.class.type_cast(obj) })
end
- def find_by_parts(path, extension = nil, prefix = nil, partial = false)
+ def find_by_parts(path, details = {}, prefix = nil, partial = false)
template_path = path.sub(/^\//, '')
each do |load_path|
- if template = load_path.find_by_parts(template_path, extension, prefix, partial)
+ if template = load_path.find_by_parts(template_path, details, prefix, partial)
return template
end
end
Template.new(path, self)
rescue ActionView::MissingTemplate => e
- extension ||= []
+ extension = details[:formats] || []
raise ActionView::MissingTemplate.new(self, "#{prefix}/#{path}.{#{extension.join(",")}}")
end
diff --git a/actionpack/lib/action_view/render/partials.rb b/actionpack/lib/action_view/render/partials.rb
index e337dcb63b..43f8a1edf8 100644
--- a/actionpack/lib/action_view/render/partials.rb
+++ b/actionpack/lib/action_view/render/partials.rb
@@ -187,6 +187,7 @@ module ActionView
path = ActionController::RecordIdentifier.partial_path(object, controller_path)
end
_, _, prefix, object = parts = partial_parts(path, options)
+ parts[1] = {:formats => parts[1]}
template = find_by_parts(*parts)
_render_partial_object(template, options, (object unless object == true))
end
@@ -225,7 +226,7 @@ module ActionView
def _render_partial_with_layout(layout, options)
if layout
prefix = controller && !layout.include?("/") ? controller.controller_path : nil
- layout = find_by_parts(layout, formats, prefix, true)
+ layout = find_by_parts(layout, {:formats => formats}, prefix, true)
end
content = _render_partial(options)
return _render_content_with_layout(content, layout, options[:locals])
@@ -253,7 +254,7 @@ module ActionView
def _render_partial_with_layout(layout, options)
if layout
prefix = controller && !layout.include?("/") ? controller.controller_path : nil
- layout = find_by_parts(layout, formats, prefix, true)
+ layout = find_by_parts(layout, {:formats => formats}, prefix, true)
end
content = _render_partial(options)
return _render_content_with_layout(content, layout, options[:locals])
@@ -321,7 +322,7 @@ module ActionView
def _pick_partial_template(partial_path) #:nodoc:
prefix = controller_path unless partial_path.include?('/')
- find_by_parts(partial_path, formats, prefix, true)
+ find_by_parts(partial_path, {:formats => formats}, prefix, true)
end
memoize :_pick_partial_template
end
diff --git a/actionpack/lib/action_view/render/rendering.rb b/actionpack/lib/action_view/render/rendering.rb
index a9b2acecd5..4213b09e48 100644
--- a/actionpack/lib/action_view/render/rendering.rb
+++ b/actionpack/lib/action_view/render/rendering.rb
@@ -23,10 +23,10 @@ module ActionView
return _render_partial_with_layout(layout, options) if options.key?(:partial)
return _render_partial_with_block(layout, block, options) if block_given?
- layout = find_by_parts(layout, formats) if layout
+ layout = find_by_parts(layout, {:formats => formats}) if layout
if file = options[:file]
- template = find_by_parts(file, formats)
+ template = find_by_parts(file, {:formats => formats})
_render_template_with_layout(template, layout, :locals => options[:locals])
elsif inline = options[:inline]
_render_inline(inline, layout, options)
diff --git a/actionpack/lib/action_view/template/handlers.rb b/actionpack/lib/action_view/template/handlers.rb
index fb85f28851..448ab6731b 100644
--- a/actionpack/lib/action_view/template/handlers.rb
+++ b/actionpack/lib/action_view/template/handlers.rb
@@ -16,6 +16,10 @@ module ActionView #:nodoc:
@@template_handlers = {}
@@default_template_handlers = nil
+
+ def self.extensions
+ @@template_handlers.keys
+ end
# Register a class that knows how to handle template files with the given
# extension. This can be used to implement new template types.
diff --git a/actionpack/lib/action_view/template/path.rb b/actionpack/lib/action_view/template/path.rb
index 9709549b70..660a7e91a2 100644
--- a/actionpack/lib/action_view/template/path.rb
+++ b/actionpack/lib/action_view/template/path.rb
@@ -1,13 +1,81 @@
module ActionView
class Template
+ # Abstract super class
class Path
- attr_reader :path, :paths
- delegate :hash, :inspect, :to => :path
-
def initialize(options)
- @cache = options[:cache]
+ @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
+
+ # 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
+ end
+
+ def handler_matcher
+ @handler_matcher ||= begin
+ e = valid_handlers.join('|')
+ /\.(?:#{e})$/
+ end
+ end
+
+ def handler_glob
+ e = TemplateHandlers.extensions.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 = 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))}\//, '')
@@ -27,61 +95,36 @@ module ActionView
def eql?(path)
to_str == path.to_str
end
-
- def find_by_parts(name, extensions = nil, prefix = nil, partial = nil)
- path = prefix ? "#{prefix}/" : ""
+ # ==== </suck>
- name = name.to_s.split("/")
- name[-1] = "_#{name[-1]}" if partial
-
- path << name.join("/")
-
- template = nil
-
- Array(extensions).each do |extension|
- extensioned_path = extension ? "#{path}.#{extension}" : path
- break if (template = find_template(extensioned_path))
+ def find_templates(name, details, prefix, partial)
+ if glob = parts_to_glob(name, details, prefix, partial)
+ cached(glob) do
+ Dir[glob].map do |path|
+ initialize_template(path) unless File.directory?(path)
+ end.compact
+ end
end
- template || find_template(path)
end
-
- private
- def create_template(file)
- Template.new(file.split("#{self}/").last, self)
- 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, @paths = path, {}
-
- # **/*/** is a hax for symlinked directories
- load_templates("#{@path}/{**/*,**}/**") if @cache
- end
-
- private
-
- def load_template(template)
- template.load!
- template.accessible_paths.each do |path|
- @paths[path] = template
- end
- end
-
- def find_template(path)
- load_templates("#{@path}/#{path}{,.*}") unless @cache
- @paths[path]
- end
- def load_templates(glob)
- Dir[glob].each do |file|
- load_template(create_template(file)) unless File.directory?(file)
+ private
+
+ def parts_to_glob(name, details, prefix, partial)
+ 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
+
+ "#{@path}/#{path}#{extensions}#{handler_glob}"
end
-
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 b6967a2013..e541336613 100644
--- a/actionpack/lib/action_view/template/template.rb
+++ b/actionpack/lib/action_view/template/template.rb
@@ -101,7 +101,7 @@ module ActionView #:nodoc:
end
def content_type
- format.gsub('.', '/')
+ format && format.gsub('.', '/')
end
private
diff --git a/actionpack/test/abstract_controller/abstract_controller_test.rb b/actionpack/test/abstract_controller/abstract_controller_test.rb
index 918062c7db..f1dcb39ef1 100644
--- a/actionpack/test/abstract_controller/abstract_controller_test.rb
+++ b/actionpack/test/abstract_controller/abstract_controller_test.rb
@@ -139,10 +139,10 @@ module AbstractController
private
def self.layout(formats)
begin
- view_paths.find_by_parts(name.underscore, formats, "layouts")
+ view_paths.find_by_parts(name.underscore, {:formats => formats}t, "layouts")
rescue ActionView::MissingTemplate
begin
- view_paths.find_by_parts("application", formats, "layouts")
+ view_paths.find_by_parts("application", {:formats => formats}, "layouts")
rescue ActionView::MissingTemplate
end
end
diff --git a/actionpack/test/template/render_test.rb b/actionpack/test/template/render_test.rb
index 8843f6fdd7..7191df0dfd 100644
--- a/actionpack/test/template/render_test.rb
+++ b/actionpack/test/template/render_test.rb
@@ -29,23 +29,19 @@ module RenderTestCases
end
def test_render_file_with_localization
- pending do
- begin
- old_locale = I18n.locale
- I18n.locale = :da
- assert_equal "Hey verden", @view.render(:file => "test/hello_world")
- ensure
- I18n.locale = old_locale
- end
+ begin
+ old_locale = I18n.locale
+ I18n.locale = :da
+ assert_equal "Hey verden", @view.render(:file => "test/hello_world")
+ ensure
+ I18n.locale = old_locale
end
end
def test_render_file_with_dashed_locale
old_locale = I18n.locale
- pending do
- I18n.locale = :"pt-BR"
- assert_equal "Ola mundo", @view.render(:file => "test/hello_world")
- end
+ I18n.locale = :"pt-BR"
+ assert_equal "Ola mundo", @view.render(:file => "test/hello_world")
ensure
I18n.locale = old_locale
end