actionview 5.2.7.1 → 6.1.4.6
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 +250 -112
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -3
- data/lib/action_view/base.rb +81 -15
- data/lib/action_view/buffers.rb +15 -0
- data/lib/action_view/cache_expiry.rb +52 -0
- data/lib/action_view/context.rb +5 -9
- data/lib/action_view/dependency_tracker.rb +10 -4
- data/lib/action_view/digestor.rb +15 -22
- data/lib/action_view/flows.rb +0 -1
- data/lib/action_view/gem_version.rb +4 -4
- data/lib/action_view/helpers/active_model_helper.rb +0 -1
- data/lib/action_view/helpers/asset_tag_helper.rb +64 -47
- data/lib/action_view/helpers/asset_url_helper.rb +9 -6
- data/lib/action_view/helpers/atom_feed_helper.rb +2 -1
- data/lib/action_view/helpers/cache_helper.rb +23 -22
- data/lib/action_view/helpers/capture_helper.rb +4 -0
- data/lib/action_view/helpers/csp_helper.rb +4 -2
- data/lib/action_view/helpers/csrf_helper.rb +1 -1
- data/lib/action_view/helpers/date_helper.rb +73 -30
- data/lib/action_view/helpers/form_helper.rb +305 -37
- data/lib/action_view/helpers/form_options_helper.rb +23 -23
- data/lib/action_view/helpers/form_tag_helper.rb +19 -16
- data/lib/action_view/helpers/javascript_helper.rb +12 -11
- data/lib/action_view/helpers/number_helper.rb +14 -8
- data/lib/action_view/helpers/output_safety_helper.rb +1 -1
- data/lib/action_view/helpers/rendering_helper.rb +17 -7
- data/lib/action_view/helpers/sanitize_helper.rb +12 -18
- data/lib/action_view/helpers/tag_helper.rb +100 -55
- data/lib/action_view/helpers/tags/base.rb +18 -11
- data/lib/action_view/helpers/tags/check_box.rb +0 -1
- data/lib/action_view/helpers/tags/collection_check_boxes.rb +0 -1
- data/lib/action_view/helpers/tags/collection_helpers.rb +0 -1
- data/lib/action_view/helpers/tags/collection_radio_buttons.rb +0 -1
- data/lib/action_view/helpers/tags/color_field.rb +1 -2
- data/lib/action_view/helpers/tags/date_field.rb +1 -2
- data/lib/action_view/helpers/tags/date_select.rb +2 -3
- data/lib/action_view/helpers/tags/datetime_field.rb +0 -1
- data/lib/action_view/helpers/tags/datetime_local_field.rb +1 -2
- data/lib/action_view/helpers/tags/label.rb +4 -1
- data/lib/action_view/helpers/tags/month_field.rb +1 -2
- data/lib/action_view/helpers/tags/radio_button.rb +0 -1
- data/lib/action_view/helpers/tags/select.rb +1 -2
- data/lib/action_view/helpers/tags/text_field.rb +0 -1
- data/lib/action_view/helpers/tags/time_field.rb +1 -2
- data/lib/action_view/helpers/tags/translator.rb +1 -6
- data/lib/action_view/helpers/tags/week_field.rb +1 -2
- data/lib/action_view/helpers/text_helper.rb +4 -5
- data/lib/action_view/helpers/translation_helper.rb +94 -54
- data/lib/action_view/helpers/url_helper.rb +136 -28
- data/lib/action_view/helpers.rb +0 -2
- data/lib/action_view/layouts.rb +8 -10
- data/lib/action_view/log_subscriber.rb +30 -15
- data/lib/action_view/lookup_context.rb +63 -35
- data/lib/action_view/path_set.rb +3 -12
- data/lib/action_view/railtie.rb +42 -26
- data/lib/action_view/record_identifier.rb +2 -3
- data/lib/action_view/renderer/abstract_renderer.rb +142 -11
- data/lib/action_view/renderer/collection_renderer.rb +196 -0
- data/lib/action_view/renderer/object_renderer.rb +34 -0
- data/lib/action_view/renderer/partial_renderer/collection_caching.rb +61 -16
- data/lib/action_view/renderer/partial_renderer.rb +21 -273
- data/lib/action_view/renderer/renderer.rb +59 -4
- data/lib/action_view/renderer/streaming_template_renderer.rb +10 -8
- data/lib/action_view/renderer/template_renderer.rb +35 -27
- data/lib/action_view/rendering.rb +54 -33
- data/lib/action_view/routing_url_for.rb +13 -12
- data/lib/action_view/template/error.rb +30 -15
- data/lib/action_view/template/handlers/builder.rb +2 -2
- data/lib/action_view/template/handlers/erb/erubi.rb +15 -9
- data/lib/action_view/template/handlers/erb.rb +16 -11
- 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/handlers.rb +1 -1
- data/lib/action_view/template/html.rb +5 -6
- data/lib/action_view/template/inline.rb +22 -0
- data/lib/action_view/template/raw_file.rb +25 -0
- data/lib/action_view/template/renderable.rb +24 -0
- data/lib/action_view/template/resolver.rb +191 -150
- data/lib/action_view/template/sources/file.rb +17 -0
- data/lib/action_view/template/sources.rb +13 -0
- data/lib/action_view/template/text.rb +2 -3
- data/lib/action_view/template.rb +66 -75
- data/lib/action_view/test_case.rb +21 -29
- data/lib/action_view/testing/resolvers.rb +18 -27
- data/lib/action_view/unbound_template.rb +31 -0
- data/lib/action_view/view_paths.rb +59 -38
- data/lib/action_view.rb +7 -2
- data/lib/assets/compiled/rails-ujs.js +32 -6
- metadata +29 -18
- data/lib/action_view/helpers/record_tag_helper.rb +0 -23
data/lib/action_view/template.rb
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "active_support/core_ext/object/try"
|
4
|
-
require "active_support/core_ext/kernel/singleton_class"
|
5
3
|
require "thread"
|
4
|
+
require "delegate"
|
6
5
|
|
7
6
|
module ActionView
|
8
7
|
# = Action View Template
|
@@ -103,41 +102,37 @@ module ActionView
|
|
103
102
|
|
104
103
|
eager_autoload do
|
105
104
|
autoload :Error
|
105
|
+
autoload :RawFile
|
106
|
+
autoload :Renderable
|
106
107
|
autoload :Handlers
|
107
108
|
autoload :HTML
|
109
|
+
autoload :Inline
|
110
|
+
autoload :Sources
|
108
111
|
autoload :Text
|
109
112
|
autoload :Types
|
110
113
|
end
|
111
114
|
|
112
115
|
extend Template::Handlers
|
113
116
|
|
114
|
-
|
115
|
-
|
116
|
-
attr_reader :source, :identifier, :handler, :original_encoding, :updated_at
|
117
|
-
|
118
|
-
# This finalizer is needed (and exactly with a proc inside another proc)
|
119
|
-
# otherwise templates leak in development.
|
120
|
-
Finalizer = proc do |method_name, mod| # :nodoc:
|
121
|
-
proc do
|
122
|
-
mod.module_eval do
|
123
|
-
remove_possible_method method_name
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
def initialize(source, identifier, handler, details)
|
129
|
-
format = details[:format] || (handler.default_format if handler.respond_to?(:default_format))
|
117
|
+
attr_reader :identifier, :handler
|
118
|
+
attr_reader :variable, :format, :variant, :locals, :virtual_path
|
130
119
|
|
120
|
+
def initialize(source, identifier, handler, locals:, format: nil, variant: nil, virtual_path: nil)
|
131
121
|
@source = source
|
132
122
|
@identifier = identifier
|
133
123
|
@handler = handler
|
134
124
|
@compiled = false
|
135
|
-
@
|
136
|
-
@
|
137
|
-
|
138
|
-
@
|
139
|
-
|
140
|
-
|
125
|
+
@locals = locals
|
126
|
+
@virtual_path = virtual_path
|
127
|
+
|
128
|
+
@variable = if @virtual_path
|
129
|
+
base = @virtual_path.end_with?("/") ? "" : ::File.basename(@virtual_path)
|
130
|
+
base =~ /\A_?(.*?)(?:\.\w+)*\z/
|
131
|
+
$1.to_sym
|
132
|
+
end
|
133
|
+
|
134
|
+
@format = format
|
135
|
+
@variant = variant
|
141
136
|
@compile_mutex = Mutex.new
|
142
137
|
end
|
143
138
|
|
@@ -153,40 +148,29 @@ module ActionView
|
|
153
148
|
# This method is instrumented as "!render_template.action_view". Notice that
|
154
149
|
# we use a bang in this instrumentation because you don't want to
|
155
150
|
# consume this in production. This is only slow if it's being listened to.
|
156
|
-
def render(view, locals, buffer =
|
151
|
+
def render(view, locals, buffer = ActionView::OutputBuffer.new, add_to_stack: true, &block)
|
157
152
|
instrument_render_template do
|
158
153
|
compile!(view)
|
159
|
-
view.
|
154
|
+
view._run(method_name, self, locals, buffer, add_to_stack: add_to_stack, &block)
|
160
155
|
end
|
161
156
|
rescue => e
|
162
157
|
handle_render_error(view, e)
|
163
158
|
end
|
164
159
|
|
165
160
|
def type
|
166
|
-
@type ||= Types[
|
161
|
+
@type ||= Types[format]
|
167
162
|
end
|
168
163
|
|
169
|
-
|
170
|
-
|
171
|
-
# This method is useful if you have a template object but it does not contain its source
|
172
|
-
# anymore since it was already compiled. In such cases, all you need to do is to call
|
173
|
-
# refresh passing in the view object.
|
174
|
-
#
|
175
|
-
# Notice this method raises an error if the template to be refreshed does not have a
|
176
|
-
# virtual path set (true just for inline templates).
|
177
|
-
def refresh(view)
|
178
|
-
raise "A template needs to have a virtual path in order to be refreshed" unless @virtual_path
|
179
|
-
lookup = view.lookup_context
|
180
|
-
pieces = @virtual_path.split("/")
|
181
|
-
name = pieces.pop
|
182
|
-
partial = !!name.sub!(/^_/, "")
|
183
|
-
lookup.disable_cache do
|
184
|
-
lookup.find_template(name, [ pieces.join("/") ], partial, @locals)
|
185
|
-
end
|
164
|
+
def short_identifier
|
165
|
+
@short_identifier ||= defined?(Rails.root) ? identifier.delete_prefix("#{Rails.root}/") : identifier
|
186
166
|
end
|
187
167
|
|
188
168
|
def inspect
|
189
|
-
|
169
|
+
"#<#{self.class.name} #{short_identifier} locals=#{@locals.inspect}>"
|
170
|
+
end
|
171
|
+
|
172
|
+
def source
|
173
|
+
@source.to_s
|
190
174
|
end
|
191
175
|
|
192
176
|
# This method is responsible for properly setting the encoding of the
|
@@ -200,7 +184,9 @@ module ActionView
|
|
200
184
|
# before passing the source on to the template engine, leaving a
|
201
185
|
# blank line in its stead.
|
202
186
|
def encode!
|
203
|
-
|
187
|
+
source = self.source
|
188
|
+
|
189
|
+
return source unless source.encoding == Encoding::BINARY
|
204
190
|
|
205
191
|
# Look for # encoding: *. If we find one, we'll encode the
|
206
192
|
# String in that encoding, otherwise, we'll use the
|
@@ -233,8 +219,20 @@ module ActionView
|
|
233
219
|
end
|
234
220
|
end
|
235
221
|
|
236
|
-
private
|
237
222
|
|
223
|
+
# Exceptions are marshalled when using the parallel test runner with DRb, so we need
|
224
|
+
# to ensure that references to the template object can be marshalled as well. This means forgoing
|
225
|
+
# the marshalling of the compiler mutex and instantiating that again on unmarshalling.
|
226
|
+
def marshal_dump # :nodoc:
|
227
|
+
[ @source, @identifier, @handler, @compiled, @locals, @virtual_path, @format, @variant ]
|
228
|
+
end
|
229
|
+
|
230
|
+
def marshal_load(array) # :nodoc:
|
231
|
+
@source, @identifier, @handler, @compiled, @locals, @virtual_path, @format, @variant = *array
|
232
|
+
@compile_mutex = Mutex.new
|
233
|
+
end
|
234
|
+
|
235
|
+
private
|
238
236
|
# Compile a template. This method ensures a template is compiled
|
239
237
|
# just once and removes the source after it is compiled.
|
240
238
|
def compile!(view)
|
@@ -249,19 +247,12 @@ module ActionView
|
|
249
247
|
# re-compilation
|
250
248
|
return if @compiled
|
251
249
|
|
252
|
-
|
253
|
-
mod = ActionView::CompiledTemplates
|
254
|
-
else
|
255
|
-
mod = view.singleton_class
|
256
|
-
end
|
250
|
+
mod = view.compiled_method_container
|
257
251
|
|
258
252
|
instrument("!compile_template") do
|
259
253
|
compile(mod)
|
260
254
|
end
|
261
255
|
|
262
|
-
# Just discard the source if we have a virtual path. This
|
263
|
-
# means we can get the template back.
|
264
|
-
@source = nil if @virtual_path
|
265
256
|
@compiled = true
|
266
257
|
end
|
267
258
|
end
|
@@ -279,16 +270,15 @@ module ActionView
|
|
279
270
|
# In general, this means that templates will be UTF-8 inside of Rails,
|
280
271
|
# regardless of the original source encoding.
|
281
272
|
def compile(mod)
|
282
|
-
encode!
|
283
|
-
code = @handler.call(self)
|
273
|
+
source = encode!
|
274
|
+
code = @handler.call(self, source)
|
284
275
|
|
285
276
|
# Make sure that the resulting String to be eval'd is in the
|
286
277
|
# encoding of the code
|
287
|
-
|
278
|
+
original_source = source
|
279
|
+
source = +<<-end_src
|
288
280
|
def #{method_name}(local_assigns, output_buffer)
|
289
|
-
|
290
|
-
ensure
|
291
|
-
@virtual_path, @output_buffer = _old_virtual_path, _old_output_buffer
|
281
|
+
@virtual_path = #{@virtual_path.inspect};#{locals_code};#{code}
|
292
282
|
end
|
293
283
|
end_src
|
294
284
|
|
@@ -303,11 +293,17 @@ module ActionView
|
|
303
293
|
# handler is valid in the default_internal. This is for handlers
|
304
294
|
# that handle encoding but screw up
|
305
295
|
unless source.valid_encoding?
|
306
|
-
raise WrongEncodingError.new(
|
296
|
+
raise WrongEncodingError.new(source, Encoding.default_internal)
|
307
297
|
end
|
308
298
|
|
309
|
-
|
310
|
-
|
299
|
+
begin
|
300
|
+
mod.module_eval(source, identifier, 0)
|
301
|
+
rescue SyntaxError
|
302
|
+
# Account for when code in the template is not syntactically valid; e.g. if we're using
|
303
|
+
# ERB and the user writes <%= foo( %>, attempting to call a helper `foo` and interpolate
|
304
|
+
# the result into the template, but missing an end parenthesis.
|
305
|
+
raise SyntaxErrorInTemplate.new(self, original_source)
|
306
|
+
end
|
311
307
|
end
|
312
308
|
|
313
309
|
def handle_render_error(view, e)
|
@@ -315,12 +311,7 @@ module ActionView
|
|
315
311
|
e.sub_template_of(self)
|
316
312
|
raise e
|
317
313
|
else
|
318
|
-
|
319
|
-
unless template.source
|
320
|
-
template = refresh(view)
|
321
|
-
template.encode!
|
322
|
-
end
|
323
|
-
raise Template::Error.new(template)
|
314
|
+
raise Template::Error.new(self)
|
324
315
|
end
|
325
316
|
end
|
326
317
|
|
@@ -331,19 +322,19 @@ module ActionView
|
|
331
322
|
locals = locals.grep(/\A@?(?![A-Z0-9])(?:[[:alnum:]_]|[^\0-\177])+\z/)
|
332
323
|
|
333
324
|
# Assign for the same variable is to suppress unused variable warning
|
334
|
-
locals.each_with_object(""
|
325
|
+
locals.each_with_object(+"") { |key, code| code << "#{key} = local_assigns[:#{key}]; #{key} = #{key};" }
|
335
326
|
end
|
336
327
|
|
337
328
|
def method_name
|
338
329
|
@method_name ||= begin
|
339
|
-
m = "_#{identifier_method_name}__#{@identifier.hash}_#{__id__}"
|
340
|
-
m.tr!("-"
|
330
|
+
m = +"_#{identifier_method_name}__#{@identifier.hash}_#{__id__}"
|
331
|
+
m.tr!("-", "_")
|
341
332
|
m
|
342
333
|
end
|
343
334
|
end
|
344
335
|
|
345
336
|
def identifier_method_name
|
346
|
-
|
337
|
+
short_identifier.tr("^a-z_", "_")
|
347
338
|
end
|
348
339
|
|
349
340
|
def instrument(action, &block) # :doc:
|
@@ -351,7 +342,7 @@ module ActionView
|
|
351
342
|
end
|
352
343
|
|
353
344
|
def instrument_render_template(&block)
|
354
|
-
ActiveSupport::Notifications.instrument("!render_template.action_view"
|
345
|
+
ActiveSupport::Notifications.instrument("!render_template.action_view", instrument_payload, &block)
|
355
346
|
end
|
356
347
|
|
357
348
|
def instrument_payload
|
@@ -16,11 +16,12 @@ module ActionView
|
|
16
16
|
attr_accessor :request, :response, :params
|
17
17
|
|
18
18
|
class << self
|
19
|
-
|
19
|
+
# Overrides AbstractController::Base#controller_path
|
20
|
+
attr_accessor :controller_path
|
20
21
|
end
|
21
22
|
|
22
23
|
def controller_path=(path)
|
23
|
-
self.class.controller_path =
|
24
|
+
self.class.controller_path = path
|
24
25
|
end
|
25
26
|
|
26
27
|
def initialize
|
@@ -73,10 +74,11 @@ module ActionView
|
|
73
74
|
def helper_method(*methods)
|
74
75
|
# Almost a duplicate from ActionController::Helpers
|
75
76
|
methods.flatten.each do |method|
|
76
|
-
|
77
|
+
_helpers_for_modification.module_eval <<-end_eval, __FILE__, __LINE__ + 1
|
77
78
|
def #{method}(*args, &block) # def current_user(*args, &block)
|
78
|
-
_test_case.send(
|
79
|
+
_test_case.send(:'#{method}', *args, &block) # _test_case.send(:'current_user', *args, &block)
|
79
80
|
end # end
|
81
|
+
ruby2_keywords(:'#{method}') if respond_to?(:ruby2_keywords, true)
|
80
82
|
end_eval
|
81
83
|
end
|
82
84
|
end
|
@@ -93,7 +95,6 @@ module ActionView
|
|
93
95
|
end
|
94
96
|
|
95
97
|
private
|
96
|
-
|
97
98
|
def include_helper_modules!
|
98
99
|
helper(helper_class) if helper_class
|
99
100
|
include _helpers
|
@@ -101,16 +102,17 @@ module ActionView
|
|
101
102
|
end
|
102
103
|
|
103
104
|
def setup_with_controller
|
104
|
-
|
105
|
+
controller_class = Class.new(ActionView::TestCase::TestController)
|
106
|
+
@controller = controller_class.new
|
105
107
|
@request = @controller.request
|
106
108
|
@view_flow = ActionView::OutputFlow.new
|
107
109
|
# empty string ensures buffer has UTF-8 encoding as
|
108
110
|
# new without arguments returns ASCII-8BIT encoded buffer like String#new
|
109
111
|
@output_buffer = ActiveSupport::SafeBuffer.new ""
|
110
|
-
@rendered = ""
|
112
|
+
@rendered = +""
|
111
113
|
|
112
|
-
|
113
|
-
|
114
|
+
test_case_instance = self
|
115
|
+
controller_class.define_method(:_test_case) { test_case_instance }
|
114
116
|
end
|
115
117
|
|
116
118
|
def config
|
@@ -160,34 +162,24 @@ module ActionView
|
|
160
162
|
included do
|
161
163
|
setup :setup_with_controller
|
162
164
|
ActiveSupport.run_load_hooks(:action_view_test_case, self)
|
163
|
-
end
|
164
|
-
|
165
|
-
private
|
166
|
-
|
167
|
-
# Need to experiment if this priority is the best one: rendered => output_buffer
|
168
|
-
def document_root_element
|
169
|
-
Nokogiri::HTML::Document.parse(@rendered.blank? ? @output_buffer : @rendered).root
|
170
|
-
end
|
171
165
|
|
172
|
-
|
173
|
-
_helpers.module_eval do
|
174
|
-
silence_redefinition_of_method :protect_against_forgery?
|
166
|
+
helper do
|
175
167
|
def protect_against_forgery?
|
176
168
|
false
|
177
169
|
end
|
178
|
-
end
|
179
|
-
end
|
180
170
|
|
181
|
-
|
182
|
-
|
183
|
-
_helpers.module_eval do
|
184
|
-
unless private_method_defined?(:_test_case)
|
185
|
-
define_method(:_test_case) { test_case_instance }
|
186
|
-
private :_test_case
|
171
|
+
def _test_case
|
172
|
+
controller._test_case
|
187
173
|
end
|
188
174
|
end
|
189
175
|
end
|
190
176
|
|
177
|
+
private
|
178
|
+
# Need to experiment if this priority is the best one: rendered => output_buffer
|
179
|
+
def document_root_element
|
180
|
+
Nokogiri::HTML::Document.parse(@rendered.blank? ? @output_buffer : @rendered).root
|
181
|
+
end
|
182
|
+
|
191
183
|
module Locals
|
192
184
|
attr_accessor :rendered_views
|
193
185
|
|
@@ -284,7 +276,7 @@ module ActionView
|
|
284
276
|
|
285
277
|
def respond_to_missing?(name, include_private = false)
|
286
278
|
begin
|
287
|
-
routes = @controller.respond_to?(:_routes) && @controller._routes
|
279
|
+
routes = defined?(@controller) && @controller.respond_to?(:_routes) && @controller._routes
|
288
280
|
rescue
|
289
281
|
# Don't call routes, if there is an error on _routes call
|
290
282
|
end
|
@@ -7,12 +7,15 @@ module ActionView #:nodoc:
|
|
7
7
|
# file system. This is used internally by Rails' own test suite, and is
|
8
8
|
# useful for testing extensions that have no way of knowing what the file
|
9
9
|
# system will look like at runtime.
|
10
|
-
class FixtureResolver <
|
11
|
-
|
12
|
-
|
13
|
-
def initialize(hash = {}, pattern = nil)
|
14
|
-
super(pattern)
|
10
|
+
class FixtureResolver < OptimizedFileSystemResolver
|
11
|
+
def initialize(hash = {})
|
12
|
+
super("")
|
15
13
|
@hash = hash
|
14
|
+
@path = ""
|
15
|
+
end
|
16
|
+
|
17
|
+
def data
|
18
|
+
@hash
|
16
19
|
end
|
17
20
|
|
18
21
|
def to_s
|
@@ -20,35 +23,23 @@ module ActionView #:nodoc:
|
|
20
23
|
end
|
21
24
|
|
22
25
|
private
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
end
|
29
|
-
query = /^(#{Regexp.escape(path)})#{query}$/
|
30
|
-
|
31
|
-
templates = []
|
32
|
-
@hash.each do |_path, array|
|
33
|
-
source, updated_at = array
|
34
|
-
next unless query.match?(_path)
|
35
|
-
handler, format, variant = extract_handler_and_format_and_variant(_path)
|
36
|
-
templates << Template.new(source, _path, handler,
|
37
|
-
virtual_path: path.virtual,
|
38
|
-
format: format,
|
39
|
-
variant: variant,
|
40
|
-
updated_at: updated_at
|
41
|
-
)
|
26
|
+
def find_candidate_template_paths(path)
|
27
|
+
@hash.keys.select do |fixture|
|
28
|
+
fixture.start_with?(path.virtual)
|
29
|
+
end.map do |fixture|
|
30
|
+
"/#{fixture}"
|
42
31
|
end
|
32
|
+
end
|
43
33
|
|
44
|
-
|
34
|
+
def source_for_template(template)
|
35
|
+
@hash[template[1..template.size]]
|
45
36
|
end
|
46
37
|
end
|
47
38
|
|
48
39
|
class NullResolver < PathResolver
|
49
|
-
def query(path, exts, _,
|
40
|
+
def query(path, exts, _, locals, cache:)
|
50
41
|
handler, format, variant = extract_handler_and_format_and_variant(path)
|
51
|
-
[ActionView::Template.new("Template generated by Null Resolver", path.virtual, handler, virtual_path: path.virtual, format: format, variant: variant)]
|
42
|
+
[ActionView::Template.new("Template generated by Null Resolver", path.virtual, handler, virtual_path: path.virtual, format: format, variant: variant, locals: locals)]
|
52
43
|
end
|
53
44
|
end
|
54
45
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "concurrent/map"
|
4
|
+
|
5
|
+
module ActionView
|
6
|
+
class UnboundTemplate
|
7
|
+
def initialize(source, identifier, handler, options)
|
8
|
+
@source = source
|
9
|
+
@identifier = identifier
|
10
|
+
@handler = handler
|
11
|
+
@options = options
|
12
|
+
|
13
|
+
@templates = Concurrent::Map.new(initial_capacity: 2)
|
14
|
+
end
|
15
|
+
|
16
|
+
def bind_locals(locals)
|
17
|
+
@templates[locals] ||= build_template(locals)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
def build_template(locals)
|
22
|
+
options = @options.merge(locals: locals)
|
23
|
+
Template.new(
|
24
|
+
@source,
|
25
|
+
@identifier,
|
26
|
+
@handler,
|
27
|
+
**options
|
28
|
+
)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -5,13 +5,21 @@ module ActionView
|
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
|
7
7
|
included do
|
8
|
-
|
8
|
+
ViewPaths.set_view_paths(self, ActionView::PathSet.new.freeze)
|
9
9
|
end
|
10
10
|
|
11
11
|
delegate :template_exists?, :any_templates?, :view_paths, :formats, :formats=,
|
12
12
|
:locale, :locale=, to: :lookup_context
|
13
13
|
|
14
14
|
module ClassMethods
|
15
|
+
def _view_paths
|
16
|
+
ViewPaths.get_view_paths(self)
|
17
|
+
end
|
18
|
+
|
19
|
+
def _view_paths=(paths)
|
20
|
+
ViewPaths.set_view_paths(self, paths)
|
21
|
+
end
|
22
|
+
|
15
23
|
def _prefixes # :nodoc:
|
16
24
|
@_prefixes ||= begin
|
17
25
|
return local_prefixes if superclass.abstract?
|
@@ -20,8 +28,41 @@ module ActionView
|
|
20
28
|
end
|
21
29
|
end
|
22
30
|
|
23
|
-
|
31
|
+
# Append a path to the list of view paths for this controller.
|
32
|
+
#
|
33
|
+
# ==== Parameters
|
34
|
+
# * <tt>path</tt> - If a String is provided, it gets converted into
|
35
|
+
# the default view path. You may also provide a custom view path
|
36
|
+
# (see ActionView::PathSet for more information)
|
37
|
+
def append_view_path(path)
|
38
|
+
self._view_paths = view_paths + Array(path)
|
39
|
+
end
|
24
40
|
|
41
|
+
# Prepend a path to the list of view paths for this controller.
|
42
|
+
#
|
43
|
+
# ==== Parameters
|
44
|
+
# * <tt>path</tt> - If a String is provided, it gets converted into
|
45
|
+
# the default view path. You may also provide a custom view path
|
46
|
+
# (see ActionView::PathSet for more information)
|
47
|
+
def prepend_view_path(path)
|
48
|
+
self._view_paths = ActionView::PathSet.new(Array(path) + view_paths)
|
49
|
+
end
|
50
|
+
|
51
|
+
# A list of all of the default view paths for this controller.
|
52
|
+
def view_paths
|
53
|
+
_view_paths
|
54
|
+
end
|
55
|
+
|
56
|
+
# Set the view paths.
|
57
|
+
#
|
58
|
+
# ==== Parameters
|
59
|
+
# * <tt>paths</tt> - If a PathSet is provided, use that;
|
60
|
+
# otherwise, process the parameter into a PathSet.
|
61
|
+
def view_paths=(paths)
|
62
|
+
self._view_paths = ActionView::PathSet.new(Array(paths))
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
25
66
|
# Override this method in your controller if you want to change paths prefixes for finding views.
|
26
67
|
# Prefixes defined here will still be added to parents' <tt>._prefixes</tt>.
|
27
68
|
def local_prefixes
|
@@ -29,6 +70,22 @@ module ActionView
|
|
29
70
|
end
|
30
71
|
end
|
31
72
|
|
73
|
+
# :stopdoc:
|
74
|
+
@all_view_paths = {}
|
75
|
+
|
76
|
+
def self.get_view_paths(klass)
|
77
|
+
@all_view_paths[klass] || get_view_paths(klass.superclass)
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.set_view_paths(klass, paths)
|
81
|
+
@all_view_paths[klass] = paths
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.all_view_paths
|
85
|
+
@all_view_paths.values.uniq
|
86
|
+
end
|
87
|
+
# :startdoc:
|
88
|
+
|
32
89
|
# The prefixes used in render "foo" shortcuts.
|
33
90
|
def _prefixes # :nodoc:
|
34
91
|
self.class._prefixes
|
@@ -65,41 +122,5 @@ module ActionView
|
|
65
122
|
def prepend_view_path(path)
|
66
123
|
lookup_context.view_paths.unshift(*path)
|
67
124
|
end
|
68
|
-
|
69
|
-
module ClassMethods
|
70
|
-
# Append a path to the list of view paths for this controller.
|
71
|
-
#
|
72
|
-
# ==== Parameters
|
73
|
-
# * <tt>path</tt> - If a String is provided, it gets converted into
|
74
|
-
# the default view path. You may also provide a custom view path
|
75
|
-
# (see ActionView::PathSet for more information)
|
76
|
-
def append_view_path(path)
|
77
|
-
self._view_paths = view_paths + Array(path)
|
78
|
-
end
|
79
|
-
|
80
|
-
# Prepend a path to the list of view paths for this controller.
|
81
|
-
#
|
82
|
-
# ==== Parameters
|
83
|
-
# * <tt>path</tt> - If a String is provided, it gets converted into
|
84
|
-
# the default view path. You may also provide a custom view path
|
85
|
-
# (see ActionView::PathSet for more information)
|
86
|
-
def prepend_view_path(path)
|
87
|
-
self._view_paths = ActionView::PathSet.new(Array(path) + view_paths)
|
88
|
-
end
|
89
|
-
|
90
|
-
# A list of all of the default view paths for this controller.
|
91
|
-
def view_paths
|
92
|
-
_view_paths
|
93
|
-
end
|
94
|
-
|
95
|
-
# Set the view paths.
|
96
|
-
#
|
97
|
-
# ==== Parameters
|
98
|
-
# * <tt>paths</tt> - If a PathSet is provided, use that;
|
99
|
-
# otherwise, process the parameter into a PathSet.
|
100
|
-
def view_paths=(paths)
|
101
|
-
self._view_paths = ActionView::PathSet.new(Array(paths))
|
102
|
-
end
|
103
|
-
end
|
104
125
|
end
|
105
126
|
end
|
data/lib/action_view.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
#--
|
4
|
-
# Copyright (c) 2004-
|
4
|
+
# Copyright (c) 2004-2020 David Heinemeier Hansson
|
5
5
|
#
|
6
6
|
# Permission is hereby granted, free of charge, to any person obtaining
|
7
7
|
# a copy of this software and associated documentation files (the
|
@@ -35,7 +35,6 @@ module ActionView
|
|
35
35
|
eager_autoload do
|
36
36
|
autoload :Base
|
37
37
|
autoload :Context
|
38
|
-
autoload :CompiledTemplates, "action_view/context"
|
39
38
|
autoload :Digestor
|
40
39
|
autoload :Helpers
|
41
40
|
autoload :LookupContext
|
@@ -45,12 +44,15 @@ module ActionView
|
|
45
44
|
autoload :Rendering
|
46
45
|
autoload :RoutingUrlFor
|
47
46
|
autoload :Template
|
47
|
+
autoload :UnboundTemplate
|
48
48
|
autoload :ViewPaths
|
49
49
|
|
50
50
|
autoload_under "renderer" do
|
51
51
|
autoload :Renderer
|
52
52
|
autoload :AbstractRenderer
|
53
53
|
autoload :PartialRenderer
|
54
|
+
autoload :CollectionRenderer
|
55
|
+
autoload :ObjectRenderer
|
54
56
|
autoload :TemplateRenderer
|
55
57
|
autoload :StreamingTemplateRenderer
|
56
58
|
end
|
@@ -58,6 +60,7 @@ module ActionView
|
|
58
60
|
autoload_at "action_view/template/resolver" do
|
59
61
|
autoload :Resolver
|
60
62
|
autoload :PathResolver
|
63
|
+
autoload :FileSystemResolver
|
61
64
|
autoload :OptimizedFileSystemResolver
|
62
65
|
autoload :FallbackFileSystemResolver
|
63
66
|
end
|
@@ -77,10 +80,12 @@ module ActionView
|
|
77
80
|
autoload :ActionViewError
|
78
81
|
autoload :EncodingError
|
79
82
|
autoload :TemplateError
|
83
|
+
autoload :SyntaxErrorInTemplate
|
80
84
|
autoload :WrongEncodingError
|
81
85
|
end
|
82
86
|
end
|
83
87
|
|
88
|
+
autoload :CacheExpiry
|
84
89
|
autoload :TestCase
|
85
90
|
|
86
91
|
def self.eager_load!
|