actionview 6.0.0.beta1 → 6.0.1.rc1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of actionview might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +90 -3
- data/README.rdoc +3 -1
- data/lib/action_view.rb +2 -1
- data/lib/action_view/base.rb +107 -10
- data/lib/action_view/cache_expiry.rb +54 -0
- data/lib/action_view/context.rb +0 -5
- data/lib/action_view/digestor.rb +8 -17
- data/lib/action_view/gem_version.rb +2 -2
- data/lib/action_view/helpers/asset_tag_helper.rb +5 -5
- data/lib/action_view/helpers/cache_helper.rb +5 -5
- data/lib/action_view/helpers/csp_helper.rb +4 -2
- data/lib/action_view/helpers/form_helper.rb +2 -2
- data/lib/action_view/helpers/form_options_helper.rb +4 -3
- data/lib/action_view/helpers/form_tag_helper.rb +5 -2
- data/lib/action_view/helpers/output_safety_helper.rb +1 -1
- data/lib/action_view/helpers/rendering_helper.rb +6 -4
- data/lib/action_view/helpers/sanitize_helper.rb +10 -16
- data/lib/action_view/helpers/tag_helper.rb +1 -1
- data/lib/action_view/helpers/tags/base.rb +1 -1
- data/lib/action_view/helpers/translation_helper.rb +3 -3
- data/lib/action_view/helpers/url_helper.rb +2 -2
- data/lib/action_view/layouts.rb +5 -5
- data/lib/action_view/lookup_context.rb +69 -27
- data/lib/action_view/path_set.rb +5 -10
- data/lib/action_view/railtie.rb +9 -4
- data/lib/action_view/renderer/abstract_renderer.rb +56 -3
- data/lib/action_view/renderer/partial_renderer.rb +66 -55
- data/lib/action_view/renderer/partial_renderer/collection_caching.rb +27 -20
- data/lib/action_view/renderer/renderer.rb +16 -4
- data/lib/action_view/renderer/streaming_template_renderer.rb +4 -4
- data/lib/action_view/renderer/template_renderer.rb +24 -18
- data/lib/action_view/rendering.rb +46 -27
- data/lib/action_view/template.rb +84 -69
- data/lib/action_view/template/error.rb +21 -1
- data/lib/action_view/template/handlers.rb +27 -1
- data/lib/action_view/template/handlers/builder.rb +2 -2
- data/lib/action_view/template/handlers/erb.rb +5 -5
- data/lib/action_view/template/handlers/erb/erubi.rb +7 -3
- data/lib/action_view/template/handlers/html.rb +1 -1
- data/lib/action_view/template/handlers/raw.rb +2 -2
- data/lib/action_view/template/html.rb +14 -5
- data/lib/action_view/template/inline.rb +22 -0
- data/lib/action_view/template/raw_file.rb +28 -0
- data/lib/action_view/template/resolver.rb +80 -117
- data/lib/action_view/template/sources.rb +13 -0
- data/lib/action_view/template/sources/file.rb +17 -0
- data/lib/action_view/template/text.rb +5 -3
- data/lib/action_view/testing/resolvers.rb +33 -20
- data/lib/action_view/unbound_template.rb +32 -0
- data/lib/action_view/view_paths.rb +25 -1
- data/lib/assets/compiled/rails-ujs.js +21 -12
- metadata +25 -16
@@ -109,7 +109,7 @@ module ActionView
|
|
109
109
|
end
|
110
110
|
end
|
111
111
|
|
112
|
-
def
|
112
|
+
def annotated_source_code
|
113
113
|
source_extract(4)
|
114
114
|
end
|
115
115
|
|
@@ -138,4 +138,24 @@ module ActionView
|
|
138
138
|
end
|
139
139
|
|
140
140
|
TemplateError = Template::Error
|
141
|
+
|
142
|
+
class SyntaxErrorInTemplate < TemplateError #:nodoc
|
143
|
+
def initialize(template, offending_code_string)
|
144
|
+
@offending_code_string = offending_code_string
|
145
|
+
super(template)
|
146
|
+
end
|
147
|
+
|
148
|
+
def message
|
149
|
+
<<~MESSAGE
|
150
|
+
Encountered a syntax error while rendering template: check #{@offending_code_string}
|
151
|
+
MESSAGE
|
152
|
+
end
|
153
|
+
|
154
|
+
def annotated_source_code
|
155
|
+
@offending_code_string.split("\n").map.with_index(1) { |line, index|
|
156
|
+
indentation = " " * 4
|
157
|
+
"#{index}:#{indentation}#{line}"
|
158
|
+
}
|
159
|
+
end
|
160
|
+
end
|
141
161
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/deprecation"
|
4
|
+
|
3
5
|
module ActionView #:nodoc:
|
4
6
|
# = Action View Template Handlers
|
5
7
|
class Template #:nodoc:
|
@@ -14,7 +16,7 @@ module ActionView #:nodoc:
|
|
14
16
|
base.register_template_handler :erb, ERB.new
|
15
17
|
base.register_template_handler :html, Html.new
|
16
18
|
base.register_template_handler :builder, Builder.new
|
17
|
-
base.register_template_handler :ruby,
|
19
|
+
base.register_template_handler :ruby, lambda { |_, source| source }
|
18
20
|
end
|
19
21
|
|
20
22
|
@@template_handlers = {}
|
@@ -24,11 +26,35 @@ module ActionView #:nodoc:
|
|
24
26
|
@@template_extensions ||= @@template_handlers.keys
|
25
27
|
end
|
26
28
|
|
29
|
+
class LegacyHandlerWrapper < SimpleDelegator # :nodoc:
|
30
|
+
def call(view, source)
|
31
|
+
__getobj__.call(ActionView::Template::LegacyTemplate.new(view, source))
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
27
35
|
# Register an object that knows how to handle template files with the given
|
28
36
|
# extensions. This can be used to implement new template types.
|
29
37
|
# The handler must respond to +:call+, which will be passed the template
|
30
38
|
# and should return the rendered template as a String.
|
31
39
|
def register_template_handler(*extensions, handler)
|
40
|
+
params = if handler.is_a?(Proc)
|
41
|
+
handler.parameters
|
42
|
+
else
|
43
|
+
handler.method(:call).parameters
|
44
|
+
end
|
45
|
+
|
46
|
+
unless params.find_all { |type, _| type == :req || type == :opt }.length >= 2
|
47
|
+
ActiveSupport::Deprecation.warn <<~eowarn
|
48
|
+
Single arity template handlers are deprecated. Template handlers must
|
49
|
+
now accept two parameters, the view object and the source for the view object.
|
50
|
+
Change:
|
51
|
+
>> #{handler}.call(#{params.map(&:last).join(", ")})
|
52
|
+
To:
|
53
|
+
>> #{handler}.call(#{params.map(&:last).join(", ")}, source)
|
54
|
+
eowarn
|
55
|
+
handler = LegacyHandlerWrapper.new(handler)
|
56
|
+
end
|
57
|
+
|
32
58
|
raise(ArgumentError, "Extension is required") if extensions.empty?
|
33
59
|
extensions.each do |extension|
|
34
60
|
@@template_handlers[extension.to_sym] = handler
|
@@ -5,11 +5,11 @@ module ActionView
|
|
5
5
|
class Builder
|
6
6
|
class_attribute :default_format, default: :xml
|
7
7
|
|
8
|
-
def call(template)
|
8
|
+
def call(template, source)
|
9
9
|
require_engine
|
10
10
|
"xml = ::Builder::XmlMarkup.new(:indent => 2);" \
|
11
11
|
"self.output_buffer = xml.target!;" +
|
12
|
-
|
12
|
+
source +
|
13
13
|
";xml.target!;"
|
14
14
|
end
|
15
15
|
|
@@ -28,8 +28,8 @@ module ActionView
|
|
28
28
|
|
29
29
|
ENCODING_TAG = Regexp.new("\\A(<%#{ENCODING_FLAG}-?%>)[ \\t]*")
|
30
30
|
|
31
|
-
def self.call(template)
|
32
|
-
new.call(template)
|
31
|
+
def self.call(template, source)
|
32
|
+
new.call(template, source)
|
33
33
|
end
|
34
34
|
|
35
35
|
def supports_streaming?
|
@@ -40,17 +40,17 @@ module ActionView
|
|
40
40
|
true
|
41
41
|
end
|
42
42
|
|
43
|
-
def call(template)
|
43
|
+
def call(template, source)
|
44
44
|
# First, convert to BINARY, so in case the encoding is
|
45
45
|
# wrong, we can still find an encoding tag
|
46
46
|
# (<%# encoding %>) inside the String using a regular
|
47
47
|
# expression
|
48
|
-
template_source =
|
48
|
+
template_source = source.dup.force_encoding(Encoding::ASCII_8BIT)
|
49
49
|
|
50
50
|
erb = template_source.gsub(ENCODING_TAG, "")
|
51
51
|
encoding = $2
|
52
52
|
|
53
|
-
erb.force_encoding valid_encoding(
|
53
|
+
erb.force_encoding valid_encoding(source.dup, encoding)
|
54
54
|
|
55
55
|
# Always make sure we return a String in the default_internal
|
56
56
|
erb.encode!
|
@@ -13,7 +13,7 @@ module ActionView
|
|
13
13
|
|
14
14
|
# Dup properties so that we don't modify argument
|
15
15
|
properties = Hash[properties]
|
16
|
-
properties[:preamble] = "
|
16
|
+
properties[:preamble] = ""
|
17
17
|
properties[:postamble] = "@output_buffer.to_s"
|
18
18
|
properties[:bufvar] = "@output_buffer"
|
19
19
|
properties[:escapefunc] = ""
|
@@ -22,8 +22,12 @@ module ActionView
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def evaluate(action_view_erb_handler_context)
|
25
|
-
|
26
|
-
|
25
|
+
src = @src
|
26
|
+
view = Class.new(ActionView::Base) {
|
27
|
+
include action_view_erb_handler_context._routes.url_helpers
|
28
|
+
class_eval("define_method(:_template) { |local_assigns, output_buffer| #{src} }", defined?(@filename) ? @filename : "(erubi)", 0)
|
29
|
+
}.empty
|
30
|
+
view._run(:_template, nil, {}, ActionView::OutputBuffer.new)
|
27
31
|
end
|
28
32
|
|
29
33
|
private
|
@@ -1,15 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/deprecation"
|
4
|
+
|
3
5
|
module ActionView #:nodoc:
|
4
6
|
# = Action View HTML Template
|
5
7
|
class Template #:nodoc:
|
6
8
|
class HTML #:nodoc:
|
7
|
-
|
9
|
+
attr_reader :type
|
8
10
|
|
9
11
|
def initialize(string, type = nil)
|
12
|
+
unless type
|
13
|
+
ActiveSupport::Deprecation.warn "ActionView::Template::HTML#initialize requires a type parameter"
|
14
|
+
type = :html
|
15
|
+
end
|
16
|
+
|
10
17
|
@string = string.to_s
|
11
|
-
@type =
|
12
|
-
@type ||= Types[:html]
|
18
|
+
@type = type
|
13
19
|
end
|
14
20
|
|
15
21
|
def identifier
|
@@ -26,9 +32,12 @@ module ActionView #:nodoc:
|
|
26
32
|
to_str
|
27
33
|
end
|
28
34
|
|
29
|
-
def
|
30
|
-
|
35
|
+
def format
|
36
|
+
@type
|
31
37
|
end
|
38
|
+
|
39
|
+
def formats; Array(format); end
|
40
|
+
deprecate :formats
|
32
41
|
end
|
33
42
|
end
|
34
43
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionView #:nodoc:
|
4
|
+
class Template #:nodoc:
|
5
|
+
class Inline < Template #:nodoc:
|
6
|
+
# This finalizer is needed (and exactly with a proc inside another proc)
|
7
|
+
# otherwise templates leak in development.
|
8
|
+
Finalizer = proc do |method_name, mod| # :nodoc:
|
9
|
+
proc do
|
10
|
+
mod.module_eval do
|
11
|
+
remove_possible_method method_name
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def compile(mod)
|
17
|
+
super
|
18
|
+
ObjectSpace.define_finalizer(self, Finalizer[method_name, mod])
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionView #:nodoc:
|
4
|
+
# = Action View RawFile Template
|
5
|
+
class Template #:nodoc:
|
6
|
+
class RawFile #:nodoc:
|
7
|
+
attr_accessor :type, :format
|
8
|
+
|
9
|
+
def initialize(filename)
|
10
|
+
@filename = filename.to_s
|
11
|
+
extname = ::File.extname(filename).delete(".")
|
12
|
+
@type = Template::Types[extname] || Template::Types[:text]
|
13
|
+
@format = @type.symbol
|
14
|
+
end
|
15
|
+
|
16
|
+
def identifier
|
17
|
+
@filename
|
18
|
+
end
|
19
|
+
|
20
|
+
def render(*args)
|
21
|
+
::File.read(@filename)
|
22
|
+
end
|
23
|
+
|
24
|
+
def formats; Array(format); end
|
25
|
+
deprecate :formats
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -63,26 +63,11 @@ module ActionView
|
|
63
63
|
|
64
64
|
# Cache the templates returned by the block
|
65
65
|
def cache(key, name, prefix, partial, locals)
|
66
|
-
|
67
|
-
@data[key][name][prefix][partial][locals] ||= canonical_no_templates(yield)
|
68
|
-
else
|
69
|
-
fresh_templates = yield
|
70
|
-
cached_templates = @data[key][name][prefix][partial][locals]
|
71
|
-
|
72
|
-
if templates_have_changed?(cached_templates, fresh_templates)
|
73
|
-
@data[key][name][prefix][partial][locals] = canonical_no_templates(fresh_templates)
|
74
|
-
else
|
75
|
-
cached_templates || NO_TEMPLATES
|
76
|
-
end
|
77
|
-
end
|
66
|
+
@data[key][name][prefix][partial][locals] ||= canonical_no_templates(yield)
|
78
67
|
end
|
79
68
|
|
80
69
|
def cache_query(query) # :nodoc:
|
81
|
-
|
82
|
-
@query_cache[query] ||= canonical_no_templates(yield)
|
83
|
-
else
|
84
|
-
yield
|
85
|
-
end
|
70
|
+
@query_cache[query] ||= canonical_no_templates(yield)
|
86
71
|
end
|
87
72
|
|
88
73
|
def clear
|
@@ -112,19 +97,6 @@ module ActionView
|
|
112
97
|
def canonical_no_templates(templates)
|
113
98
|
templates.empty? ? NO_TEMPLATES : templates
|
114
99
|
end
|
115
|
-
|
116
|
-
def templates_have_changed?(cached_templates, fresh_templates)
|
117
|
-
# if either the old or new template list is empty, we don't need to (and can't)
|
118
|
-
# compare modification times, and instead just check whether the lists are different
|
119
|
-
if cached_templates.blank? || fresh_templates.blank?
|
120
|
-
return fresh_templates.blank? != cached_templates.blank?
|
121
|
-
end
|
122
|
-
|
123
|
-
cached_templates_max_updated_at = cached_templates.map(&:updated_at).max
|
124
|
-
|
125
|
-
# if a template has changed, it will be now be newer than all the cached templates
|
126
|
-
fresh_templates.any? { |t| t.updated_at > cached_templates_max_updated_at }
|
127
|
-
end
|
128
100
|
end
|
129
101
|
|
130
102
|
cattr_accessor :caching, default: true
|
@@ -143,35 +115,33 @@ module ActionView
|
|
143
115
|
|
144
116
|
# Normalizes the arguments and passes it on to find_templates.
|
145
117
|
def find_all(name, prefix = nil, partial = false, details = {}, key = nil, locals = [])
|
146
|
-
|
147
|
-
find_templates(name, prefix, partial, details)
|
148
|
-
end
|
149
|
-
end
|
118
|
+
locals = locals.map(&:to_s).sort!.freeze
|
150
119
|
|
151
|
-
def find_all_anywhere(name, prefix, partial = false, details = {}, key = nil, locals = [])
|
152
120
|
cached(key, [name, prefix, partial], details, locals) do
|
153
|
-
|
121
|
+
_find_all(name, prefix, partial, details, key, locals)
|
154
122
|
end
|
155
123
|
end
|
156
124
|
|
125
|
+
alias :find_all_anywhere :find_all
|
126
|
+
deprecate :find_all_anywhere
|
127
|
+
|
157
128
|
def find_all_with_query(query) # :nodoc:
|
158
129
|
@cache.cache_query(query) { find_template_paths(File.join(@path, query)) }
|
159
130
|
end
|
160
131
|
|
161
132
|
private
|
162
133
|
|
134
|
+
def _find_all(name, prefix, partial, details, key, locals)
|
135
|
+
find_templates(name, prefix, partial, details, locals)
|
136
|
+
end
|
137
|
+
|
163
138
|
delegate :caching?, to: :class
|
164
139
|
|
165
140
|
# This is what child classes implement. No defaults are needed
|
166
141
|
# because Resolver guarantees that the arguments are present and
|
167
142
|
# normalized.
|
168
|
-
def find_templates(name, prefix, partial, details,
|
169
|
-
raise NotImplementedError, "Subclasses must implement a find_templates(name, prefix, partial, details,
|
170
|
-
end
|
171
|
-
|
172
|
-
# Helpers that builds a path. Useful for building virtual paths.
|
173
|
-
def build_path(name, prefix, partial)
|
174
|
-
Path.build(name, prefix, partial)
|
143
|
+
def find_templates(name, prefix, partial, details, locals = [])
|
144
|
+
raise NotImplementedError, "Subclasses must implement a find_templates(name, prefix, partial, details, locals = []) method"
|
175
145
|
end
|
176
146
|
|
177
147
|
# Handles templates caching. If a key is given and caching is on
|
@@ -180,25 +150,13 @@ module ActionView
|
|
180
150
|
# resolver is fresher before returning it.
|
181
151
|
def cached(key, path_info, details, locals)
|
182
152
|
name, prefix, partial = path_info
|
183
|
-
locals = locals.map(&:to_s).sort!
|
184
153
|
|
185
154
|
if key
|
186
155
|
@cache.cache(key, name, prefix, partial, locals) do
|
187
|
-
|
156
|
+
yield
|
188
157
|
end
|
189
158
|
else
|
190
|
-
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
# Ensures all the resolver information is set in the template.
|
195
|
-
def decorate(templates, path_info, details, locals)
|
196
|
-
cached = nil
|
197
|
-
templates.each do |t|
|
198
|
-
t.locals = locals
|
199
|
-
t.formats = details[:formats] || [:html] if t.formats.empty?
|
200
|
-
t.variants = details[:variants] || [] if t.variants.empty?
|
201
|
-
t.virtual_path ||= (cached ||= build_path(*path_info))
|
159
|
+
yield
|
202
160
|
end
|
203
161
|
end
|
204
162
|
end
|
@@ -209,34 +167,60 @@ module ActionView
|
|
209
167
|
DEFAULT_PATTERN = ":prefix/:action{.:locale,}{.:formats,}{+:variants,}{.:handlers,}"
|
210
168
|
|
211
169
|
def initialize(pattern = nil)
|
212
|
-
|
170
|
+
if pattern
|
171
|
+
ActiveSupport::Deprecation.warn "Specifying a custom path for #{self.class} is deprecated. Implement a custom Resolver subclass instead."
|
172
|
+
@pattern = pattern
|
173
|
+
else
|
174
|
+
@pattern = DEFAULT_PATTERN
|
175
|
+
end
|
176
|
+
@unbound_templates = Concurrent::Map.new
|
177
|
+
super()
|
178
|
+
end
|
179
|
+
|
180
|
+
def clear_cache
|
181
|
+
@unbound_templates.clear
|
213
182
|
super()
|
214
183
|
end
|
215
184
|
|
216
185
|
private
|
217
186
|
|
218
|
-
def
|
187
|
+
def _find_all(name, prefix, partial, details, key, locals)
|
219
188
|
path = Path.build(name, prefix, partial)
|
220
|
-
query(path, details, details[:formats],
|
189
|
+
query(path, details, details[:formats], locals, cache: !!key)
|
221
190
|
end
|
222
191
|
|
223
|
-
def query(path, details, formats,
|
192
|
+
def query(path, details, formats, locals, cache:)
|
224
193
|
template_paths = find_template_paths_from_details(path, details)
|
225
|
-
template_paths = reject_files_external_to_app(template_paths)
|
194
|
+
template_paths = reject_files_external_to_app(template_paths)
|
226
195
|
|
227
196
|
template_paths.map do |template|
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
197
|
+
unbound_template =
|
198
|
+
if cache
|
199
|
+
@unbound_templates.compute_if_absent([template, path.virtual]) do
|
200
|
+
build_unbound_template(template, path.virtual)
|
201
|
+
end
|
202
|
+
else
|
203
|
+
build_unbound_template(template, path.virtual)
|
204
|
+
end
|
205
|
+
|
206
|
+
unbound_template.bind_locals(locals)
|
237
207
|
end
|
238
208
|
end
|
239
209
|
|
210
|
+
def build_unbound_template(template, virtual_path)
|
211
|
+
handler, format, variant = extract_handler_and_format_and_variant(template)
|
212
|
+
source = Template::Sources::File.new(template)
|
213
|
+
|
214
|
+
UnboundTemplate.new(
|
215
|
+
source,
|
216
|
+
template,
|
217
|
+
handler,
|
218
|
+
virtual_path: virtual_path,
|
219
|
+
format: format,
|
220
|
+
variant: variant,
|
221
|
+
)
|
222
|
+
end
|
223
|
+
|
240
224
|
def reject_files_external_to_app(files)
|
241
225
|
files.reject { |filename| !inside_path?(@path, filename) }
|
242
226
|
end
|
@@ -285,11 +269,6 @@ module ActionView
|
|
285
269
|
entry.gsub(/[*?{}\[\]]/, '\\\\\\&')
|
286
270
|
end
|
287
271
|
|
288
|
-
# Returns the file mtime from the filesystem.
|
289
|
-
def mtime(p)
|
290
|
-
File.mtime(p)
|
291
|
-
end
|
292
|
-
|
293
272
|
# Extract handler, formats and variant from path. If a format cannot be found neither
|
294
273
|
# from the path, or the handler, we should return the array of formats given
|
295
274
|
# to the resolver.
|
@@ -301,51 +280,25 @@ module ActionView
|
|
301
280
|
|
302
281
|
handler = Template.handler_for_extension(extension)
|
303
282
|
format, variant = pieces.last.split(EXTENSIONS[:variants], 2) if pieces.last
|
304
|
-
format
|
283
|
+
format = if format
|
284
|
+
Template::Types[format]&.ref
|
285
|
+
else
|
286
|
+
if handler.respond_to?(:default_format) # default_format can return nil
|
287
|
+
handler.default_format
|
288
|
+
else
|
289
|
+
nil
|
290
|
+
end
|
291
|
+
end
|
305
292
|
|
293
|
+
# Template::Types[format] and handler.default_format can return nil
|
306
294
|
[handler, format, variant]
|
307
295
|
end
|
308
296
|
end
|
309
297
|
|
310
|
-
# A resolver that loads files from the filesystem.
|
311
|
-
# resolving pattern. Such pattern can be a glob string supported by some variables.
|
312
|
-
#
|
313
|
-
# ==== Examples
|
314
|
-
#
|
315
|
-
# Default pattern, loads views the same way as previous versions of rails, eg. when you're
|
316
|
-
# looking for <tt>users/new</tt> it will produce query glob: <tt>users/new{.{en},}{.{html,js},}{.{erb,haml},}</tt>
|
317
|
-
#
|
318
|
-
# FileSystemResolver.new("/path/to/views", ":prefix/:action{.:locale,}{.:formats,}{+:variants,}{.:handlers,}")
|
319
|
-
#
|
320
|
-
# This one allows you to keep files with different formats in separate subdirectories,
|
321
|
-
# eg. <tt>users/new.html</tt> will be loaded from <tt>users/html/new.erb</tt> or <tt>users/new.html.erb</tt>,
|
322
|
-
# <tt>users/new.js</tt> from <tt>users/js/new.erb</tt> or <tt>users/new.js.erb</tt>, etc.
|
323
|
-
#
|
324
|
-
# FileSystemResolver.new("/path/to/views", ":prefix/{:formats/,}:action{.:locale,}{.:formats,}{+:variants,}{.:handlers,}")
|
325
|
-
#
|
326
|
-
# If you don't specify a pattern then the default will be used.
|
327
|
-
#
|
328
|
-
# In order to use any of the customized resolvers above in a Rails application, you just need
|
329
|
-
# to configure ActionController::Base.view_paths in an initializer, for example:
|
330
|
-
#
|
331
|
-
# ActionController::Base.view_paths = FileSystemResolver.new(
|
332
|
-
# Rails.root.join("app/views"),
|
333
|
-
# ":prefix/:action{.:locale,}{.:formats,}{+:variants,}{.:handlers,}",
|
334
|
-
# )
|
335
|
-
#
|
336
|
-
# ==== Pattern format and variables
|
337
|
-
#
|
338
|
-
# Pattern has to be a valid glob string, and it allows you to use the
|
339
|
-
# following variables:
|
340
|
-
#
|
341
|
-
# * <tt>:prefix</tt> - usually the controller path
|
342
|
-
# * <tt>:action</tt> - name of the action
|
343
|
-
# * <tt>:locale</tt> - possible locale versions
|
344
|
-
# * <tt>:formats</tt> - possible request formats (for example html, json, xml...)
|
345
|
-
# * <tt>:variants</tt> - possible request variants (for example phone, tablet...)
|
346
|
-
# * <tt>:handlers</tt> - possible handlers (for example erb, haml, builder...)
|
347
|
-
#
|
298
|
+
# A resolver that loads files from the filesystem.
|
348
299
|
class FileSystemResolver < PathResolver
|
300
|
+
attr_reader :path
|
301
|
+
|
349
302
|
def initialize(path, pattern = nil)
|
350
303
|
raise ArgumentError, "path already is a Resolver class" if path.is_a?(Resolver)
|
351
304
|
super(pattern)
|
@@ -365,6 +318,10 @@ module ActionView
|
|
365
318
|
|
366
319
|
# An Optimized resolver for Rails' most common case.
|
367
320
|
class OptimizedFileSystemResolver < FileSystemResolver #:nodoc:
|
321
|
+
def initialize(path)
|
322
|
+
super(path)
|
323
|
+
end
|
324
|
+
|
368
325
|
private
|
369
326
|
|
370
327
|
def find_template_paths_from_details(path, details)
|
@@ -420,12 +377,18 @@ module ActionView
|
|
420
377
|
# The same as FileSystemResolver but does not allow templates to store
|
421
378
|
# a virtual path since it is invalid for such resolvers.
|
422
379
|
class FallbackFileSystemResolver < FileSystemResolver #:nodoc:
|
380
|
+
private_class_method :new
|
381
|
+
|
423
382
|
def self.instances
|
424
383
|
[new(""), new("/")]
|
425
384
|
end
|
426
385
|
|
427
|
-
def
|
428
|
-
super
|
386
|
+
def build_unbound_template(template, _)
|
387
|
+
super(template, nil)
|
388
|
+
end
|
389
|
+
|
390
|
+
def reject_files_external_to_app(files)
|
391
|
+
files
|
429
392
|
end
|
430
393
|
end
|
431
394
|
end
|