12808581a333707437b919d820aee796ef98addf
[depot.git] / template.rb
1 require 'action_controller/mime_type'
2
3 module ActionView #:nodoc:
4 class Template
5 extend TemplateHandlers
6 extend ActiveSupport::Memoizable
7 include Renderable
8
9 attr_accessor :filename, :load_path, :base_path, :name, :format, :extension
10 delegate :to_s, :to => :path
11
12 def initialize(template_path, load_paths = [])
13 template_path = template_path.dup
14 @base_path, @name, @format, @extension = split(template_path)
15 @base_path.to_s.gsub!(/\/$/, '') # Push to split method
16 @load_path, @filename = find_full_path(template_path, load_paths)
17
18 # Extend with partial super powers
19 extend RenderablePartial if @name =~ /^_/
20 end
21
22 def format_and_extension
23 (extensions = [format, extension].compact.join(".")).blank? ? nil : extensions
24 end
25 memoize :format_and_extension
26
27 def multipart?
28 format && format.include?('.')
29 end
30
31 def content_type
32 format.gsub('.', '/')
33 end
34
35 def mime_type
36 Mime::Type.lookup_by_extension(format) if format
37 end
38 memoize :mime_type
39
40 def path
41 [base_path, [name, format, extension].compact.join('.')].compact.join('/')
42 end
43 memoize :path
44
45 def path_without_extension
46 [base_path, [name, format].compact.join('.')].compact.join('/')
47 end
48 memoize :path_without_extension
49
50 def path_without_format_and_extension
51 [base_path, name].compact.join('/')
52 end
53 memoize :path_without_format_and_extension
54
55 def relative_path
56 path = File.expand_path(filename)
57 path.sub!(/^#{Regexp.escape(File.expand_path(RAILS_ROOT))}\//, '') if defined?(RAILS_ROOT)
58 path
59 end
60 memoize :relative_path
61
62 def source
63 File.read(filename)
64 end
65 memoize :source
66
67 def method_segment
68 relative_path.to_s.gsub(/([^a-zA-Z0-9_])/) { $1.ord }
69 end
70 memoize :method_segment
71
72 def render_template(view, local_assigns = {})
73 render(view, local_assigns)
74 rescue Exception => e
75 raise e unless filename
76 if TemplateError === e
77 e.sub_template_of(self)
78 raise e
79 else
80 raise TemplateError.new(self, view.assigns, e)
81 end
82 end
83
84 private
85 def valid_extension?(extension)
86 Template.template_handler_extensions.include?(extension)
87 end
88
89 def find_full_path(path, load_paths)
90 load_paths = Array(load_paths) + [nil]
91 load_paths.each do |load_path|
92 file = [load_path, path].compact.join('/')
93 return load_path, file if File.file?(file)
94 end
95 raise MissingTemplate.new(load_paths, path)
96 end
97
98 # Returns file split into an array
99 # [base_path, name, format, extension]
100 def split(file)
101 if m = file.match(/^(.*\/)?([^\.]+)\.?(\w+)?\.?(\w+)?\.?(\w+)?$/)
102 if m[5] # Multipart formats
103 [m[1], m[2], "#{m[3]}.#{m[4]}", m[5]]
104 elsif m[4] # Single format
105 [m[1], m[2], m[3], m[4]]
106 else
107 if valid_extension?(m[3]) # No format
108 [m[1], m[2], nil, m[3]]
109 else # No extension
110 [m[1], m[2], m[3], nil]
111 end
112 end
113 end
114 end
115 end
116 end