aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_view/template/path.rb
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/lib/action_view/template/path.rb
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/lib/action_view/template/path.rb')
-rw-r--r--actionpack/lib/action_view/template/path.rb151
1 files changed, 97 insertions, 54 deletions
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