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.

Files changed (118) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +199 -168
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +7 -5
  5. data/lib/action_view.rb +10 -4
  6. data/lib/action_view/base.rb +87 -23
  7. data/lib/action_view/buffers.rb +17 -0
  8. data/lib/action_view/cache_expiry.rb +52 -0
  9. data/lib/action_view/context.rb +7 -11
  10. data/lib/action_view/dependency_tracker.rb +12 -4
  11. data/lib/action_view/digestor.rb +24 -23
  12. data/lib/action_view/flows.rb +2 -1
  13. data/lib/action_view/gem_version.rb +4 -2
  14. data/lib/action_view/helpers.rb +4 -2
  15. data/lib/action_view/helpers/active_model_helper.rb +9 -4
  16. data/lib/action_view/helpers/asset_tag_helper.rb +220 -57
  17. data/lib/action_view/helpers/asset_url_helper.rb +28 -23
  18. data/lib/action_view/helpers/atom_feed_helper.rb +5 -2
  19. data/lib/action_view/helpers/cache_helper.rb +39 -28
  20. data/lib/action_view/helpers/capture_helper.rb +13 -7
  21. data/lib/action_view/helpers/controller_helper.rb +3 -1
  22. data/lib/action_view/helpers/csp_helper.rb +26 -0
  23. data/lib/action_view/helpers/csrf_helper.rb +5 -3
  24. data/lib/action_view/helpers/date_helper.rb +78 -33
  25. data/lib/action_view/helpers/debug_helper.rb +4 -2
  26. data/lib/action_view/helpers/form_helper.rb +357 -106
  27. data/lib/action_view/helpers/form_options_helper.rb +45 -39
  28. data/lib/action_view/helpers/form_tag_helper.rb +42 -27
  29. data/lib/action_view/helpers/javascript_helper.rb +28 -12
  30. data/lib/action_view/helpers/number_helper.rb +16 -8
  31. data/lib/action_view/helpers/output_safety_helper.rb +3 -1
  32. data/lib/action_view/helpers/rendering_helper.rb +20 -9
  33. data/lib/action_view/helpers/sanitize_helper.rb +15 -19
  34. data/lib/action_view/helpers/tag_helper.rb +100 -24
  35. data/lib/action_view/helpers/tags.rb +3 -1
  36. data/lib/action_view/helpers/tags/base.rb +30 -21
  37. data/lib/action_view/helpers/tags/check_box.rb +3 -2
  38. data/lib/action_view/helpers/tags/checkable.rb +4 -2
  39. data/lib/action_view/helpers/tags/collection_check_boxes.rb +2 -1
  40. data/lib/action_view/helpers/tags/collection_helpers.rb +2 -1
  41. data/lib/action_view/helpers/tags/collection_radio_buttons.rb +2 -1
  42. data/lib/action_view/helpers/tags/collection_select.rb +3 -1
  43. data/lib/action_view/helpers/tags/color_field.rb +4 -3
  44. data/lib/action_view/helpers/tags/date_field.rb +3 -2
  45. data/lib/action_view/helpers/tags/date_select.rb +5 -4
  46. data/lib/action_view/helpers/tags/datetime_field.rb +3 -2
  47. data/lib/action_view/helpers/tags/datetime_local_field.rb +3 -2
  48. data/lib/action_view/helpers/tags/datetime_select.rb +2 -0
  49. data/lib/action_view/helpers/tags/email_field.rb +2 -0
  50. data/lib/action_view/helpers/tags/file_field.rb +2 -0
  51. data/lib/action_view/helpers/tags/grouped_collection_select.rb +3 -1
  52. data/lib/action_view/helpers/tags/hidden_field.rb +2 -0
  53. data/lib/action_view/helpers/tags/label.rb +6 -5
  54. data/lib/action_view/helpers/tags/month_field.rb +3 -2
  55. data/lib/action_view/helpers/tags/number_field.rb +2 -0
  56. data/lib/action_view/helpers/tags/password_field.rb +2 -0
  57. data/lib/action_view/helpers/tags/placeholderable.rb +2 -0
  58. data/lib/action_view/helpers/tags/radio_button.rb +3 -2
  59. data/lib/action_view/helpers/tags/range_field.rb +2 -0
  60. data/lib/action_view/helpers/tags/search_field.rb +2 -0
  61. data/lib/action_view/helpers/tags/select.rb +4 -3
  62. data/lib/action_view/helpers/tags/tel_field.rb +2 -0
  63. data/lib/action_view/helpers/tags/text_area.rb +3 -1
  64. data/lib/action_view/helpers/tags/text_field.rb +3 -2
  65. data/lib/action_view/helpers/tags/time_field.rb +3 -2
  66. data/lib/action_view/helpers/tags/time_select.rb +2 -0
  67. data/lib/action_view/helpers/tags/time_zone_select.rb +3 -1
  68. data/lib/action_view/helpers/tags/translator.rb +3 -6
  69. data/lib/action_view/helpers/tags/url_field.rb +2 -0
  70. data/lib/action_view/helpers/tags/week_field.rb +3 -2
  71. data/lib/action_view/helpers/text_helper.rb +11 -10
  72. data/lib/action_view/helpers/translation_helper.rb +102 -52
  73. data/lib/action_view/helpers/url_helper.rb +150 -32
  74. data/lib/action_view/layouts.rb +15 -15
  75. data/lib/action_view/log_subscriber.rb +32 -15
  76. data/lib/action_view/lookup_context.rb +67 -39
  77. data/lib/action_view/model_naming.rb +2 -0
  78. data/lib/action_view/path_set.rb +5 -12
  79. data/lib/action_view/railtie.rb +46 -21
  80. data/lib/action_view/record_identifier.rb +4 -3
  81. data/lib/action_view/renderer/abstract_renderer.rb +144 -11
  82. data/lib/action_view/renderer/collection_renderer.rb +196 -0
  83. data/lib/action_view/renderer/object_renderer.rb +34 -0
  84. data/lib/action_view/renderer/partial_renderer.rb +33 -283
  85. data/lib/action_view/renderer/partial_renderer/collection_caching.rb +64 -17
  86. data/lib/action_view/renderer/renderer.rb +61 -4
  87. data/lib/action_view/renderer/streaming_template_renderer.rb +14 -8
  88. data/lib/action_view/renderer/template_renderer.rb +36 -26
  89. data/lib/action_view/rendering.rb +57 -38
  90. data/lib/action_view/routing_url_for.rb +15 -12
  91. data/lib/action_view/tasks/cache_digests.rake +2 -0
  92. data/lib/action_view/template.rb +69 -76
  93. data/lib/action_view/template/error.rb +32 -18
  94. data/lib/action_view/template/handlers.rb +4 -2
  95. data/lib/action_view/template/handlers/builder.rb +5 -6
  96. data/lib/action_view/template/handlers/erb.rb +20 -19
  97. data/lib/action_view/template/handlers/erb/erubi.rb +17 -9
  98. data/lib/action_view/template/handlers/html.rb +3 -1
  99. data/lib/action_view/template/handlers/raw.rb +4 -2
  100. data/lib/action_view/template/html.rb +8 -7
  101. data/lib/action_view/template/inline.rb +22 -0
  102. data/lib/action_view/template/raw_file.rb +25 -0
  103. data/lib/action_view/template/renderable.rb +24 -0
  104. data/lib/action_view/template/resolver.rb +194 -152
  105. data/lib/action_view/template/sources.rb +13 -0
  106. data/lib/action_view/template/sources/file.rb +17 -0
  107. data/lib/action_view/template/text.rb +5 -4
  108. data/lib/action_view/template/types.rb +3 -1
  109. data/lib/action_view/test_case.rb +38 -30
  110. data/lib/action_view/testing/resolvers.rb +20 -27
  111. data/lib/action_view/unbound_template.rb +31 -0
  112. data/lib/action_view/version.rb +2 -0
  113. data/lib/action_view/view_paths.rb +61 -40
  114. data/lib/assets/compiled/rails-ujs.js +84 -23
  115. metadata +34 -23
  116. data/lib/action_view/helpers/record_tag_helper.rb +0 -21
  117. data/lib/action_view/template/handlers/erb/deprecated_erubis.rb +0 -9
  118. data/lib/action_view/template/handlers/erb/erubis.rb +0 -81
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2004-2017 David Heinemeier Hansson
1
+ Copyright (c) 2004-2020 David Heinemeier Hansson
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
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
- * http://www.opensource.org/licenses/MIT
25
+ * https://opensource.org/licenses/MIT
24
26
 
25
27
 
26
28
  == Support
27
29
 
28
30
  API documentation is at
29
31
 
30
- * http://api.rubyonrails.org
32
+ * https://api.rubyonrails.org
31
33
 
32
- Bug reports can be filed for the Ruby on Rails project here:
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://groups.google.com/forum/?fromgroups#!forum/rubyonrails-core
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-2017 David Heinemeier Hansson
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 << "#{File.dirname(__FILE__)}/action_view/locale/en.yml"
101
+ I18n.load_path << File.expand_path("action_view/locale/en.yml", __dir__)
96
102
  end
@@ -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 setup in regular embedding tags <tt><% %></tt>, and the name is written using the output embedding tag <tt><%= %></tt>. Note that this
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
- cattr_accessor :prefix_partial_path_with_controller_namespace
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
- @@automatically_disable_submit_tag = true
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
- attr_accessor :view_renderer
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
- def initialize(context = nil, assigns = {}, controller = nil, formats = nil) #:nodoc:
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
- if context.is_a?(ActionView::Renderer)
201
- @view_renderer = context
202
- else
203
- lookup_context = context.is_a?(ActionView::LookupContext) ?
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
@@ -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
@@ -1,23 +1,20 @@
1
- module ActionView
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 ActionController, a Context must just include this module.
12
- # The initialization of the variables used by the context (@output_buffer, @view_flow,
13
- # and @virtual_path) is responsibility of the object that includes this module
14
- # (although you can call _prepare_context defined below).
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
- add_dynamic_dependency(render_dependencies, Regexp.last_match[:dynamic])
132
- add_static_dependency(render_dependencies, Regexp.last_match[:static])
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[-1] == "*" }
173
+ wildcards, explicits = dependencies.partition { |dependency| dependency.end_with?("*") }
166
174
 
167
175
  (explicits + resolve_directories(wildcards)).uniq
168
176
  end
@@ -1,26 +1,24 @@
1
- require "concurrent/map"
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> - Template name
19
- # * <tt>finder</tt> - An instance of <tt>ActionView::LookupContext</tt>
20
- # * <tt>dependencies</tt> - An array of dependent views
21
- def digest(name:, finder:, dependencies: [])
22
- dependencies ||= []
23
- cache_key = [ name, finder.rendered_format, dependencies ].flatten.compact.join(".")
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
- options = {}
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 name.include?("#") # Dynamic template partial names can never be tracked
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::MD5.hexdigest("#{template.source}-#{dependency_digest(finder, stack)}")
91
+ ActiveSupport::Digest.hexdigest("#{template.source}-#{dependency_digest(finder, stack)}")
91
92
  end
92
93
 
93
94
  def dependency_digest(finder, stack)