actionview 5.2.4 → 6.0.0
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 +189 -77
- data/MIT-LICENSE +1 -1
- data/README.rdoc +4 -2
- data/lib/action_view.rb +3 -2
- data/lib/action_view/base.rb +107 -10
- data/lib/action_view/buffers.rb +15 -0
- data/lib/action_view/cache_expiry.rb +54 -0
- data/lib/action_view/context.rb +5 -9
- data/lib/action_view/digestor.rb +12 -20
- data/lib/action_view/gem_version.rb +3 -3
- data/lib/action_view/helpers.rb +0 -2
- data/lib/action_view/helpers/asset_tag_helper.rb +7 -30
- data/lib/action_view/helpers/asset_url_helper.rb +4 -3
- data/lib/action_view/helpers/cache_helper.rb +18 -10
- 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 +69 -25
- data/lib/action_view/helpers/form_helper.rb +238 -6
- data/lib/action_view/helpers/form_options_helper.rb +27 -18
- data/lib/action_view/helpers/form_tag_helper.rb +12 -11
- data/lib/action_view/helpers/javascript_helper.rb +9 -8
- data/lib/action_view/helpers/number_helper.rb +5 -0
- 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 +12 -18
- data/lib/action_view/helpers/tag_helper.rb +7 -6
- data/lib/action_view/helpers/tags/base.rb +9 -5
- data/lib/action_view/helpers/tags/color_field.rb +1 -1
- data/lib/action_view/helpers/tags/translator.rb +1 -6
- data/lib/action_view/helpers/text_helper.rb +3 -3
- data/lib/action_view/helpers/translation_helper.rb +16 -12
- data/lib/action_view/helpers/url_helper.rb +14 -14
- data/lib/action_view/layouts.rb +5 -5
- data/lib/action_view/log_subscriber.rb +6 -6
- data/lib/action_view/lookup_context.rb +73 -31
- data/lib/action_view/path_set.rb +5 -10
- data/lib/action_view/railtie.rb +24 -1
- data/lib/action_view/record_identifier.rb +2 -2
- 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 +62 -16
- data/lib/action_view/renderer/renderer.rb +16 -4
- data/lib/action_view/renderer/streaming_template_renderer.rb +5 -5
- data/lib/action_view/renderer/template_renderer.rb +24 -18
- data/lib/action_view/rendering.rb +51 -31
- data/lib/action_view/routing_url_for.rb +12 -11
- data/lib/action_view/template.rb +102 -70
- 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 +17 -7
- 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 +136 -133
- 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/test_case.rb +1 -1
- 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 +30 -4
- metadata +23 -18
- data/lib/action_view/helpers/record_tag_helper.rb +0 -23
data/lib/action_view/layouts.rb
CHANGED
@@ -322,7 +322,7 @@ module ActionView
|
|
322
322
|
end
|
323
323
|
|
324
324
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
325
|
-
def _layout(formats)
|
325
|
+
def _layout(lookup_context, formats)
|
326
326
|
if _conditional_layout?
|
327
327
|
#{layout_definition}
|
328
328
|
else
|
@@ -388,8 +388,8 @@ module ActionView
|
|
388
388
|
case name
|
389
389
|
when String then _normalize_layout(name)
|
390
390
|
when Proc then name
|
391
|
-
when true then Proc.new { |formats| _default_layout(formats, true) }
|
392
|
-
when :default then Proc.new { |formats| _default_layout(formats, false) }
|
391
|
+
when true then Proc.new { |lookup_context, formats| _default_layout(lookup_context, formats, true) }
|
392
|
+
when :default then Proc.new { |lookup_context, formats| _default_layout(lookup_context, formats, false) }
|
393
393
|
when false, nil then nil
|
394
394
|
else
|
395
395
|
raise ArgumentError,
|
@@ -411,9 +411,9 @@ module ActionView
|
|
411
411
|
#
|
412
412
|
# ==== Returns
|
413
413
|
# * <tt>template</tt> - The template object for the default layout (or +nil+)
|
414
|
-
def _default_layout(formats, require_layout = false)
|
414
|
+
def _default_layout(lookup_context, formats, require_layout = false)
|
415
415
|
begin
|
416
|
-
value = _layout(formats) if action_has_layout?
|
416
|
+
value = _layout(lookup_context, formats) if action_has_layout?
|
417
417
|
rescue NameError => e
|
418
418
|
raise e, "Could not render layout: #{e.message}"
|
419
419
|
end
|
@@ -16,17 +16,17 @@ module ActionView
|
|
16
16
|
|
17
17
|
def render_template(event)
|
18
18
|
info do
|
19
|
-
message = " Rendered #{from_rails_root(event.payload[:identifier])}"
|
19
|
+
message = +" Rendered #{from_rails_root(event.payload[:identifier])}"
|
20
20
|
message << " within #{from_rails_root(event.payload[:layout])}" if event.payload[:layout]
|
21
|
-
message << " (#{event.duration.round(1)}ms)"
|
21
|
+
message << " (Duration: #{event.duration.round(1)}ms | Allocations: #{event.allocations})"
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
25
|
def render_partial(event)
|
26
26
|
info do
|
27
|
-
message = " Rendered #{from_rails_root(event.payload[:identifier])}"
|
27
|
+
message = +" Rendered #{from_rails_root(event.payload[:identifier])}"
|
28
28
|
message << " within #{from_rails_root(event.payload[:layout])}" if event.payload[:layout]
|
29
|
-
message << " (#{event.duration.round(1)}ms)"
|
29
|
+
message << " (Duration: #{event.duration.round(1)}ms | Allocations: #{event.allocations})"
|
30
30
|
message << " #{cache_message(event.payload)}" unless event.payload[:cache_hit].nil?
|
31
31
|
message
|
32
32
|
end
|
@@ -37,7 +37,7 @@ module ActionView
|
|
37
37
|
|
38
38
|
info do
|
39
39
|
" Rendered collection of #{from_rails_root(identifier)}" \
|
40
|
-
" #{render_count(event.payload)} (#{event.duration.round(1)}ms)"
|
40
|
+
" #{render_count(event.payload)} (Duration: #{event.duration.round(1)}ms | Allocations: #{event.allocations})"
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
@@ -85,7 +85,7 @@ module ActionView
|
|
85
85
|
|
86
86
|
def log_rendering_start(payload)
|
87
87
|
info do
|
88
|
-
message = " Rendering #{from_rails_root(payload[:identifier])}"
|
88
|
+
message = +" Rendering #{from_rails_root(payload[:identifier])}"
|
89
89
|
message << " within #{from_rails_root(payload[:layout])}" if payload[:layout]
|
90
90
|
message
|
91
91
|
end
|
@@ -3,6 +3,7 @@
|
|
3
3
|
require "concurrent/map"
|
4
4
|
require "active_support/core_ext/module/remove_method"
|
5
5
|
require "active_support/core_ext/module/attribute_accessors"
|
6
|
+
require "active_support/deprecation"
|
6
7
|
require "action_view/template/resolver"
|
7
8
|
|
8
9
|
module ActionView
|
@@ -15,6 +16,8 @@ module ActionView
|
|
15
16
|
# only once during the request, it speeds up all cache accesses.
|
16
17
|
class LookupContext #:nodoc:
|
17
18
|
attr_accessor :prefixes, :rendered_format
|
19
|
+
deprecate :rendered_format
|
20
|
+
deprecate :rendered_format=
|
18
21
|
|
19
22
|
mattr_accessor :fallbacks, default: FallbackFileSystemResolver.instances
|
20
23
|
|
@@ -24,7 +27,7 @@ module ActionView
|
|
24
27
|
registered_details << name
|
25
28
|
Accessors::DEFAULT_PROCS[name] = block
|
26
29
|
|
27
|
-
Accessors.
|
30
|
+
Accessors.define_method(:"default_#{name}", &block)
|
28
31
|
Accessors.module_eval <<-METHOD, __FILE__, __LINE__ + 1
|
29
32
|
def #{name}
|
30
33
|
@details.fetch(:#{name}, [])
|
@@ -57,21 +60,36 @@ module ActionView
|
|
57
60
|
alias :eql? :equal?
|
58
61
|
|
59
62
|
@details_keys = Concurrent::Map.new
|
63
|
+
@digest_cache = Concurrent::Map.new
|
60
64
|
|
61
|
-
def self.
|
65
|
+
def self.digest_cache(details)
|
66
|
+
@digest_cache[details_cache_key(details)] ||= Concurrent::Map.new
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.details_cache_key(details)
|
62
70
|
if details[:formats]
|
63
71
|
details = details.dup
|
64
72
|
details[:formats] &= Template::Types.symbols
|
65
73
|
end
|
66
|
-
@details_keys[details] ||=
|
74
|
+
@details_keys[details] ||= Object.new
|
67
75
|
end
|
68
76
|
|
69
77
|
def self.clear
|
78
|
+
ActionView::ViewPaths.all_view_paths.each do |path_set|
|
79
|
+
path_set.each(&:clear_cache)
|
80
|
+
end
|
81
|
+
ActionView::LookupContext.fallbacks.each(&:clear_cache)
|
82
|
+
@view_context_class = nil
|
70
83
|
@details_keys.clear
|
84
|
+
@digest_cache.clear
|
71
85
|
end
|
72
86
|
|
73
87
|
def self.digest_caches
|
74
|
-
@
|
88
|
+
@digest_cache.values
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.view_context_class(klass)
|
92
|
+
@view_context_class ||= klass.with_empty_template_cache
|
75
93
|
end
|
76
94
|
end
|
77
95
|
|
@@ -82,7 +100,7 @@ module ActionView
|
|
82
100
|
# Calculate the details key. Remove the handlers from calculation to improve performance
|
83
101
|
# since the user cannot modify it explicitly.
|
84
102
|
def details_key #:nodoc:
|
85
|
-
@details_key ||= DetailsKey.
|
103
|
+
@details_key ||= DetailsKey.details_cache_key(@details) if @cache
|
86
104
|
end
|
87
105
|
|
88
106
|
# Temporary skip passing the details_key forward.
|
@@ -96,7 +114,8 @@ module ActionView
|
|
96
114
|
private
|
97
115
|
|
98
116
|
def _set_detail(key, value) # :doc:
|
99
|
-
@details = @details.dup if @details_key
|
117
|
+
@details = @details.dup if @digest_cache || @details_key
|
118
|
+
@digest_cache = nil
|
100
119
|
@details_key = nil
|
101
120
|
@details[key] = value
|
102
121
|
end
|
@@ -106,20 +125,13 @@ module ActionView
|
|
106
125
|
module ViewPaths
|
107
126
|
attr_reader :view_paths, :html_fallback_for_js
|
108
127
|
|
109
|
-
# Whenever setting view paths, makes a copy so that we can manipulate them in
|
110
|
-
# instance objects as we wish.
|
111
|
-
def view_paths=(paths)
|
112
|
-
@view_paths = ActionView::PathSet.new(Array(paths))
|
113
|
-
end
|
114
|
-
|
115
128
|
def find(name, prefixes = [], partial = false, keys = [], options = {})
|
116
129
|
@view_paths.find(*args_for_lookup(name, prefixes, partial, keys, options))
|
117
130
|
end
|
118
131
|
alias :find_template :find
|
119
132
|
|
120
|
-
|
121
|
-
|
122
|
-
end
|
133
|
+
alias :find_file :find
|
134
|
+
deprecate :find_file
|
123
135
|
|
124
136
|
def find_all(name, prefixes = [], partial = false, keys = [], options = {})
|
125
137
|
@view_paths.find_all(*args_for_lookup(name, prefixes, partial, keys, options))
|
@@ -138,19 +150,34 @@ module ActionView
|
|
138
150
|
# Adds fallbacks to the view paths. Useful in cases when you are rendering
|
139
151
|
# a :file.
|
140
152
|
def with_fallbacks
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
153
|
+
view_paths = build_view_paths((@view_paths.paths + self.class.fallbacks).uniq)
|
154
|
+
|
155
|
+
if block_given?
|
156
|
+
ActiveSupport::Deprecation.warn <<~eowarn.squish
|
157
|
+
Calling `with_fallbacks` with a block is deprecated. Call methods on
|
158
|
+
the lookup context returned by `with_fallbacks` instead.
|
159
|
+
eowarn
|
160
|
+
|
161
|
+
begin
|
162
|
+
_view_paths = @view_paths
|
163
|
+
@view_paths = view_paths
|
164
|
+
yield
|
165
|
+
ensure
|
166
|
+
@view_paths = _view_paths
|
167
|
+
end
|
168
|
+
else
|
169
|
+
ActionView::LookupContext.new(view_paths, @details, @prefixes)
|
146
170
|
end
|
147
|
-
yield
|
148
|
-
ensure
|
149
|
-
added_resolvers.times { view_paths.pop }
|
150
171
|
end
|
151
172
|
|
152
173
|
private
|
153
174
|
|
175
|
+
# Whenever setting view paths, makes a copy so that we can manipulate them in
|
176
|
+
# instance objects as we wish.
|
177
|
+
def build_view_paths(paths)
|
178
|
+
ActionView::PathSet.new(Array(paths))
|
179
|
+
end
|
180
|
+
|
154
181
|
def args_for_lookup(name, prefixes, partial, keys, details_options)
|
155
182
|
name, prefixes = normalize_name(name, prefixes)
|
156
183
|
details, details_key = detail_args_for(details_options)
|
@@ -163,7 +190,7 @@ module ActionView
|
|
163
190
|
user_details = @details.merge(options)
|
164
191
|
|
165
192
|
if @cache
|
166
|
-
details_key = DetailsKey.
|
193
|
+
details_key = DetailsKey.details_cache_key(user_details)
|
167
194
|
else
|
168
195
|
details_key = nil
|
169
196
|
end
|
@@ -190,7 +217,7 @@ module ActionView
|
|
190
217
|
end
|
191
218
|
|
192
219
|
if @cache
|
193
|
-
[details, DetailsKey.
|
220
|
+
[details, DetailsKey.details_cache_key(details)]
|
194
221
|
else
|
195
222
|
[details, nil]
|
196
223
|
end
|
@@ -202,13 +229,13 @@ module ActionView
|
|
202
229
|
# name instead of the prefix.
|
203
230
|
def normalize_name(name, prefixes)
|
204
231
|
prefixes = prefixes.presence
|
205
|
-
parts = name.to_s.split("/"
|
232
|
+
parts = name.to_s.split("/")
|
206
233
|
parts.shift if parts.first.empty?
|
207
234
|
name = parts.pop
|
208
235
|
|
209
236
|
return name, prefixes || [""] if parts.empty?
|
210
237
|
|
211
|
-
parts = parts.join("/"
|
238
|
+
parts = parts.join("/")
|
212
239
|
prefixes = prefixes ? prefixes.map { |p| "#{p}/#{parts}" } : [parts]
|
213
240
|
|
214
241
|
return name, prefixes
|
@@ -221,16 +248,23 @@ module ActionView
|
|
221
248
|
|
222
249
|
def initialize(view_paths, details = {}, prefixes = [])
|
223
250
|
@details_key = nil
|
251
|
+
@digest_cache = nil
|
224
252
|
@cache = true
|
225
253
|
@prefixes = prefixes
|
226
|
-
@rendered_format = nil
|
227
254
|
|
228
255
|
@details = initialize_details({}, details)
|
229
|
-
|
256
|
+
@view_paths = build_view_paths(view_paths)
|
230
257
|
end
|
231
258
|
|
232
259
|
def digest_cache
|
233
|
-
|
260
|
+
@digest_cache ||= DetailsKey.digest_cache(@details)
|
261
|
+
end
|
262
|
+
|
263
|
+
def with_prepended_formats(formats)
|
264
|
+
details = @details.dup
|
265
|
+
details[:formats] = formats
|
266
|
+
|
267
|
+
self.class.new(@view_paths, details, @prefixes)
|
234
268
|
end
|
235
269
|
|
236
270
|
def initialize_details(target, details)
|
@@ -245,7 +279,15 @@ module ActionView
|
|
245
279
|
# add :html as fallback to :js.
|
246
280
|
def formats=(values)
|
247
281
|
if values
|
248
|
-
values
|
282
|
+
values = values.dup
|
283
|
+
values.concat(default_formats) if values.delete "*/*"
|
284
|
+
values.uniq!
|
285
|
+
|
286
|
+
invalid_values = (values - Template::Types.symbols)
|
287
|
+
unless invalid_values.empty?
|
288
|
+
raise ArgumentError, "Invalid formats: #{invalid_values.map(&:inspect).join(", ")}"
|
289
|
+
end
|
290
|
+
|
249
291
|
if values == [:js]
|
250
292
|
values << :html
|
251
293
|
@html_fallback_for_js = true
|
data/lib/action_view/path_set.rb
CHANGED
@@ -48,12 +48,11 @@ module ActionView #:nodoc:
|
|
48
48
|
find_all(*args).first || raise(MissingTemplate.new(self, *args))
|
49
49
|
end
|
50
50
|
|
51
|
-
|
52
|
-
|
53
|
-
end
|
51
|
+
alias :find_file :find
|
52
|
+
deprecate :find_file
|
54
53
|
|
55
54
|
def find_all(path, prefixes = [], *args)
|
56
|
-
_find_all path, prefixes, args
|
55
|
+
_find_all path, prefixes, args
|
57
56
|
end
|
58
57
|
|
59
58
|
def exists?(path, prefixes, *args)
|
@@ -71,15 +70,11 @@ module ActionView #:nodoc:
|
|
71
70
|
|
72
71
|
private
|
73
72
|
|
74
|
-
def _find_all(path, prefixes, args
|
73
|
+
def _find_all(path, prefixes, args)
|
75
74
|
prefixes = [prefixes] if String === prefixes
|
76
75
|
prefixes.each do |prefix|
|
77
76
|
paths.each do |resolver|
|
78
|
-
|
79
|
-
templates = resolver.find_all_anywhere(path, prefix, *args)
|
80
|
-
else
|
81
|
-
templates = resolver.find_all(path, prefix, *args)
|
82
|
-
end
|
77
|
+
templates = resolver.find_all(path, prefix, *args)
|
83
78
|
return templates unless templates.empty?
|
84
79
|
end
|
85
80
|
end
|
data/lib/action_view/railtie.rb
CHANGED
@@ -6,9 +6,13 @@ require "rails"
|
|
6
6
|
module ActionView
|
7
7
|
# = Action View Railtie
|
8
8
|
class Railtie < Rails::Engine # :nodoc:
|
9
|
+
NULL_OPTION = Object.new
|
10
|
+
|
9
11
|
config.action_view = ActiveSupport::OrderedOptions.new
|
10
12
|
config.action_view.embed_authenticity_token_in_remote_forms = nil
|
11
13
|
config.action_view.debug_missing_translation = true
|
14
|
+
config.action_view.default_enforce_utf8 = nil
|
15
|
+
config.action_view.finalize_compiled_template_methods = NULL_OPTION
|
12
16
|
|
13
17
|
config.eager_load_namespaces << ActionView
|
14
18
|
|
@@ -35,6 +39,25 @@ module ActionView
|
|
35
39
|
end
|
36
40
|
end
|
37
41
|
|
42
|
+
initializer "action_view.default_enforce_utf8" do |app|
|
43
|
+
ActiveSupport.on_load(:action_view) do
|
44
|
+
default_enforce_utf8 = app.config.action_view.delete(:default_enforce_utf8)
|
45
|
+
unless default_enforce_utf8.nil?
|
46
|
+
ActionView::Helpers::FormTagHelper.default_enforce_utf8 = default_enforce_utf8
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
initializer "action_view.finalize_compiled_template_methods" do |app|
|
52
|
+
ActiveSupport.on_load(:action_view) do
|
53
|
+
option = app.config.action_view.delete(:finalize_compiled_template_methods)
|
54
|
+
|
55
|
+
if option != NULL_OPTION
|
56
|
+
ActiveSupport::Deprecation.warn "action_view.finalize_compiled_template_methods is deprecated and has no effect"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
38
61
|
initializer "action_view.logger" do
|
39
62
|
ActiveSupport.on_load(:action_view) { self.logger ||= Rails.logger }
|
40
63
|
end
|
@@ -58,7 +81,7 @@ module ActionView
|
|
58
81
|
initializer "action_view.per_request_digest_cache" do |app|
|
59
82
|
ActiveSupport.on_load(:action_view) do
|
60
83
|
unless ActionView::Resolver.caching?
|
61
|
-
app.executor.to_run ActionView::
|
84
|
+
app.executor.to_run ActionView::CacheExpiry::Executor.new(watcher: app.config.file_watcher)
|
62
85
|
end
|
63
86
|
end
|
64
87
|
end
|
@@ -17,7 +17,7 @@ module ActionView
|
|
17
17
|
# that new object is called in turn. This abstracts the setup and rendering
|
18
18
|
# into a separate classes for partials and templates.
|
19
19
|
class AbstractRenderer #:nodoc:
|
20
|
-
delegate :
|
20
|
+
delegate :template_exists?, :any_templates?, :formats, to: :@lookup_context
|
21
21
|
|
22
22
|
def initialize(lookup_context)
|
23
23
|
@lookup_context = lookup_context
|
@@ -27,6 +27,53 @@ module ActionView
|
|
27
27
|
raise NotImplementedError
|
28
28
|
end
|
29
29
|
|
30
|
+
class RenderedCollection # :nodoc:
|
31
|
+
def self.empty(format)
|
32
|
+
EmptyCollection.new format
|
33
|
+
end
|
34
|
+
|
35
|
+
attr_reader :rendered_templates
|
36
|
+
|
37
|
+
def initialize(rendered_templates, spacer)
|
38
|
+
@rendered_templates = rendered_templates
|
39
|
+
@spacer = spacer
|
40
|
+
end
|
41
|
+
|
42
|
+
def body
|
43
|
+
@rendered_templates.map(&:body).join(@spacer.body).html_safe
|
44
|
+
end
|
45
|
+
|
46
|
+
def format
|
47
|
+
rendered_templates.first.format
|
48
|
+
end
|
49
|
+
|
50
|
+
class EmptyCollection
|
51
|
+
attr_reader :format
|
52
|
+
|
53
|
+
def initialize(format)
|
54
|
+
@format = format
|
55
|
+
end
|
56
|
+
|
57
|
+
def body; nil; end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class RenderedTemplate # :nodoc:
|
62
|
+
attr_reader :body, :layout, :template
|
63
|
+
|
64
|
+
def initialize(body, layout, template)
|
65
|
+
@body = body
|
66
|
+
@layout = layout
|
67
|
+
@template = template
|
68
|
+
end
|
69
|
+
|
70
|
+
def format
|
71
|
+
template.format
|
72
|
+
end
|
73
|
+
|
74
|
+
EMPTY_SPACER = Struct.new(:body).new
|
75
|
+
end
|
76
|
+
|
30
77
|
private
|
31
78
|
|
32
79
|
def extract_details(options) # :doc:
|
@@ -38,8 +85,6 @@ module ActionView
|
|
38
85
|
end
|
39
86
|
|
40
87
|
def instrument(name, **options) # :doc:
|
41
|
-
options[:identifier] ||= (@template && @template.identifier) || @path
|
42
|
-
|
43
88
|
ActiveSupport::Notifications.instrument("render_#{name}.action_view", options) do |payload|
|
44
89
|
yield payload
|
45
90
|
end
|
@@ -51,5 +96,13 @@ module ActionView
|
|
51
96
|
|
52
97
|
@lookup_context.formats = formats | @lookup_context.formats
|
53
98
|
end
|
99
|
+
|
100
|
+
def build_rendered_template(content, template, layout = nil)
|
101
|
+
RenderedTemplate.new content, layout, template
|
102
|
+
end
|
103
|
+
|
104
|
+
def build_rendered_collection(templates, spacer)
|
105
|
+
RenderedCollection.new templates, spacer
|
106
|
+
end
|
54
107
|
end
|
55
108
|
end
|