actionview 4.2.11.3 → 5.2.7.1
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 +115 -245
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -6
- data/lib/action_view/base.rb +38 -28
- data/lib/action_view/buffers.rb +3 -1
- data/lib/action_view/context.rb +3 -3
- data/lib/action_view/dependency_tracker.rb +54 -20
- data/lib/action_view/digestor.rb +94 -83
- data/lib/action_view/flows.rb +11 -11
- data/lib/action_view/gem_version.rb +5 -3
- data/lib/action_view/helpers/active_model_helper.rb +17 -11
- data/lib/action_view/helpers/asset_tag_helper.rb +244 -62
- data/lib/action_view/helpers/asset_url_helper.rb +170 -67
- data/lib/action_view/helpers/atom_feed_helper.rb +19 -17
- data/lib/action_view/helpers/cache_helper.rb +105 -42
- data/lib/action_view/helpers/capture_helper.rb +16 -13
- data/lib/action_view/helpers/controller_helper.rb +15 -4
- data/lib/action_view/helpers/csp_helper.rb +24 -0
- data/lib/action_view/helpers/csrf_helper.rb +7 -5
- data/lib/action_view/helpers/date_helper.rb +170 -112
- data/lib/action_view/helpers/debug_helper.rb +7 -6
- data/lib/action_view/helpers/form_helper.rb +521 -127
- data/lib/action_view/helpers/form_options_helper.rb +109 -63
- data/lib/action_view/helpers/form_tag_helper.rb +110 -67
- data/lib/action_view/helpers/javascript_helper.rb +27 -12
- data/lib/action_view/helpers/number_helper.rb +77 -58
- data/lib/action_view/helpers/output_safety_helper.rb +36 -4
- data/lib/action_view/helpers/record_tag_helper.rb +14 -99
- data/lib/action_view/helpers/rendering_helper.rb +6 -5
- data/lib/action_view/helpers/sanitize_helper.rb +20 -15
- data/lib/action_view/helpers/tag_helper.rb +229 -73
- data/lib/action_view/helpers/tags/base.rb +134 -97
- data/lib/action_view/helpers/tags/check_box.rb +20 -18
- data/lib/action_view/helpers/tags/checkable.rb +4 -2
- data/lib/action_view/helpers/tags/collection_check_boxes.rb +12 -33
- data/lib/action_view/helpers/tags/collection_helpers.rb +70 -36
- data/lib/action_view/helpers/tags/collection_radio_buttons.rb +6 -11
- data/lib/action_view/helpers/tags/collection_select.rb +4 -2
- data/lib/action_view/helpers/tags/color_field.rb +3 -1
- data/lib/action_view/helpers/tags/date_field.rb +2 -0
- data/lib/action_view/helpers/tags/date_select.rb +38 -36
- data/lib/action_view/helpers/tags/datetime_field.rb +4 -2
- data/lib/action_view/helpers/tags/datetime_local_field.rb +2 -0
- data/lib/action_view/helpers/tags/datetime_select.rb +2 -0
- data/lib/action_view/helpers/tags/email_field.rb +2 -0
- data/lib/action_view/helpers/tags/file_field.rb +2 -0
- data/lib/action_view/helpers/tags/grouped_collection_select.rb +4 -2
- data/lib/action_view/helpers/tags/hidden_field.rb +2 -0
- data/lib/action_view/helpers/tags/label.rb +3 -1
- data/lib/action_view/helpers/tags/month_field.rb +2 -0
- data/lib/action_view/helpers/tags/number_field.rb +2 -0
- data/lib/action_view/helpers/tags/password_field.rb +3 -1
- data/lib/action_view/helpers/tags/placeholderable.rb +3 -1
- data/lib/action_view/helpers/tags/radio_button.rb +7 -5
- data/lib/action_view/helpers/tags/range_field.rb +2 -0
- data/lib/action_view/helpers/tags/search_field.rb +14 -9
- data/lib/action_view/helpers/tags/select.rb +11 -9
- data/lib/action_view/helpers/tags/tel_field.rb +2 -0
- data/lib/action_view/helpers/tags/text_area.rb +4 -2
- data/lib/action_view/helpers/tags/text_field.rb +8 -7
- data/lib/action_view/helpers/tags/time_field.rb +2 -0
- data/lib/action_view/helpers/tags/time_select.rb +2 -0
- data/lib/action_view/helpers/tags/time_zone_select.rb +3 -1
- data/lib/action_view/helpers/tags/translator.rb +17 -13
- data/lib/action_view/helpers/tags/url_field.rb +2 -0
- data/lib/action_view/helpers/tags/week_field.rb +2 -0
- data/lib/action_view/helpers/tags.rb +3 -1
- data/lib/action_view/helpers/text_helper.rb +55 -36
- data/lib/action_view/helpers/translation_helper.rb +74 -32
- data/lib/action_view/helpers/url_helper.rb +159 -104
- data/lib/action_view/helpers.rb +5 -1
- data/lib/action_view/layouts.rb +65 -58
- data/lib/action_view/log_subscriber.rb +60 -8
- data/lib/action_view/lookup_context.rb +80 -65
- data/lib/action_view/model_naming.rb +3 -1
- data/lib/action_view/path_set.rb +30 -19
- data/lib/action_view/railtie.rb +39 -6
- data/lib/action_view/record_identifier.rb +53 -25
- data/lib/action_view/renderer/abstract_renderer.rb +21 -15
- data/lib/action_view/renderer/partial_renderer/collection_caching.rb +57 -0
- data/lib/action_view/renderer/partial_renderer.rb +218 -214
- data/lib/action_view/renderer/renderer.rb +8 -6
- data/lib/action_view/renderer/streaming_template_renderer.rb +50 -48
- data/lib/action_view/renderer/template_renderer.rb +67 -66
- data/lib/action_view/rendering.rb +19 -14
- data/lib/action_view/routing_url_for.rb +27 -17
- data/lib/action_view/tasks/cache_digests.rake +25 -0
- data/lib/action_view/template/error.rb +16 -16
- data/lib/action_view/template/handlers/builder.rb +10 -11
- data/lib/action_view/template/handlers/erb/erubi.rb +83 -0
- data/lib/action_view/template/handlers/erb.rb +9 -80
- data/lib/action_view/template/handlers/html.rb +11 -0
- data/lib/action_view/template/handlers/raw.rb +3 -3
- data/lib/action_view/template/handlers.rb +11 -7
- data/lib/action_view/template/html.rb +5 -5
- data/lib/action_view/template/resolver.rb +140 -115
- data/lib/action_view/template/text.rb +8 -9
- data/lib/action_view/template/types.rb +18 -18
- data/lib/action_view/template.rb +54 -33
- data/lib/action_view/test_case.rb +50 -29
- data/lib/action_view/testing/resolvers.rb +31 -31
- data/lib/action_view/version.rb +3 -1
- data/lib/action_view/view_paths.rb +28 -34
- data/lib/action_view.rb +8 -7
- data/lib/assets/compiled/rails-ujs.js +720 -0
- metadata +28 -27
- data/lib/action_view/tasks/dependencies.rake +0 -23
@@ -1,10 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "pathname"
|
2
4
|
require "active_support/core_ext/class"
|
3
5
|
require "active_support/core_ext/module/attribute_accessors"
|
4
|
-
require 'active_support/core_ext/string/filters'
|
5
6
|
require "action_view/template"
|
6
7
|
require "thread"
|
7
|
-
require "
|
8
|
+
require "concurrent/map"
|
8
9
|
|
9
10
|
module ActionView
|
10
11
|
# = Action View Resolver
|
@@ -15,7 +16,7 @@ module ActionView
|
|
15
16
|
alias_method :partial?, :partial
|
16
17
|
|
17
18
|
def self.build(name, prefix, partial)
|
18
|
-
virtual = ""
|
19
|
+
virtual = "".dup
|
19
20
|
virtual << "#{prefix}/" unless prefix.empty?
|
20
21
|
virtual << (partial ? "_#{name}" : name)
|
21
22
|
new name, prefix, partial, virtual
|
@@ -36,23 +37,28 @@ module ActionView
|
|
36
37
|
|
37
38
|
# Threadsafe template cache
|
38
39
|
class Cache #:nodoc:
|
39
|
-
class SmallCache <
|
40
|
+
class SmallCache < Concurrent::Map
|
40
41
|
def initialize(options = {})
|
41
|
-
super(options.merge(:
|
42
|
+
super(options.merge(initial_capacity: 2))
|
42
43
|
end
|
43
44
|
end
|
44
45
|
|
45
46
|
# preallocate all the default blocks for performance/memory consumption reasons
|
46
|
-
PARTIAL_BLOCK = lambda {|cache, partial| cache[partial] = SmallCache.new}
|
47
|
-
PREFIX_BLOCK = lambda {|cache, prefix| cache[prefix] = SmallCache.new(&PARTIAL_BLOCK)}
|
48
|
-
NAME_BLOCK = lambda {|cache, name| cache[name] = SmallCache.new(&PREFIX_BLOCK)}
|
49
|
-
KEY_BLOCK = lambda {|cache, key| cache[key] = SmallCache.new(&NAME_BLOCK)}
|
47
|
+
PARTIAL_BLOCK = lambda { |cache, partial| cache[partial] = SmallCache.new }
|
48
|
+
PREFIX_BLOCK = lambda { |cache, prefix| cache[prefix] = SmallCache.new(&PARTIAL_BLOCK) }
|
49
|
+
NAME_BLOCK = lambda { |cache, name| cache[name] = SmallCache.new(&PREFIX_BLOCK) }
|
50
|
+
KEY_BLOCK = lambda { |cache, key| cache[key] = SmallCache.new(&NAME_BLOCK) }
|
50
51
|
|
51
52
|
# usually a majority of template look ups return nothing, use this canonical preallocated array to save memory
|
52
53
|
NO_TEMPLATES = [].freeze
|
53
54
|
|
54
55
|
def initialize
|
55
56
|
@data = SmallCache.new(&KEY_BLOCK)
|
57
|
+
@query_cache = SmallCache.new
|
58
|
+
end
|
59
|
+
|
60
|
+
def inspect
|
61
|
+
"#<#{self.class.name}:0x#{(object_id << 1).to_s(16)} keys=#{@data.size} queries=#{@query_cache.size}>"
|
56
62
|
end
|
57
63
|
|
58
64
|
# Cache the templates returned by the block
|
@@ -71,32 +77,57 @@ module ActionView
|
|
71
77
|
end
|
72
78
|
end
|
73
79
|
|
80
|
+
def cache_query(query) # :nodoc:
|
81
|
+
if Resolver.caching?
|
82
|
+
@query_cache[query] ||= canonical_no_templates(yield)
|
83
|
+
else
|
84
|
+
yield
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
74
88
|
def clear
|
75
89
|
@data.clear
|
90
|
+
@query_cache.clear
|
76
91
|
end
|
77
92
|
|
78
|
-
|
93
|
+
# Get the cache size. Do not call this
|
94
|
+
# method. This method is not guaranteed to be here ever.
|
95
|
+
def size # :nodoc:
|
96
|
+
size = 0
|
97
|
+
@data.each_value do |v1|
|
98
|
+
v1.each_value do |v2|
|
99
|
+
v2.each_value do |v3|
|
100
|
+
v3.each_value do |v4|
|
101
|
+
size += v4.size
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
79
106
|
|
80
|
-
|
81
|
-
templates.empty? ? NO_TEMPLATES : templates
|
107
|
+
size + @query_cache.size
|
82
108
|
end
|
83
109
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
return fresh_templates.blank? != cached_templates.blank?
|
110
|
+
private
|
111
|
+
|
112
|
+
def canonical_no_templates(templates)
|
113
|
+
templates.empty? ? NO_TEMPLATES : templates
|
89
114
|
end
|
90
115
|
|
91
|
-
|
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
|
92
122
|
|
93
|
-
|
94
|
-
|
95
|
-
|
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
|
96
128
|
end
|
97
129
|
|
98
|
-
cattr_accessor :caching
|
99
|
-
self.caching = true
|
130
|
+
cattr_accessor :caching, default: true
|
100
131
|
|
101
132
|
class << self
|
102
133
|
alias :caching? :caching
|
@@ -111,18 +142,22 @@ module ActionView
|
|
111
142
|
end
|
112
143
|
|
113
144
|
# Normalizes the arguments and passes it on to find_templates.
|
114
|
-
def find_all(name, prefix=nil, partial=false, details={}, key=nil, locals=[])
|
145
|
+
def find_all(name, prefix = nil, partial = false, details = {}, key = nil, locals = [])
|
115
146
|
cached(key, [name, prefix, partial], details, locals) do
|
116
|
-
find_templates(name, prefix, partial, details
|
147
|
+
find_templates(name, prefix, partial, details)
|
117
148
|
end
|
118
149
|
end
|
119
150
|
|
120
|
-
def find_all_anywhere(name, prefix, partial=false, details={}, key=nil, locals=[])
|
151
|
+
def find_all_anywhere(name, prefix, partial = false, details = {}, key = nil, locals = [])
|
121
152
|
cached(key, [name, prefix, partial], details, locals) do
|
122
153
|
find_templates(name, prefix, partial, details, true)
|
123
154
|
end
|
124
155
|
end
|
125
156
|
|
157
|
+
def find_all_with_query(query) # :nodoc:
|
158
|
+
@cache.cache_query(query) { find_template_paths(File.join(@path, query)) }
|
159
|
+
end
|
160
|
+
|
126
161
|
private
|
127
162
|
|
128
163
|
delegate :caching?, to: :class
|
@@ -130,8 +165,8 @@ module ActionView
|
|
130
165
|
# This is what child classes implement. No defaults are needed
|
131
166
|
# because Resolver guarantees that the arguments are present and
|
132
167
|
# normalized.
|
133
|
-
def find_templates(name, prefix, partial, details, outside_app_allowed)
|
134
|
-
raise NotImplementedError, "Subclasses must implement a find_templates(name, prefix, partial, details, outside_app_allowed) method"
|
168
|
+
def find_templates(name, prefix, partial, details, outside_app_allowed = false)
|
169
|
+
raise NotImplementedError, "Subclasses must implement a find_templates(name, prefix, partial, details, outside_app_allowed = false) method"
|
135
170
|
end
|
136
171
|
|
137
172
|
# Helpers that builds a path. Useful for building virtual paths.
|
@@ -143,9 +178,9 @@ module ActionView
|
|
143
178
|
# always check the cache before hitting the resolver. Otherwise,
|
144
179
|
# it always hits the resolver but if the key is present, check if the
|
145
180
|
# resolver is fresher before returning it.
|
146
|
-
def cached(key, path_info, details, locals)
|
181
|
+
def cached(key, path_info, details, locals)
|
147
182
|
name, prefix, partial = path_info
|
148
|
-
locals = locals.map
|
183
|
+
locals = locals.map(&:to_s).sort!
|
149
184
|
|
150
185
|
if key
|
151
186
|
@cache.cache(key, name, prefix, partial, locals) do
|
@@ -157,7 +192,7 @@ module ActionView
|
|
157
192
|
end
|
158
193
|
|
159
194
|
# Ensures all the resolver information is set in the template.
|
160
|
-
def decorate(templates, path_info, details, locals)
|
195
|
+
def decorate(templates, path_info, details, locals)
|
161
196
|
cached = nil
|
162
197
|
templates.each do |t|
|
163
198
|
t.locals = locals
|
@@ -170,117 +205,103 @@ module ActionView
|
|
170
205
|
|
171
206
|
# An abstract class that implements a Resolver with path semantics.
|
172
207
|
class PathResolver < Resolver #:nodoc:
|
173
|
-
EXTENSIONS = { :
|
208
|
+
EXTENSIONS = { locale: ".", formats: ".", variants: "+", handlers: "." }
|
174
209
|
DEFAULT_PATTERN = ":prefix/:action{.:locale,}{.:formats,}{+:variants,}{.:handlers,}"
|
175
210
|
|
176
|
-
def initialize(pattern=nil)
|
211
|
+
def initialize(pattern = nil)
|
177
212
|
@pattern = pattern || DEFAULT_PATTERN
|
178
213
|
super()
|
179
214
|
end
|
180
215
|
|
181
216
|
private
|
182
217
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
218
|
+
def find_templates(name, prefix, partial, details, outside_app_allowed = false)
|
219
|
+
path = Path.build(name, prefix, partial)
|
220
|
+
query(path, details, details[:formats], outside_app_allowed)
|
221
|
+
end
|
187
222
|
|
188
|
-
|
189
|
-
|
223
|
+
def query(path, details, formats, outside_app_allowed)
|
224
|
+
query = build_query(path, details)
|
190
225
|
|
191
|
-
|
192
|
-
|
226
|
+
template_paths = find_template_paths(query)
|
227
|
+
template_paths = reject_files_external_to_app(template_paths) unless outside_app_allowed
|
193
228
|
|
194
|
-
|
195
|
-
|
196
|
-
|
229
|
+
template_paths.map do |template|
|
230
|
+
handler, format, variant = extract_handler_and_format_and_variant(template)
|
231
|
+
contents = File.binread(template)
|
197
232
|
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
233
|
+
Template.new(contents, File.expand_path(template), handler,
|
234
|
+
virtual_path: path.virtual,
|
235
|
+
format: format,
|
236
|
+
variant: variant,
|
237
|
+
updated_at: mtime(template)
|
238
|
+
)
|
239
|
+
end
|
240
|
+
end
|
206
241
|
|
207
|
-
|
208
|
-
|
209
|
-
|
242
|
+
def reject_files_external_to_app(files)
|
243
|
+
files.reject { |filename| !inside_path?(@path, filename) }
|
244
|
+
end
|
210
245
|
|
211
|
-
if RUBY_VERSION >= '2.2.0'
|
212
246
|
def find_template_paths(query)
|
213
|
-
Dir[query].reject
|
247
|
+
Dir[query].uniq.reject do |filename|
|
214
248
|
File.directory?(filename) ||
|
215
249
|
# deals with case-insensitive file systems.
|
216
250
|
!File.fnmatch(query, filename, File::FNM_EXTGLOB)
|
217
|
-
|
251
|
+
end
|
218
252
|
end
|
219
|
-
else
|
220
|
-
def find_template_paths(query)
|
221
|
-
# deals with case-insensitive file systems.
|
222
|
-
sanitizer = Hash.new { |h,dir| h[dir] = Dir["#{dir}/*"] }
|
223
253
|
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
254
|
+
def inside_path?(path, filename)
|
255
|
+
filename = File.expand_path(filename)
|
256
|
+
path = File.join(path, "")
|
257
|
+
filename.start_with?(path)
|
228
258
|
end
|
229
|
-
end
|
230
259
|
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
filename.start_with?(path)
|
235
|
-
end
|
260
|
+
# Helper for building query glob string based on resolver's pattern.
|
261
|
+
def build_query(path, details)
|
262
|
+
query = @pattern.dup
|
236
263
|
|
237
|
-
|
238
|
-
|
239
|
-
query = @pattern.dup
|
264
|
+
prefix = path.prefix.empty? ? "" : "#{escape_entry(path.prefix)}\\1"
|
265
|
+
query.gsub!(/:prefix(\/)?/, prefix)
|
240
266
|
|
241
|
-
|
242
|
-
|
267
|
+
partial = escape_entry(path.partial? ? "_#{path.name}" : path.name)
|
268
|
+
query.gsub!(/:action/, partial)
|
243
269
|
|
244
|
-
|
245
|
-
|
270
|
+
details.each do |ext, candidates|
|
271
|
+
if ext == :variants && candidates == :any
|
272
|
+
query.gsub!(/:#{ext}/, "*")
|
273
|
+
else
|
274
|
+
query.gsub!(/:#{ext}/, "{#{candidates.compact.uniq.join(',')}}")
|
275
|
+
end
|
276
|
+
end
|
246
277
|
|
247
|
-
|
248
|
-
query.gsub!(/\:#{ext}/, "{#{variants.compact.uniq.join(',')}}")
|
278
|
+
File.expand_path(query, @path)
|
249
279
|
end
|
250
280
|
|
251
|
-
|
252
|
-
|
281
|
+
def escape_entry(entry)
|
282
|
+
entry.gsub(/[*?{}\[\]]/, '\\\\\\&'.freeze)
|
283
|
+
end
|
253
284
|
|
254
|
-
|
255
|
-
|
256
|
-
|
285
|
+
# Returns the file mtime from the filesystem.
|
286
|
+
def mtime(p)
|
287
|
+
File.mtime(p)
|
288
|
+
end
|
257
289
|
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
290
|
+
# Extract handler, formats and variant from path. If a format cannot be found neither
|
291
|
+
# from the path, or the handler, we should return the array of formats given
|
292
|
+
# to the resolver.
|
293
|
+
def extract_handler_and_format_and_variant(path)
|
294
|
+
pieces = File.basename(path).split(".".freeze)
|
295
|
+
pieces.shift
|
262
296
|
|
263
|
-
|
264
|
-
# from the path, or the handler, we should return the array of formats given
|
265
|
-
# to the resolver.
|
266
|
-
def extract_handler_and_format_and_variant(path, default_formats)
|
267
|
-
pieces = File.basename(path).split(".")
|
268
|
-
pieces.shift
|
269
|
-
|
270
|
-
extension = pieces.pop
|
271
|
-
unless extension
|
272
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
273
|
-
The file #{path} did not specify a template handler. The default is
|
274
|
-
currently ERB, but will change to RAW in the future.
|
275
|
-
MSG
|
276
|
-
end
|
297
|
+
extension = pieces.pop
|
277
298
|
|
278
|
-
|
279
|
-
|
280
|
-
|
299
|
+
handler = Template.handler_for_extension(extension)
|
300
|
+
format, variant = pieces.last.split(EXTENSIONS[:variants], 2) if pieces.last
|
301
|
+
format &&= Template::Types[format]
|
281
302
|
|
282
|
-
|
283
|
-
|
303
|
+
[handler, format, variant]
|
304
|
+
end
|
284
305
|
end
|
285
306
|
|
286
307
|
# A resolver that loads files from the filesystem. It allows setting your own
|
@@ -289,13 +310,13 @@ module ActionView
|
|
289
310
|
# ==== Examples
|
290
311
|
#
|
291
312
|
# Default pattern, loads views the same way as previous versions of rails, eg. when you're
|
292
|
-
# looking for
|
313
|
+
# looking for <tt>users/new</tt> it will produce query glob: <tt>users/new{.{en},}{.{html,js},}{.{erb,haml},}</tt>
|
293
314
|
#
|
294
315
|
# FileSystemResolver.new("/path/to/views", ":prefix/:action{.:locale,}{.:formats,}{+:variants,}{.:handlers,}")
|
295
316
|
#
|
296
317
|
# This one allows you to keep files with different formats in separate subdirectories,
|
297
|
-
# eg.
|
298
|
-
#
|
318
|
+
# eg. <tt>users/new.html</tt> will be loaded from <tt>users/html/new.erb</tt> or <tt>users/new.html.erb</tt>,
|
319
|
+
# <tt>users/new.js</tt> from <tt>users/js/new.erb</tt> or <tt>users/new.js.erb</tt>, etc.
|
299
320
|
#
|
300
321
|
# FileSystemResolver.new("/path/to/views", ":prefix/{:formats/,}:action{.:locale,}{.:formats,}{+:variants,}{.:handlers,}")
|
301
322
|
#
|
@@ -306,7 +327,7 @@ module ActionView
|
|
306
327
|
#
|
307
328
|
# ActionController::Base.view_paths = FileSystemResolver.new(
|
308
329
|
# Rails.root.join("app/views"),
|
309
|
-
# ":prefix{
|
330
|
+
# ":prefix/:action{.:locale,}{.:formats,}{+:variants,}{.:handlers,}",
|
310
331
|
# )
|
311
332
|
#
|
312
333
|
# ==== Pattern format and variables
|
@@ -322,7 +343,7 @@ module ActionView
|
|
322
343
|
# * <tt>:handlers</tt> - possible handlers (for example erb, haml, builder...)
|
323
344
|
#
|
324
345
|
class FileSystemResolver < PathResolver
|
325
|
-
def initialize(path, pattern=nil)
|
346
|
+
def initialize(path, pattern = nil)
|
326
347
|
raise ArgumentError, "path already is a Resolver class" if path.is_a?(Resolver)
|
327
348
|
super(pattern)
|
328
349
|
@path = File.expand_path(path)
|
@@ -345,7 +366,11 @@ module ActionView
|
|
345
366
|
query = escape_entry(File.join(@path, path))
|
346
367
|
|
347
368
|
exts = EXTENSIONS.map do |ext, prefix|
|
348
|
-
|
369
|
+
if ext == :variants && details[ext] == :any
|
370
|
+
"{#{prefix}*,}"
|
371
|
+
else
|
372
|
+
"{#{details[ext].compact.uniq.map { |e| "#{prefix}#{e}," }.join}}"
|
373
|
+
end
|
349
374
|
end.join
|
350
375
|
|
351
376
|
query + exts
|
@@ -1,22 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActionView #:nodoc:
|
2
4
|
# = Action View Text Template
|
3
|
-
class Template
|
5
|
+
class Template #:nodoc:
|
4
6
|
class Text #:nodoc:
|
5
7
|
attr_accessor :type
|
6
8
|
|
7
|
-
def initialize(string
|
9
|
+
def initialize(string)
|
8
10
|
@string = string.to_s
|
9
|
-
@type
|
10
|
-
@type ||= Types[:text]
|
11
|
+
@type = Types[:text]
|
11
12
|
end
|
12
13
|
|
13
14
|
def identifier
|
14
|
-
|
15
|
+
"text template"
|
15
16
|
end
|
16
17
|
|
17
|
-
|
18
|
-
'text template'
|
19
|
-
end
|
18
|
+
alias_method :inspect, :identifier
|
20
19
|
|
21
20
|
def to_str
|
22
21
|
@string
|
@@ -27,7 +26,7 @@ module ActionView #:nodoc:
|
|
27
26
|
end
|
28
27
|
|
29
28
|
def formats
|
30
|
-
[@type.
|
29
|
+
[@type.ref]
|
31
30
|
end
|
32
31
|
end
|
33
32
|
end
|
@@ -1,23 +1,17 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/module/attribute_accessors"
|
3
4
|
|
4
5
|
module ActionView
|
5
|
-
class Template
|
6
|
+
class Template #:nodoc:
|
6
7
|
class Types
|
7
8
|
class Type
|
8
|
-
|
9
|
-
self.types = Set.new
|
10
|
-
|
11
|
-
def self.register(*t)
|
12
|
-
types.merge(t.map { |type| type.to_s })
|
13
|
-
end
|
14
|
-
|
15
|
-
register :html, :text, :js, :css, :xml, :json
|
9
|
+
SET = Struct.new(:symbols).new([ :html, :text, :js, :css, :xml, :json ])
|
16
10
|
|
17
11
|
def self.[](type)
|
18
|
-
|
19
|
-
|
20
|
-
|
12
|
+
if type.is_a?(self)
|
13
|
+
type
|
14
|
+
else
|
21
15
|
new(type)
|
22
16
|
end
|
23
17
|
end
|
@@ -28,16 +22,18 @@ module ActionView
|
|
28
22
|
@symbol = symbol.to_sym
|
29
23
|
end
|
30
24
|
|
31
|
-
|
25
|
+
def to_s
|
26
|
+
@symbol.to_s
|
27
|
+
end
|
32
28
|
alias to_str to_s
|
33
29
|
|
34
30
|
def ref
|
35
|
-
|
31
|
+
@symbol
|
36
32
|
end
|
33
|
+
alias to_sym ref
|
37
34
|
|
38
35
|
def ==(type)
|
39
|
-
|
40
|
-
symbol.to_sym == type.to_sym
|
36
|
+
@symbol == type.to_sym unless type.blank?
|
41
37
|
end
|
42
38
|
end
|
43
39
|
|
@@ -52,6 +48,10 @@ module ActionView
|
|
52
48
|
def self.[](type)
|
53
49
|
type_klass[type]
|
54
50
|
end
|
51
|
+
|
52
|
+
def self.symbols
|
53
|
+
type_klass::SET.symbols
|
54
|
+
end
|
55
55
|
end
|
56
56
|
end
|
57
57
|
end
|