1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
module ActionView #:nodoc:
class PathSet < Array #:nodoc:
def self.type_cast(obj)
if obj.is_a?(String)
Path.new(obj)
else
obj
end
end
def initialize(*args)
super(*args).map! { |obj| self.class.type_cast(obj) }
end
def <<(obj)
super(self.class.type_cast(obj))
end
def concat(array)
super(array.map! { |obj| self.class.type_cast(obj) })
end
def insert(index, obj)
super(index, self.class.type_cast(obj))
end
def push(*objs)
super(*objs.map { |obj| self.class.type_cast(obj) })
end
def unshift(*objs)
super(*objs.map { |obj| self.class.type_cast(obj) })
end
class Path #:nodoc:
attr_reader :path, :paths
delegate :hash, :inspect, :to => :path
def initialize(path, load = false)
raise ArgumentError, "path already is a Path class" if path.is_a?(Path)
@path = path.freeze
reload! if load
end
def to_s
if defined?(RAILS_ROOT)
path.to_s.sub(/^#{Regexp.escape(File.expand_path(RAILS_ROOT))}\//, '')
else
path.to_s
end
end
def to_str
path.to_str
end
def ==(path)
to_str == path.to_str
end
def eql?(path)
to_str == path.to_str
end
# Returns a ActionView::Template object for the given path string. The
# input path should be relative to the view path directory,
# +hello/index.html.erb+. This method also has a special exception to
# match partial file names without a handler extension. So
# +hello/index.html+ will match the first template it finds with a
# known template extension, +hello/index.html.erb+. Template extensions
# should not be confused with format extensions +html+, +js+, +xml+,
# etc. A format must be supplied to match a formated file. +hello/index+
# will never match +hello/index.html.erb+.
#
# This method also has two different implementations, one that is "lazy"
# and makes file system calls every time and the other is cached,
# "eager" which looks up the template in an in memory index. The "lazy"
# version is designed for development where you want to automatically
# find new templates between requests. The "eager" version is designed
# for production mode and it is much faster but requires more time
# upfront to build the file index.
def [](path)
if loaded?
@paths[path]
else
Dir.glob("#{@path}/#{path}*").each do |file|
template = create_template(file)
if template.accessible_paths.include?(path)
return template
end
end
nil
end
end
def loaded?
@loaded ? true : false
end
def load
reload! unless loaded?
self
end
# Rebuild load path directory cache
def reload!
@paths = {}
templates_in_path do |template|
template.load!
template.accessible_paths.each do |path|
@paths[path] = template
end
end
@paths.freeze
@loaded = true
end
private
def templates_in_path
(Dir.glob("#{@path}/**/*/**") | Dir.glob("#{@path}/**")).each do |file|
yield create_template(file) unless File.directory?(file)
end
end
def create_template(file)
Template.new(file.split("#{self}/").last, self)
end
end
def load
each { |path| path.load }
end
def reload!
each { |path| path.reload! }
end
def find_template(original_template_path, format = nil)
return original_template_path if original_template_path.respond_to?(:render)
template_path = original_template_path.sub(/^\//, '')
each do |load_path|
if format && (template = load_path["#{template_path}.#{format}"])
return template
elsif template = load_path[template_path]
return template
end
end
Template.new(original_template_path, self)
end
end
end
|