2009-04-22 19:41:06 -04:00
|
|
|
require 'set'
|
2009-04-14 20:22:51 -04:00
|
|
|
require "action_view/template/path"
|
|
|
|
|
2008-02-05 23:26:40 -05:00
|
|
|
module ActionView #:nodoc:
|
2008-07-12 15:33:46 -04:00
|
|
|
class Template
|
2008-07-03 22:08:27 -04:00
|
|
|
extend TemplateHandlers
|
2008-07-18 16:32:28 -04:00
|
|
|
extend ActiveSupport::Memoizable
|
2009-04-14 20:22:51 -04:00
|
|
|
|
|
|
|
module Loading
|
|
|
|
def load!
|
|
|
|
@cached = true
|
|
|
|
# freeze
|
|
|
|
end
|
|
|
|
end
|
|
|
|
include Loading
|
|
|
|
|
2008-07-05 13:05:50 -04:00
|
|
|
include Renderable
|
2008-07-03 14:06:00 -04:00
|
|
|
|
2008-12-21 18:23:53 -05:00
|
|
|
# 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)
|
|
|
|
end
|
|
|
|
|
2009-02-24 11:41:45 -05:00
|
|
|
attr_accessor :template_path, :filename, :load_path, :base_path
|
2009-01-25 23:50:02 -05:00
|
|
|
attr_accessor :locale, :name, :format, :extension
|
2008-07-12 15:33:46 -04:00
|
|
|
delegate :to_s, :to => :path
|
2008-02-05 23:26:40 -05:00
|
|
|
|
2008-07-12 15:33:46 -04:00
|
|
|
def initialize(template_path, load_paths = [])
|
|
|
|
template_path = template_path.dup
|
2008-12-03 14:58:47 -05:00
|
|
|
@load_path, @filename = find_full_path(template_path, load_paths)
|
2009-01-25 23:50:02 -05:00
|
|
|
@base_path, @name, @locale, @format, @extension = split(template_path)
|
2008-07-12 15:33:46 -04:00
|
|
|
@base_path.to_s.gsub!(/\/$/, '') # Push to split method
|
|
|
|
|
|
|
|
# Extend with partial super powers
|
|
|
|
extend RenderablePartial if @name =~ /^_/
|
|
|
|
end
|
2009-04-13 20:33:15 -04:00
|
|
|
|
2008-12-21 18:23:53 -05:00
|
|
|
def accessible_paths
|
|
|
|
paths = []
|
2009-02-24 11:41:45 -05:00
|
|
|
|
|
|
|
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
|
2008-12-21 18:23:53 -05:00
|
|
|
end
|
2009-02-24 11:41:45 -05:00
|
|
|
|
2008-12-21 18:23:53 -05:00
|
|
|
paths
|
|
|
|
end
|
2009-04-13 20:33:15 -04:00
|
|
|
|
|
|
|
def relative_path
|
|
|
|
path = File.expand_path(filename)
|
|
|
|
path.sub!(/^#{Regexp.escape(File.expand_path(RAILS_ROOT))}\//, '') if defined?(RAILS_ROOT)
|
|
|
|
path
|
2008-07-12 15:33:46 -04:00
|
|
|
end
|
2009-04-13 20:33:15 -04:00
|
|
|
memoize :relative_path
|
|
|
|
|
|
|
|
def source
|
|
|
|
File.read(filename)
|
2008-08-06 21:08:27 -04:00
|
|
|
end
|
2009-04-13 20:33:15 -04:00
|
|
|
memoize :source
|
|
|
|
|
|
|
|
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('/')
|
2008-08-06 21:08:27 -04:00
|
|
|
end
|
2009-04-13 20:33:15 -04:00
|
|
|
memoize :path_without_extension
|
2008-08-06 21:08:27 -04:00
|
|
|
|
2009-04-13 20:33:15 -04:00
|
|
|
def path_without_format_and_extension
|
|
|
|
[base_path, [name, locale].compact.join('.')].compact.join('/')
|
2008-07-18 21:14:12 -04:00
|
|
|
end
|
2009-04-13 20:33:15 -04:00
|
|
|
memoize :path_without_format_and_extension
|
|
|
|
|
2008-07-12 15:33:46 -04:00
|
|
|
def path
|
2009-01-25 23:50:02 -05:00
|
|
|
[base_path, [name, locale, format, extension].compact.join('.')].compact.join('/')
|
2008-07-12 15:33:46 -04:00
|
|
|
end
|
2008-07-14 21:02:59 -04:00
|
|
|
memoize :path
|
2009-04-13 20:33:15 -04:00
|
|
|
|
|
|
|
def mime_type
|
|
|
|
Mime::Type.lookup_by_extension(format) if format && defined?(::Mime)
|
2008-07-12 15:33:46 -04:00
|
|
|
end
|
2009-04-13 20:33:15 -04:00
|
|
|
memoize :mime_type
|
|
|
|
|
2009-04-16 14:57:27 -04:00
|
|
|
def multipart?
|
|
|
|
format && format.include?('.')
|
|
|
|
end
|
|
|
|
|
|
|
|
def content_type
|
2009-04-22 20:16:28 -04:00
|
|
|
format && format.gsub('.', '/')
|
2009-04-16 14:57:27 -04:00
|
|
|
end
|
|
|
|
|
2009-04-13 20:33:15 -04:00
|
|
|
private
|
|
|
|
|
|
|
|
def format_and_extension
|
|
|
|
(extensions = [format, extension].compact.join(".")).blank? ? nil : extensions
|
2008-07-12 15:33:46 -04:00
|
|
|
end
|
2009-04-13 20:33:15 -04:00
|
|
|
memoize :format_and_extension
|
2008-06-11 23:05:36 -04:00
|
|
|
|
2008-11-28 15:31:54 -05:00
|
|
|
def mtime
|
|
|
|
File.mtime(filename)
|
|
|
|
end
|
|
|
|
memoize :mtime
|
|
|
|
|
2008-07-12 15:33:46 -04:00
|
|
|
def method_segment
|
2008-09-20 23:57:45 -04:00
|
|
|
relative_path.to_s.gsub(/([^a-zA-Z0-9_])/) { $1.ord }
|
2008-07-12 15:33:46 -04:00
|
|
|
end
|
2008-07-14 21:02:59 -04:00
|
|
|
memoize :method_segment
|
2008-07-12 15:33:46 -04:00
|
|
|
|
2008-11-28 15:31:54 -05:00
|
|
|
def stale?
|
|
|
|
File.mtime(filename) > mtime
|
|
|
|
end
|
|
|
|
|
2008-12-29 20:27:19 -05:00
|
|
|
def recompile?
|
|
|
|
!@cached
|
2008-11-28 15:31:54 -05:00
|
|
|
end
|
|
|
|
|
2009-04-13 20:33:15 -04:00
|
|
|
def valid_extension?(extension)
|
|
|
|
!Template.registered_template_handler(extension).nil?
|
2008-11-28 15:31:54 -05:00
|
|
|
end
|
2008-06-11 23:05:36 -04:00
|
|
|
|
2009-04-13 20:33:15 -04:00
|
|
|
def valid_locale?(locale)
|
|
|
|
I18n.available_locales.include?(locale.to_sym)
|
|
|
|
end
|
2008-12-19 08:05:45 -05:00
|
|
|
|
2009-04-13 20:33:15 -04:00
|
|
|
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)
|
2009-01-25 23:50:02 -05:00
|
|
|
end
|
2009-04-13 20:33:15 -04:00
|
|
|
raise MissingTemplate.new(load_paths, path)
|
|
|
|
end
|
2009-01-25 23:50:02 -05:00
|
|
|
|
2009-04-13 20:33:15 -04:00
|
|
|
# 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
|
2008-06-11 23:05:36 -04:00
|
|
|
end
|
2008-07-05 17:27:43 -04:00
|
|
|
|
2009-04-13 20:33:15 -04:00
|
|
|
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]
|
2009-01-25 23:50:02 -05:00
|
|
|
end
|
2008-07-05 17:27:43 -04:00
|
|
|
end
|
2009-04-13 20:33:15 -04:00
|
|
|
|
|
|
|
[base_path, name, locale, format, extension]
|
|
|
|
end
|
2008-02-05 23:26:40 -05:00
|
|
|
end
|
|
|
|
end
|