2009-04-23 18:58:38 -04:00
|
|
|
require "pathname"
|
2009-09-02 18:00:22 -04:00
|
|
|
require "active_support/core_ext/class"
|
2010-01-31 21:32:28 -05:00
|
|
|
require "active_support/core_ext/array/wrap"
|
2009-12-02 23:01:01 -05:00
|
|
|
require "action_view/template"
|
2009-04-23 18:58:38 -04:00
|
|
|
|
2009-04-14 20:22:51 -04:00
|
|
|
module ActionView
|
2009-06-17 18:32:55 -04:00
|
|
|
class Resolver
|
2010-03-07 06:49:27 -05:00
|
|
|
def initialize
|
2010-03-08 14:39:15 -05:00
|
|
|
@cached = Hash.new { |h1,k1| h1[k1] =
|
|
|
|
Hash.new { |h2,k2| h2[k2] = Hash.new { |h3, k3| h3[k3] = {} } } }
|
2009-06-17 18:32:55 -04:00
|
|
|
end
|
|
|
|
|
2010-03-08 17:13:24 -05:00
|
|
|
def clear_cache
|
|
|
|
@cached.clear
|
|
|
|
end
|
|
|
|
|
2009-08-07 14:00:12 -04:00
|
|
|
def find(*args)
|
2009-09-02 18:00:22 -04:00
|
|
|
find_all(*args).first
|
2009-06-17 18:32:55 -04:00
|
|
|
end
|
2009-09-02 18:00:22 -04:00
|
|
|
|
2010-03-08 10:32:40 -05:00
|
|
|
# Normalizes the arguments and passes it on to find_template.
|
2010-03-08 17:13:24 -05:00
|
|
|
def find_all(name, prefix=nil, partial=false, details={}, key=nil)
|
2009-09-02 18:00:22 -04:00
|
|
|
name, prefix = normalize_name(name, prefix)
|
|
|
|
|
2010-03-08 14:39:15 -05:00
|
|
|
cached(key, prefix, name, partial) do
|
2010-03-08 17:13:24 -05:00
|
|
|
find_templates(name, prefix, partial, details)
|
2009-09-02 18:00:22 -04:00
|
|
|
end
|
2009-04-22 20:16:28 -04:00
|
|
|
end
|
2009-09-02 18:00:22 -04:00
|
|
|
|
2009-06-17 18:32:55 -04:00
|
|
|
private
|
|
|
|
|
2010-03-07 06:49:27 -05:00
|
|
|
def caching?
|
|
|
|
@caching ||= !defined?(Rails.application) || Rails.application.config.cache_classes
|
|
|
|
end
|
|
|
|
|
2009-06-17 18:32:55 -04:00
|
|
|
# This is what child classes implement. No defaults are needed
|
|
|
|
# because Resolver guarantees that the arguments are present and
|
|
|
|
# normalized.
|
2010-03-08 17:13:24 -05:00
|
|
|
def find_templates(name, prefix, partial, details)
|
2009-06-17 18:32:55 -04:00
|
|
|
raise NotImplementedError
|
|
|
|
end
|
|
|
|
|
2009-09-02 18:00:22 -04:00
|
|
|
# Support legacy foo.erb names even though we now ignore .erb
|
|
|
|
# as well as incorrectly putting part of the path in the template
|
|
|
|
# name instead of the prefix.
|
|
|
|
def normalize_name(name, prefix)
|
2009-12-02 23:01:01 -05:00
|
|
|
handlers = Template::Handlers.extensions.join('|')
|
2009-09-02 18:00:22 -04:00
|
|
|
name = name.to_s.gsub(/\.(?:#{handlers})$/, '')
|
|
|
|
|
|
|
|
parts = name.split('/')
|
|
|
|
return parts.pop, [prefix, *parts].compact.join("/")
|
2009-06-17 18:32:55 -04:00
|
|
|
end
|
2009-04-14 20:22:51 -04:00
|
|
|
|
2010-03-08 14:39:15 -05:00
|
|
|
def cached(key, prefix, name, partial)
|
|
|
|
return yield unless key && caching?
|
|
|
|
scope = @cached[key][prefix][name]
|
|
|
|
if scope.key?(partial)
|
|
|
|
scope[partial]
|
|
|
|
else
|
|
|
|
scope[partial] = yield
|
|
|
|
end
|
2009-06-17 18:32:55 -04:00
|
|
|
end
|
|
|
|
end
|
2009-04-14 20:22:51 -04:00
|
|
|
|
2009-09-02 18:00:22 -04:00
|
|
|
class PathResolver < Resolver
|
|
|
|
EXTENSION_ORDER = [:locale, :formats, :handlers]
|
2009-06-17 18:32:55 -04:00
|
|
|
|
|
|
|
def to_s
|
2009-09-01 18:54:29 -04:00
|
|
|
@path.to_s
|
2009-06-17 18:32:55 -04:00
|
|
|
end
|
2010-03-08 10:32:40 -05:00
|
|
|
alias :to_path :to_s
|
|
|
|
|
|
|
|
private
|
2009-06-17 18:32:55 -04:00
|
|
|
|
2010-03-08 17:13:24 -05:00
|
|
|
def find_templates(name, prefix, partial, details)
|
|
|
|
path = build_path(name, prefix, partial, details)
|
2009-09-02 18:00:22 -04:00
|
|
|
query(path, EXTENSION_ORDER.map { |ext| details[ext] })
|
2009-06-17 18:32:55 -04:00
|
|
|
end
|
2009-09-02 18:00:22 -04:00
|
|
|
|
2010-03-08 17:13:24 -05:00
|
|
|
def build_path(name, prefix, partial, details)
|
2009-09-02 18:00:22 -04:00
|
|
|
path = ""
|
|
|
|
path << "#{prefix}/" unless prefix.empty?
|
|
|
|
path << (partial ? "_#{name}" : name)
|
|
|
|
path
|
|
|
|
end
|
|
|
|
|
|
|
|
def query(path, exts)
|
2010-02-01 19:47:31 -05:00
|
|
|
query = File.join(@path, path)
|
2009-09-02 18:00:22 -04:00
|
|
|
exts.each do |ext|
|
|
|
|
query << '{' << ext.map {|e| e && ".#{e}" }.join(',') << '}'
|
2009-08-09 08:46:50 -04:00
|
|
|
end
|
2009-09-02 18:00:22 -04:00
|
|
|
|
2009-12-28 19:28:26 -05:00
|
|
|
Dir[query].reject { |p| File.directory?(p) }.map do |p|
|
|
|
|
Template.new(File.read(p), File.expand_path(p), *path_to_details(p))
|
|
|
|
end
|
2009-04-14 20:22:51 -04:00
|
|
|
end
|
2009-04-23 18:58:38 -04:00
|
|
|
|
2009-09-02 18:00:22 -04:00
|
|
|
# # TODO: fix me
|
|
|
|
# # :api: plugin
|
2009-06-17 18:32:55 -04:00
|
|
|
def path_to_details(path)
|
|
|
|
# [:erb, :format => :html, :locale => :en, :partial => true/false]
|
2010-01-26 14:43:35 -05:00
|
|
|
if m = path.match(%r'((^|.*/)(_)?[\w-]+)((?:\.[\w-]+)*)\.(\w+)$')
|
|
|
|
partial = m[3] == '_'
|
|
|
|
details = (m[4]||"").split('.').reject { |e| e.empty? }
|
|
|
|
handler = Template.handler_class_for_extension(m[5])
|
2009-06-17 18:32:55 -04:00
|
|
|
|
|
|
|
format = Mime[details.last] && details.pop.to_sym
|
|
|
|
locale = details.last && details.pop.to_sym
|
|
|
|
|
2010-01-26 14:43:35 -05:00
|
|
|
virtual_path = (m[1].gsub("#{@path}/", "") << details.join("."))
|
|
|
|
|
|
|
|
return handler, :format => format, :locale => locale, :partial => partial,
|
|
|
|
:virtual_path => virtual_path
|
2009-04-23 18:58:38 -04:00
|
|
|
end
|
|
|
|
end
|
2009-04-14 20:22:51 -04:00
|
|
|
end
|
2009-06-17 18:32:55 -04:00
|
|
|
|
2009-09-02 18:00:22 -04:00
|
|
|
class FileSystemResolver < PathResolver
|
2010-03-07 06:49:27 -05:00
|
|
|
def initialize(path)
|
2009-09-02 18:00:22 -04:00
|
|
|
raise ArgumentError, "path already is a Resolver class" if path.is_a?(Resolver)
|
2010-03-07 06:49:27 -05:00
|
|
|
super()
|
2009-09-02 18:00:22 -04:00
|
|
|
@path = Pathname.new(path).expand_path
|
|
|
|
end
|
2009-06-17 18:32:55 -04:00
|
|
|
|
2010-03-08 10:32:40 -05:00
|
|
|
def eql?(resolver)
|
|
|
|
self.class.equal?(resolver.class) && to_path == resolver.to_path
|
2009-09-02 18:00:22 -04:00
|
|
|
end
|
2010-03-08 10:32:40 -05:00
|
|
|
alias :== :eql?
|
2009-06-17 18:32:55 -04:00
|
|
|
end
|
2009-12-28 19:28:26 -05:00
|
|
|
end
|