actionview 6.0.0.beta1 → 6.1.4
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 +273 -119
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -3
- data/lib/action_view/base.rb +81 -15
- data/lib/action_view/cache_expiry.rb +52 -0
- data/lib/action_view/context.rb +0 -5
- data/lib/action_view/dependency_tracker.rb +10 -4
- data/lib/action_view/digestor.rb +11 -19
- data/lib/action_view/flows.rb +0 -1
- data/lib/action_view/gem_version.rb +3 -3
- data/lib/action_view/helpers/active_model_helper.rb +0 -1
- data/lib/action_view/helpers/asset_tag_helper.rb +62 -22
- data/lib/action_view/helpers/asset_url_helper.rb +6 -4
- data/lib/action_view/helpers/atom_feed_helper.rb +2 -1
- data/lib/action_view/helpers/cache_helper.rb +16 -23
- data/lib/action_view/helpers/csp_helper.rb +4 -2
- data/lib/action_view/helpers/date_helper.rb +5 -6
- data/lib/action_view/helpers/form_helper.rb +70 -34
- data/lib/action_view/helpers/form_options_helper.rb +10 -18
- data/lib/action_view/helpers/form_tag_helper.rb +12 -9
- data/lib/action_view/helpers/javascript_helper.rb +7 -5
- data/lib/action_view/helpers/number_helper.rb +9 -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 +10 -16
- data/lib/action_view/helpers/tag_helper.rb +94 -19
- data/lib/action_view/helpers/tags/base.rb +10 -7
- 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 +0 -1
- 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/week_field.rb +1 -2
- data/lib/action_view/helpers/text_helper.rb +2 -3
- data/lib/action_view/helpers/translation_helper.rb +98 -51
- data/lib/action_view/helpers/url_helper.rb +124 -16
- data/lib/action_view/layouts.rb +8 -10
- data/lib/action_view/log_subscriber.rb +26 -11
- data/lib/action_view/lookup_context.rb +59 -31
- data/lib/action_view/path_set.rb +3 -12
- data/lib/action_view/railtie.rb +39 -41
- data/lib/action_view/record_identifier.rb +0 -1
- 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 +35 -29
- 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 +9 -7
- data/lib/action_view/renderer/template_renderer.rb +35 -27
- data/lib/action_view/rendering.rb +49 -29
- data/lib/action_view/routing_url_for.rb +1 -1
- 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 +14 -19
- 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 +141 -140
- 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 +49 -75
- data/lib/action_view/test_case.rb +20 -28
- 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 +25 -16
- metadata +30 -18
data/lib/action_view/template.rb
CHANGED
@@ -1,16 +1,13 @@
|
|
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
|
9
8
|
class Template
|
10
9
|
extend ActiveSupport::Autoload
|
11
10
|
|
12
|
-
mattr_accessor :finalize_compiled_template_methods, default: true
|
13
|
-
|
14
11
|
# === Encodings in ActionView::Template
|
15
12
|
#
|
16
13
|
# ActionView::Template is one of a few sources of potential
|
@@ -105,41 +102,37 @@ module ActionView
|
|
105
102
|
|
106
103
|
eager_autoload do
|
107
104
|
autoload :Error
|
105
|
+
autoload :RawFile
|
106
|
+
autoload :Renderable
|
108
107
|
autoload :Handlers
|
109
108
|
autoload :HTML
|
109
|
+
autoload :Inline
|
110
|
+
autoload :Sources
|
110
111
|
autoload :Text
|
111
112
|
autoload :Types
|
112
113
|
end
|
113
114
|
|
114
115
|
extend Template::Handlers
|
115
116
|
|
116
|
-
|
117
|
-
|
118
|
-
attr_reader :source, :identifier, :handler, :original_encoding, :updated_at
|
119
|
-
|
120
|
-
# This finalizer is needed (and exactly with a proc inside another proc)
|
121
|
-
# otherwise templates leak in development.
|
122
|
-
Finalizer = proc do |method_name, mod| # :nodoc:
|
123
|
-
proc do
|
124
|
-
mod.module_eval do
|
125
|
-
remove_possible_method method_name
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
def initialize(source, identifier, handler, details)
|
131
|
-
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
|
132
119
|
|
120
|
+
def initialize(source, identifier, handler, locals:, format: nil, variant: nil, virtual_path: nil)
|
133
121
|
@source = source
|
134
122
|
@identifier = identifier
|
135
123
|
@handler = handler
|
136
124
|
@compiled = false
|
137
|
-
@
|
138
|
-
@
|
139
|
-
|
140
|
-
@
|
141
|
-
|
142
|
-
|
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
|
143
136
|
@compile_mutex = Mutex.new
|
144
137
|
end
|
145
138
|
|
@@ -155,40 +148,29 @@ module ActionView
|
|
155
148
|
# This method is instrumented as "!render_template.action_view". Notice that
|
156
149
|
# we use a bang in this instrumentation because you don't want to
|
157
150
|
# consume this in production. This is only slow if it's being listened to.
|
158
|
-
def render(view, locals, buffer =
|
151
|
+
def render(view, locals, buffer = ActionView::OutputBuffer.new, add_to_stack: true, &block)
|
159
152
|
instrument_render_template do
|
160
153
|
compile!(view)
|
161
|
-
view.
|
154
|
+
view._run(method_name, self, locals, buffer, add_to_stack: add_to_stack, &block)
|
162
155
|
end
|
163
156
|
rescue => e
|
164
157
|
handle_render_error(view, e)
|
165
158
|
end
|
166
159
|
|
167
160
|
def type
|
168
|
-
@type ||= Types[
|
161
|
+
@type ||= Types[format]
|
169
162
|
end
|
170
163
|
|
171
|
-
|
172
|
-
|
173
|
-
# This method is useful if you have a template object but it does not contain its source
|
174
|
-
# anymore since it was already compiled. In such cases, all you need to do is to call
|
175
|
-
# refresh passing in the view object.
|
176
|
-
#
|
177
|
-
# Notice this method raises an error if the template to be refreshed does not have a
|
178
|
-
# virtual path set (true just for inline templates).
|
179
|
-
def refresh(view)
|
180
|
-
raise "A template needs to have a virtual path in order to be refreshed" unless @virtual_path
|
181
|
-
lookup = view.lookup_context
|
182
|
-
pieces = @virtual_path.split("/")
|
183
|
-
name = pieces.pop
|
184
|
-
partial = !!name.sub!(/^_/, "")
|
185
|
-
lookup.disable_cache do
|
186
|
-
lookup.find_template(name, [ pieces.join("/") ], partial, @locals)
|
187
|
-
end
|
164
|
+
def short_identifier
|
165
|
+
@short_identifier ||= defined?(Rails.root) ? identifier.delete_prefix("#{Rails.root}/") : identifier
|
188
166
|
end
|
189
167
|
|
190
168
|
def inspect
|
191
|
-
|
169
|
+
"#<#{self.class.name} #{short_identifier} locals=#{@locals.inspect}>"
|
170
|
+
end
|
171
|
+
|
172
|
+
def source
|
173
|
+
@source.to_s
|
192
174
|
end
|
193
175
|
|
194
176
|
# This method is responsible for properly setting the encoding of the
|
@@ -202,7 +184,9 @@ module ActionView
|
|
202
184
|
# before passing the source on to the template engine, leaving a
|
203
185
|
# blank line in its stead.
|
204
186
|
def encode!
|
205
|
-
|
187
|
+
source = self.source
|
188
|
+
|
189
|
+
return source unless source.encoding == Encoding::BINARY
|
206
190
|
|
207
191
|
# Look for # encoding: *. If we find one, we'll encode the
|
208
192
|
# String in that encoding, otherwise, we'll use the
|
@@ -240,16 +224,15 @@ module ActionView
|
|
240
224
|
# to ensure that references to the template object can be marshalled as well. This means forgoing
|
241
225
|
# the marshalling of the compiler mutex and instantiating that again on unmarshalling.
|
242
226
|
def marshal_dump # :nodoc:
|
243
|
-
[ @source, @identifier, @handler, @compiled, @
|
227
|
+
[ @source, @identifier, @handler, @compiled, @locals, @virtual_path, @format, @variant ]
|
244
228
|
end
|
245
229
|
|
246
230
|
def marshal_load(array) # :nodoc:
|
247
|
-
@source, @identifier, @handler, @compiled, @
|
231
|
+
@source, @identifier, @handler, @compiled, @locals, @virtual_path, @format, @variant = *array
|
248
232
|
@compile_mutex = Mutex.new
|
249
233
|
end
|
250
234
|
|
251
235
|
private
|
252
|
-
|
253
236
|
# Compile a template. This method ensures a template is compiled
|
254
237
|
# just once and removes the source after it is compiled.
|
255
238
|
def compile!(view)
|
@@ -264,19 +247,12 @@ module ActionView
|
|
264
247
|
# re-compilation
|
265
248
|
return if @compiled
|
266
249
|
|
267
|
-
|
268
|
-
mod = ActionView::CompiledTemplates
|
269
|
-
else
|
270
|
-
mod = view.singleton_class
|
271
|
-
end
|
250
|
+
mod = view.compiled_method_container
|
272
251
|
|
273
252
|
instrument("!compile_template") do
|
274
253
|
compile(mod)
|
275
254
|
end
|
276
255
|
|
277
|
-
# Just discard the source if we have a virtual path. This
|
278
|
-
# means we can get the template back.
|
279
|
-
@source = nil if @virtual_path
|
280
256
|
@compiled = true
|
281
257
|
end
|
282
258
|
end
|
@@ -294,16 +270,15 @@ module ActionView
|
|
294
270
|
# In general, this means that templates will be UTF-8 inside of Rails,
|
295
271
|
# regardless of the original source encoding.
|
296
272
|
def compile(mod)
|
297
|
-
encode!
|
298
|
-
code = @handler.call(self)
|
273
|
+
source = encode!
|
274
|
+
code = @handler.call(self, source)
|
299
275
|
|
300
276
|
# Make sure that the resulting String to be eval'd is in the
|
301
277
|
# encoding of the code
|
278
|
+
original_source = source
|
302
279
|
source = +<<-end_src
|
303
280
|
def #{method_name}(local_assigns, output_buffer)
|
304
|
-
|
305
|
-
ensure
|
306
|
-
@virtual_path, @output_buffer = _old_virtual_path, _old_output_buffer
|
281
|
+
@virtual_path = #{@virtual_path.inspect};#{locals_code};#{code}
|
307
282
|
end
|
308
283
|
end_src
|
309
284
|
|
@@ -318,12 +293,16 @@ module ActionView
|
|
318
293
|
# handler is valid in the default_internal. This is for handlers
|
319
294
|
# that handle encoding but screw up
|
320
295
|
unless source.valid_encoding?
|
321
|
-
raise WrongEncodingError.new(
|
296
|
+
raise WrongEncodingError.new(source, Encoding.default_internal)
|
322
297
|
end
|
323
298
|
|
324
|
-
|
325
|
-
|
326
|
-
|
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)
|
327
306
|
end
|
328
307
|
end
|
329
308
|
|
@@ -332,12 +311,7 @@ module ActionView
|
|
332
311
|
e.sub_template_of(self)
|
333
312
|
raise e
|
334
313
|
else
|
335
|
-
|
336
|
-
unless template.source
|
337
|
-
template = refresh(view)
|
338
|
-
template.encode!
|
339
|
-
end
|
340
|
-
raise Template::Error.new(template)
|
314
|
+
raise Template::Error.new(self)
|
341
315
|
end
|
342
316
|
end
|
343
317
|
|
@@ -360,7 +334,7 @@ module ActionView
|
|
360
334
|
end
|
361
335
|
|
362
336
|
def identifier_method_name
|
363
|
-
|
337
|
+
short_identifier.tr("^a-z_", "_")
|
364
338
|
end
|
365
339
|
|
366
340
|
def instrument(action, &block) # :doc:
|
@@ -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,7 +102,8 @@ 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
|
@@ -109,8 +111,8 @@ module ActionView
|
|
109
111
|
@output_buffer = ActiveSupport::SafeBuffer.new ""
|
110
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!
|