actionview 5.1.4 → 6.1.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 +5 -5
- data/CHANGELOG.md +199 -168
- data/MIT-LICENSE +1 -1
- data/README.rdoc +7 -5
- data/lib/action_view.rb +10 -4
- data/lib/action_view/base.rb +87 -23
- data/lib/action_view/buffers.rb +17 -0
- data/lib/action_view/cache_expiry.rb +52 -0
- data/lib/action_view/context.rb +7 -11
- data/lib/action_view/dependency_tracker.rb +12 -4
- data/lib/action_view/digestor.rb +24 -23
- data/lib/action_view/flows.rb +2 -1
- data/lib/action_view/gem_version.rb +4 -2
- data/lib/action_view/helpers.rb +4 -2
- data/lib/action_view/helpers/active_model_helper.rb +9 -4
- data/lib/action_view/helpers/asset_tag_helper.rb +220 -57
- data/lib/action_view/helpers/asset_url_helper.rb +28 -23
- data/lib/action_view/helpers/atom_feed_helper.rb +5 -2
- data/lib/action_view/helpers/cache_helper.rb +39 -28
- data/lib/action_view/helpers/capture_helper.rb +13 -7
- data/lib/action_view/helpers/controller_helper.rb +3 -1
- data/lib/action_view/helpers/csp_helper.rb +26 -0
- data/lib/action_view/helpers/csrf_helper.rb +5 -3
- data/lib/action_view/helpers/date_helper.rb +78 -33
- data/lib/action_view/helpers/debug_helper.rb +4 -2
- data/lib/action_view/helpers/form_helper.rb +357 -106
- data/lib/action_view/helpers/form_options_helper.rb +45 -39
- data/lib/action_view/helpers/form_tag_helper.rb +42 -27
- data/lib/action_view/helpers/javascript_helper.rb +28 -12
- data/lib/action_view/helpers/number_helper.rb +16 -8
- data/lib/action_view/helpers/output_safety_helper.rb +3 -1
- data/lib/action_view/helpers/rendering_helper.rb +20 -9
- data/lib/action_view/helpers/sanitize_helper.rb +15 -19
- data/lib/action_view/helpers/tag_helper.rb +100 -24
- data/lib/action_view/helpers/tags.rb +3 -1
- data/lib/action_view/helpers/tags/base.rb +30 -21
- data/lib/action_view/helpers/tags/check_box.rb +3 -2
- data/lib/action_view/helpers/tags/checkable.rb +4 -2
- data/lib/action_view/helpers/tags/collection_check_boxes.rb +2 -1
- data/lib/action_view/helpers/tags/collection_helpers.rb +2 -1
- data/lib/action_view/helpers/tags/collection_radio_buttons.rb +2 -1
- data/lib/action_view/helpers/tags/collection_select.rb +3 -1
- data/lib/action_view/helpers/tags/color_field.rb +4 -3
- data/lib/action_view/helpers/tags/date_field.rb +3 -2
- data/lib/action_view/helpers/tags/date_select.rb +5 -4
- data/lib/action_view/helpers/tags/datetime_field.rb +3 -2
- data/lib/action_view/helpers/tags/datetime_local_field.rb +3 -2
- 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 +3 -1
- data/lib/action_view/helpers/tags/hidden_field.rb +2 -0
- data/lib/action_view/helpers/tags/label.rb +6 -5
- data/lib/action_view/helpers/tags/month_field.rb +3 -2
- data/lib/action_view/helpers/tags/number_field.rb +2 -0
- data/lib/action_view/helpers/tags/password_field.rb +2 -0
- data/lib/action_view/helpers/tags/placeholderable.rb +2 -0
- data/lib/action_view/helpers/tags/radio_button.rb +3 -2
- data/lib/action_view/helpers/tags/range_field.rb +2 -0
- data/lib/action_view/helpers/tags/search_field.rb +2 -0
- data/lib/action_view/helpers/tags/select.rb +4 -3
- data/lib/action_view/helpers/tags/tel_field.rb +2 -0
- data/lib/action_view/helpers/tags/text_area.rb +3 -1
- data/lib/action_view/helpers/tags/text_field.rb +3 -2
- data/lib/action_view/helpers/tags/time_field.rb +3 -2
- 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 +3 -6
- data/lib/action_view/helpers/tags/url_field.rb +2 -0
- data/lib/action_view/helpers/tags/week_field.rb +3 -2
- data/lib/action_view/helpers/text_helper.rb +11 -10
- data/lib/action_view/helpers/translation_helper.rb +102 -52
- data/lib/action_view/helpers/url_helper.rb +150 -32
- data/lib/action_view/layouts.rb +15 -15
- data/lib/action_view/log_subscriber.rb +32 -15
- data/lib/action_view/lookup_context.rb +67 -39
- data/lib/action_view/model_naming.rb +2 -0
- data/lib/action_view/path_set.rb +5 -12
- data/lib/action_view/railtie.rb +46 -21
- data/lib/action_view/record_identifier.rb +4 -3
- data/lib/action_view/renderer/abstract_renderer.rb +144 -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.rb +33 -283
- data/lib/action_view/renderer/partial_renderer/collection_caching.rb +64 -17
- data/lib/action_view/renderer/renderer.rb +61 -4
- data/lib/action_view/renderer/streaming_template_renderer.rb +14 -8
- data/lib/action_view/renderer/template_renderer.rb +36 -26
- data/lib/action_view/rendering.rb +57 -38
- data/lib/action_view/routing_url_for.rb +15 -12
- data/lib/action_view/tasks/cache_digests.rake +2 -0
- data/lib/action_view/template.rb +69 -76
- data/lib/action_view/template/error.rb +32 -18
- data/lib/action_view/template/handlers.rb +4 -2
- data/lib/action_view/template/handlers/builder.rb +5 -6
- data/lib/action_view/template/handlers/erb.rb +20 -19
- data/lib/action_view/template/handlers/erb/erubi.rb +17 -9
- data/lib/action_view/template/handlers/html.rb +3 -1
- data/lib/action_view/template/handlers/raw.rb +4 -2
- data/lib/action_view/template/html.rb +8 -7
- 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 +194 -152
- 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 -4
- data/lib/action_view/template/types.rb +3 -1
- data/lib/action_view/test_case.rb +38 -30
- data/lib/action_view/testing/resolvers.rb +20 -27
- data/lib/action_view/unbound_template.rb +31 -0
- data/lib/action_view/version.rb +2 -0
- data/lib/action_view/view_paths.rb +61 -40
- data/lib/assets/compiled/rails-ujs.js +84 -23
- metadata +34 -23
- data/lib/action_view/helpers/record_tag_helper.rb +0 -21
- data/lib/action_view/template/handlers/erb/deprecated_erubis.rb +0 -9
- data/lib/action_view/template/handlers/erb/erubis.rb +0 -81
data/MIT-LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -5,13 +5,15 @@ view helpers that assist when building HTML forms, Atom feeds and more.
|
|
5
5
|
Template formats that Action View handles are ERB (embedded Ruby, typically
|
6
6
|
used to inline short Ruby snippets inside HTML), and XML Builder.
|
7
7
|
|
8
|
+
You can read more about Action View in the {Action View Overview}[https://edgeguides.rubyonrails.org/action_view_overview.html] guide.
|
9
|
+
|
8
10
|
== Download and installation
|
9
11
|
|
10
12
|
The latest version of Action View can be installed with RubyGems:
|
11
13
|
|
12
14
|
$ gem install actionview
|
13
15
|
|
14
|
-
Source code can be downloaded as part of the Rails project on GitHub
|
16
|
+
Source code can be downloaded as part of the Rails project on GitHub:
|
15
17
|
|
16
18
|
* https://github.com/rails/rails/tree/master/actionview
|
17
19
|
|
@@ -20,19 +22,19 @@ Source code can be downloaded as part of the Rails project on GitHub
|
|
20
22
|
|
21
23
|
Action View is released under the MIT license:
|
22
24
|
|
23
|
-
*
|
25
|
+
* https://opensource.org/licenses/MIT
|
24
26
|
|
25
27
|
|
26
28
|
== Support
|
27
29
|
|
28
30
|
API documentation is at
|
29
31
|
|
30
|
-
*
|
32
|
+
* https://api.rubyonrails.org
|
31
33
|
|
32
|
-
Bug reports
|
34
|
+
Bug reports for the Ruby on Rails project can be filed here:
|
33
35
|
|
34
36
|
* https://github.com/rails/rails/issues
|
35
37
|
|
36
38
|
Feature requests should be discussed on the rails-core mailing list here:
|
37
39
|
|
38
|
-
* https://
|
40
|
+
* https://discuss.rubyonrails.org/c/rubyonrails-core
|
data/lib/action_view.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
#--
|
2
|
-
# Copyright (c) 2004-
|
4
|
+
# Copyright (c) 2004-2020 David Heinemeier Hansson
|
3
5
|
#
|
4
6
|
# Permission is hereby granted, free of charge, to any person obtaining
|
5
7
|
# a copy of this software and associated documentation files (the
|
@@ -33,7 +35,6 @@ module ActionView
|
|
33
35
|
eager_autoload do
|
34
36
|
autoload :Base
|
35
37
|
autoload :Context
|
36
|
-
autoload :CompiledTemplates, "action_view/context"
|
37
38
|
autoload :Digestor
|
38
39
|
autoload :Helpers
|
39
40
|
autoload :LookupContext
|
@@ -43,12 +44,15 @@ module ActionView
|
|
43
44
|
autoload :Rendering
|
44
45
|
autoload :RoutingUrlFor
|
45
46
|
autoload :Template
|
47
|
+
autoload :UnboundTemplate
|
46
48
|
autoload :ViewPaths
|
47
49
|
|
48
50
|
autoload_under "renderer" do
|
49
51
|
autoload :Renderer
|
50
52
|
autoload :AbstractRenderer
|
51
53
|
autoload :PartialRenderer
|
54
|
+
autoload :CollectionRenderer
|
55
|
+
autoload :ObjectRenderer
|
52
56
|
autoload :TemplateRenderer
|
53
57
|
autoload :StreamingTemplateRenderer
|
54
58
|
end
|
@@ -56,6 +60,7 @@ module ActionView
|
|
56
60
|
autoload_at "action_view/template/resolver" do
|
57
61
|
autoload :Resolver
|
58
62
|
autoload :PathResolver
|
63
|
+
autoload :FileSystemResolver
|
59
64
|
autoload :OptimizedFileSystemResolver
|
60
65
|
autoload :FallbackFileSystemResolver
|
61
66
|
end
|
@@ -74,12 +79,13 @@ module ActionView
|
|
74
79
|
autoload :MissingTemplate
|
75
80
|
autoload :ActionViewError
|
76
81
|
autoload :EncodingError
|
77
|
-
autoload :MissingRequestError
|
78
82
|
autoload :TemplateError
|
83
|
+
autoload :SyntaxErrorInTemplate
|
79
84
|
autoload :WrongEncodingError
|
80
85
|
end
|
81
86
|
end
|
82
87
|
|
88
|
+
autoload :CacheExpiry
|
83
89
|
autoload :TestCase
|
84
90
|
|
85
91
|
def self.eager_load!
|
@@ -92,5 +98,5 @@ end
|
|
92
98
|
require "active_support/core_ext/string/output_safety"
|
93
99
|
|
94
100
|
ActiveSupport.on_load(:i18n) do
|
95
|
-
I18n.load_path <<
|
101
|
+
I18n.load_path << File.expand_path("action_view/locale/en.yml", __dir__)
|
96
102
|
end
|
data/lib/action_view/base.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/core_ext/module/attr_internal"
|
2
4
|
require "active_support/core_ext/module/attribute_accessors"
|
3
5
|
require "active_support/ordered_options"
|
@@ -25,7 +27,7 @@ module ActionView #:nodoc:
|
|
25
27
|
# Name: <%= person.name %><br/>
|
26
28
|
# <% end %>
|
27
29
|
#
|
28
|
-
# The loop is
|
30
|
+
# The loop is set up in regular embedding tags <tt><% %></tt>, and the name is written using the output embedding tag <tt><%= %></tt>. Note that this
|
29
31
|
# is not just a usage suggestion. Regular output functions like print or puts won't work with ERB templates. So this would be wrong:
|
30
32
|
#
|
31
33
|
# <%# WRONG %>
|
@@ -140,30 +142,28 @@ module ActionView #:nodoc:
|
|
140
142
|
include Helpers, ::ERB::Util, Context
|
141
143
|
|
142
144
|
# Specify the proc used to decorate input tags that refer to attributes with errors.
|
143
|
-
cattr_accessor :field_error_proc
|
144
|
-
@@field_error_proc = Proc.new { |html_tag, instance| "<div class=\"field_with_errors\">#{html_tag}</div>".html_safe }
|
145
|
+
cattr_accessor :field_error_proc, default: Proc.new { |html_tag, instance| "<div class=\"field_with_errors\">#{html_tag}</div>".html_safe }
|
145
146
|
|
146
147
|
# How to complete the streaming when an exception occurs.
|
147
148
|
# This is our best guess: first try to close the attribute, then the tag.
|
148
|
-
cattr_accessor :streaming_completion_on_exception
|
149
|
-
@@streaming_completion_on_exception = %("><script>window.location = "/500.html"</script></html>)
|
149
|
+
cattr_accessor :streaming_completion_on_exception, default: %("><script>window.location = "/500.html"</script></html>)
|
150
150
|
|
151
151
|
# Specify whether rendering within namespaced controllers should prefix
|
152
152
|
# the partial paths for ActiveModel objects with the namespace.
|
153
153
|
# (e.g., an Admin::PostsController would render @post using /admin/posts/_post.erb)
|
154
|
-
|
155
|
-
@@prefix_partial_path_with_controller_namespace = true
|
154
|
+
class_attribute :prefix_partial_path_with_controller_namespace, default: true
|
156
155
|
|
157
156
|
# Specify default_formats that can be rendered.
|
158
157
|
cattr_accessor :default_formats
|
159
158
|
|
160
159
|
# Specify whether an error should be raised for missing translations
|
161
|
-
cattr_accessor :raise_on_missing_translations
|
162
|
-
@@raise_on_missing_translations = false
|
160
|
+
cattr_accessor :raise_on_missing_translations, default: false
|
163
161
|
|
164
162
|
# Specify whether submit_tag should automatically disable on click
|
165
|
-
cattr_accessor :automatically_disable_submit_tag
|
166
|
-
|
163
|
+
cattr_accessor :automatically_disable_submit_tag, default: true
|
164
|
+
|
165
|
+
# Annotate rendered view with file names
|
166
|
+
cattr_accessor :annotate_rendered_view_with_filenames, default: false
|
167
167
|
|
168
168
|
class_attribute :_routes
|
169
169
|
class_attribute :logger
|
@@ -182,36 +182,100 @@ module ActionView #:nodoc:
|
|
182
182
|
def xss_safe? #:nodoc:
|
183
183
|
true
|
184
184
|
end
|
185
|
+
|
186
|
+
def with_empty_template_cache # :nodoc:
|
187
|
+
subclass = Class.new(self) {
|
188
|
+
# We can't implement these as self.class because subclasses will
|
189
|
+
# share the same template cache as superclasses, so "changed?" won't work
|
190
|
+
# correctly.
|
191
|
+
define_method(:compiled_method_container) { subclass }
|
192
|
+
define_singleton_method(:compiled_method_container) { subclass }
|
193
|
+
|
194
|
+
def inspect
|
195
|
+
"#<ActionView::Base:#{'%#016x' % (object_id << 1)}>"
|
196
|
+
end
|
197
|
+
}
|
198
|
+
end
|
199
|
+
|
200
|
+
def changed?(other) # :nodoc:
|
201
|
+
compiled_method_container != other.compiled_method_container
|
202
|
+
end
|
185
203
|
end
|
186
204
|
|
187
|
-
|
205
|
+
attr_reader :view_renderer, :lookup_context
|
188
206
|
attr_internal :config, :assigns
|
189
207
|
|
190
|
-
delegate :lookup_context, to: :view_renderer
|
191
208
|
delegate :formats, :formats=, :locale, :locale=, :view_paths, :view_paths=, to: :lookup_context
|
192
209
|
|
193
210
|
def assign(new_assigns) # :nodoc:
|
194
211
|
@_assigns = new_assigns.each { |key, value| instance_variable_set("@#{key}", value) }
|
195
212
|
end
|
196
213
|
|
197
|
-
|
214
|
+
# :stopdoc:
|
215
|
+
|
216
|
+
def self.empty
|
217
|
+
with_view_paths([])
|
218
|
+
end
|
219
|
+
|
220
|
+
def self.with_view_paths(view_paths, assigns = {}, controller = nil)
|
221
|
+
with_context ActionView::LookupContext.new(view_paths), assigns, controller
|
222
|
+
end
|
223
|
+
|
224
|
+
def self.with_context(context, assigns = {}, controller = nil)
|
225
|
+
new context, assigns, controller
|
226
|
+
end
|
227
|
+
|
228
|
+
# :startdoc:
|
229
|
+
|
230
|
+
def initialize(lookup_context, assigns, controller) #:nodoc:
|
198
231
|
@_config = ActiveSupport::InheritableOptions.new
|
199
232
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
context : ActionView::LookupContext.new(context)
|
205
|
-
lookup_context.formats = formats if formats
|
206
|
-
lookup_context.prefixes = controller._prefixes if controller
|
207
|
-
@view_renderer = ActionView::Renderer.new(lookup_context)
|
208
|
-
end
|
233
|
+
@lookup_context = lookup_context
|
234
|
+
|
235
|
+
@view_renderer = ActionView::Renderer.new @lookup_context
|
236
|
+
@current_template = nil
|
209
237
|
|
210
238
|
assign(assigns)
|
211
239
|
assign_controller(controller)
|
212
240
|
_prepare_context
|
213
241
|
end
|
214
242
|
|
243
|
+
def _run(method, template, locals, buffer, add_to_stack: true, &block)
|
244
|
+
_old_output_buffer, _old_virtual_path, _old_template = @output_buffer, @virtual_path, @current_template
|
245
|
+
@current_template = template if add_to_stack
|
246
|
+
@output_buffer = buffer
|
247
|
+
public_send(method, locals, buffer, &block)
|
248
|
+
ensure
|
249
|
+
@output_buffer, @virtual_path, @current_template = _old_output_buffer, _old_virtual_path, _old_template
|
250
|
+
end
|
251
|
+
|
252
|
+
def compiled_method_container
|
253
|
+
raise NotImplementedError, <<~msg.squish
|
254
|
+
Subclasses of ActionView::Base must implement `compiled_method_container`
|
255
|
+
or use the class method `with_empty_template_cache` for constructing
|
256
|
+
an ActionView::Base subclass that has an empty cache.
|
257
|
+
msg
|
258
|
+
end
|
259
|
+
|
260
|
+
def in_rendering_context(options)
|
261
|
+
old_view_renderer = @view_renderer
|
262
|
+
old_lookup_context = @lookup_context
|
263
|
+
|
264
|
+
if !lookup_context.html_fallback_for_js && options[:formats]
|
265
|
+
formats = Array(options[:formats])
|
266
|
+
if formats == [:js]
|
267
|
+
formats << :html
|
268
|
+
end
|
269
|
+
@lookup_context = lookup_context.with_prepended_formats(formats)
|
270
|
+
@view_renderer = ActionView::Renderer.new @lookup_context
|
271
|
+
end
|
272
|
+
|
273
|
+
yield @view_renderer
|
274
|
+
ensure
|
275
|
+
@view_renderer = old_view_renderer
|
276
|
+
@lookup_context = old_lookup_context
|
277
|
+
end
|
278
|
+
|
215
279
|
ActiveSupport.run_load_hooks(:action_view, self)
|
216
280
|
end
|
217
281
|
end
|
data/lib/action_view/buffers.rb
CHANGED
@@ -1,6 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/core_ext/string/output_safety"
|
2
4
|
|
3
5
|
module ActionView
|
6
|
+
# Used as a buffer for views
|
7
|
+
#
|
8
|
+
# The main difference between this and ActiveSupport::SafeBuffer
|
9
|
+
# is for the methods `<<` and `safe_expr_append=` the inputs are
|
10
|
+
# checked for nil before they are assigned and `to_s` is called on
|
11
|
+
# the input. For example:
|
12
|
+
#
|
13
|
+
# obuf = ActionView::OutputBuffer.new "hello"
|
14
|
+
# obuf << 5
|
15
|
+
# puts obuf # => "hello5"
|
16
|
+
#
|
17
|
+
# sbuf = ActiveSupport::SafeBuffer.new "hello"
|
18
|
+
# sbuf << 5
|
19
|
+
# puts sbuf # => "hello\u0005"
|
20
|
+
#
|
4
21
|
class OutputBuffer < ActiveSupport::SafeBuffer #:nodoc:
|
5
22
|
def initialize(*)
|
6
23
|
super
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionView
|
4
|
+
class CacheExpiry
|
5
|
+
class Executor
|
6
|
+
def initialize(watcher:)
|
7
|
+
@cache_expiry = CacheExpiry.new(watcher: watcher)
|
8
|
+
end
|
9
|
+
|
10
|
+
def before(target)
|
11
|
+
@cache_expiry.clear_cache_if_necessary
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(watcher:)
|
16
|
+
@watched_dirs = nil
|
17
|
+
@watcher_class = watcher
|
18
|
+
@watcher = nil
|
19
|
+
@mutex = Mutex.new
|
20
|
+
end
|
21
|
+
|
22
|
+
def clear_cache_if_necessary
|
23
|
+
@mutex.synchronize do
|
24
|
+
watched_dirs = dirs_to_watch
|
25
|
+
return if watched_dirs.empty?
|
26
|
+
|
27
|
+
if watched_dirs != @watched_dirs
|
28
|
+
@watched_dirs = watched_dirs
|
29
|
+
@watcher = @watcher_class.new([], watched_dirs) do
|
30
|
+
clear_cache
|
31
|
+
end
|
32
|
+
@watcher.execute
|
33
|
+
else
|
34
|
+
@watcher.execute_if_updated
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def clear_cache
|
40
|
+
ActionView::LookupContext::DetailsKey.clear
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
def dirs_to_watch
|
45
|
+
all_view_paths.grep(FileSystemResolver).map!(&:path).tap(&:uniq!).sort!
|
46
|
+
end
|
47
|
+
|
48
|
+
def all_view_paths
|
49
|
+
ActionView::ViewPaths.all_view_paths.flat_map(&:paths)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/action_view/context.rb
CHANGED
@@ -1,23 +1,20 @@
|
|
1
|
-
|
2
|
-
module CompiledTemplates #:nodoc:
|
3
|
-
# holds compiled template code
|
4
|
-
end
|
1
|
+
# frozen_string_literal: true
|
5
2
|
|
3
|
+
module ActionView
|
6
4
|
# = Action View Context
|
7
5
|
#
|
8
6
|
# Action View contexts are supplied to Action Controller to render a template.
|
9
7
|
# The default Action View context is ActionView::Base.
|
10
8
|
#
|
11
|
-
# In order to work with
|
12
|
-
# The initialization of the variables used by the context
|
13
|
-
# and @virtual_path) is responsibility of the
|
14
|
-
# (although you can call _prepare_context
|
9
|
+
# In order to work with Action Controller, a Context must just include this
|
10
|
+
# module. The initialization of the variables used by the context
|
11
|
+
# (@output_buffer, @view_flow, and @virtual_path) is responsibility of the
|
12
|
+
# object that includes this module (although you can call _prepare_context
|
13
|
+
# defined below).
|
15
14
|
module Context
|
16
|
-
include CompiledTemplates
|
17
15
|
attr_accessor :output_buffer, :view_flow
|
18
16
|
|
19
17
|
# Prepares the context by setting the appropriate instance variables.
|
20
|
-
# :api: plugin
|
21
18
|
def _prepare_context
|
22
19
|
@view_flow = OutputFlow.new
|
23
20
|
@output_buffer = nil
|
@@ -27,7 +24,6 @@ module ActionView
|
|
27
24
|
# Encapsulates the interaction with the view flow so it
|
28
25
|
# returns the correct buffer on +yield+. This is usually
|
29
26
|
# overwritten by helpers to add more behavior.
|
30
|
-
# :api: plugin
|
31
27
|
def _layout_for(name = nil)
|
32
28
|
name ||= :layout
|
33
29
|
view_flow.get(name).html_safe
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "concurrent/map"
|
2
4
|
require "action_view/path_set"
|
3
5
|
|
@@ -128,8 +130,9 @@ module ActionView
|
|
128
130
|
|
129
131
|
def add_dependencies(render_dependencies, arguments, pattern)
|
130
132
|
arguments.scan(pattern) do
|
131
|
-
|
132
|
-
|
133
|
+
match = Regexp.last_match
|
134
|
+
add_dynamic_dependency(render_dependencies, match[:dynamic])
|
135
|
+
add_static_dependency(render_dependencies, match[:static], match[:quote])
|
133
136
|
end
|
134
137
|
end
|
135
138
|
|
@@ -139,7 +142,12 @@ module ActionView
|
|
139
142
|
end
|
140
143
|
end
|
141
144
|
|
142
|
-
def add_static_dependency(dependencies, dependency)
|
145
|
+
def add_static_dependency(dependencies, dependency, quote_type)
|
146
|
+
if quote_type == '"'
|
147
|
+
# Ignore if there is interpolation
|
148
|
+
return if dependency.include?('#{')
|
149
|
+
end
|
150
|
+
|
143
151
|
if dependency
|
144
152
|
if dependency.include?("/")
|
145
153
|
dependencies << dependency
|
@@ -162,7 +170,7 @@ module ActionView
|
|
162
170
|
def explicit_dependencies
|
163
171
|
dependencies = source.scan(EXPLICIT_DEPENDENCY).flatten.uniq
|
164
172
|
|
165
|
-
wildcards, explicits = dependencies.partition { |dependency| dependency
|
173
|
+
wildcards, explicits = dependencies.partition { |dependency| dependency.end_with?("*") }
|
166
174
|
|
167
175
|
(explicits + resolve_directories(wildcards)).uniq
|
168
176
|
end
|
data/lib/action_view/digestor.rb
CHANGED
@@ -1,26 +1,24 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require "action_view/dependency_tracker"
|
3
|
-
require "monitor"
|
4
4
|
|
5
5
|
module ActionView
|
6
6
|
class Digestor
|
7
7
|
@@digest_mutex = Mutex.new
|
8
8
|
|
9
|
-
module PerExecutionDigestCacheExpiry
|
10
|
-
def self.before(target)
|
11
|
-
ActionView::LookupContext::DetailsKey.clear
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
9
|
class << self
|
16
10
|
# Supported options:
|
17
11
|
#
|
18
|
-
# * <tt>name</tt>
|
19
|
-
# * <tt>
|
20
|
-
# * <tt>
|
21
|
-
|
22
|
-
|
23
|
-
|
12
|
+
# * <tt>name</tt> - Template name
|
13
|
+
# * <tt>format</tt> - Template format
|
14
|
+
# * <tt>finder</tt> - An instance of <tt>ActionView::LookupContext</tt>
|
15
|
+
# * <tt>dependencies</tt> - An array of dependent views
|
16
|
+
def digest(name:, format: nil, finder:, dependencies: nil)
|
17
|
+
if dependencies.nil? || dependencies.empty?
|
18
|
+
cache_key = "#{name}.#{format}"
|
19
|
+
else
|
20
|
+
cache_key = [ name, format, dependencies ].flatten.compact.join(".")
|
21
|
+
end
|
24
22
|
|
25
23
|
# this is a correctly done double-checked locking idiom
|
26
24
|
# (Concurrent::Map's lookups have volatile semantics)
|
@@ -30,7 +28,7 @@ module ActionView
|
|
30
28
|
root = tree(name, finder, partial)
|
31
29
|
dependencies.each do |injected_dep|
|
32
30
|
root.children << Injected.new(injected_dep, nil, nil)
|
33
|
-
end
|
31
|
+
end if dependencies
|
34
32
|
finder.digest_cache[cache_key] = root.digest(finder)
|
35
33
|
end
|
36
34
|
end
|
@@ -43,13 +41,9 @@ module ActionView
|
|
43
41
|
# Create a dependency tree for template named +name+.
|
44
42
|
def tree(name, finder, partial = false, seen = {})
|
45
43
|
logical_name = name.gsub(%r|/_|, "/")
|
44
|
+
interpolated = name.include?("#")
|
46
45
|
|
47
|
-
|
48
|
-
options[:formats] = [finder.rendered_format] if finder.rendered_format
|
49
|
-
|
50
|
-
if template = finder.disable_cache { finder.find_all(logical_name, [], partial, [], options).first }
|
51
|
-
finder.rendered_format ||= template.formats.first
|
52
|
-
|
46
|
+
if !interpolated && (template = find_template(finder, logical_name, [], partial, []))
|
53
47
|
if node = seen[template.identifier] # handle cycles in the tree
|
54
48
|
node
|
55
49
|
else
|
@@ -62,13 +56,20 @@ module ActionView
|
|
62
56
|
node
|
63
57
|
end
|
64
58
|
else
|
65
|
-
unless
|
59
|
+
unless interpolated # Dynamic template partial names can never be tracked
|
66
60
|
logger.error " Couldn't find template for digesting: #{name}"
|
67
61
|
end
|
68
62
|
|
69
63
|
seen[name] ||= Missing.new(name, logical_name, nil)
|
70
64
|
end
|
71
65
|
end
|
66
|
+
|
67
|
+
private
|
68
|
+
def find_template(finder, name, prefixes, partial, keys)
|
69
|
+
finder.disable_cache do
|
70
|
+
finder.find_all(name, prefixes, partial, keys).first
|
71
|
+
end
|
72
|
+
end
|
72
73
|
end
|
73
74
|
|
74
75
|
class Node
|
@@ -87,7 +88,7 @@ module ActionView
|
|
87
88
|
end
|
88
89
|
|
89
90
|
def digest(finder, stack = [])
|
90
|
-
Digest
|
91
|
+
ActiveSupport::Digest.hexdigest("#{template.source}-#{dependency_digest(finder, stack)}")
|
91
92
|
end
|
92
93
|
|
93
94
|
def dependency_digest(finder, stack)
|