actionview 5.2.4.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 (92) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +221 -93
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +5 -3
  5. data/lib/action_view.rb +7 -2
  6. data/lib/action_view/base.rb +81 -15
  7. data/lib/action_view/buffers.rb +15 -0
  8. data/lib/action_view/cache_expiry.rb +52 -0
  9. data/lib/action_view/context.rb +5 -9
  10. data/lib/action_view/dependency_tracker.rb +10 -4
  11. data/lib/action_view/digestor.rb +15 -22
  12. data/lib/action_view/flows.rb +0 -1
  13. data/lib/action_view/gem_version.rb +4 -4
  14. data/lib/action_view/helpers.rb +0 -2
  15. data/lib/action_view/helpers/active_model_helper.rb +0 -1
  16. data/lib/action_view/helpers/asset_tag_helper.rb +63 -46
  17. data/lib/action_view/helpers/asset_url_helper.rb +9 -6
  18. data/lib/action_view/helpers/atom_feed_helper.rb +2 -1
  19. data/lib/action_view/helpers/cache_helper.rb +23 -22
  20. data/lib/action_view/helpers/capture_helper.rb +4 -0
  21. data/lib/action_view/helpers/csp_helper.rb +4 -2
  22. data/lib/action_view/helpers/csrf_helper.rb +1 -1
  23. data/lib/action_view/helpers/date_helper.rb +73 -30
  24. data/lib/action_view/helpers/form_helper.rb +305 -37
  25. data/lib/action_view/helpers/form_options_helper.rb +23 -23
  26. data/lib/action_view/helpers/form_tag_helper.rb +19 -16
  27. data/lib/action_view/helpers/javascript_helper.rb +12 -11
  28. data/lib/action_view/helpers/number_helper.rb +14 -8
  29. data/lib/action_view/helpers/output_safety_helper.rb +1 -1
  30. data/lib/action_view/helpers/rendering_helper.rb +17 -7
  31. data/lib/action_view/helpers/sanitize_helper.rb +12 -18
  32. data/lib/action_view/helpers/tag_helper.rb +98 -22
  33. data/lib/action_view/helpers/tags/base.rb +18 -11
  34. data/lib/action_view/helpers/tags/check_box.rb +0 -1
  35. data/lib/action_view/helpers/tags/collection_check_boxes.rb +0 -1
  36. data/lib/action_view/helpers/tags/collection_helpers.rb +0 -1
  37. data/lib/action_view/helpers/tags/collection_radio_buttons.rb +0 -1
  38. data/lib/action_view/helpers/tags/color_field.rb +1 -2
  39. data/lib/action_view/helpers/tags/date_field.rb +1 -2
  40. data/lib/action_view/helpers/tags/date_select.rb +2 -3
  41. data/lib/action_view/helpers/tags/datetime_field.rb +0 -1
  42. data/lib/action_view/helpers/tags/datetime_local_field.rb +1 -2
  43. data/lib/action_view/helpers/tags/label.rb +4 -1
  44. data/lib/action_view/helpers/tags/month_field.rb +1 -2
  45. data/lib/action_view/helpers/tags/radio_button.rb +0 -1
  46. data/lib/action_view/helpers/tags/select.rb +1 -2
  47. data/lib/action_view/helpers/tags/text_field.rb +0 -1
  48. data/lib/action_view/helpers/tags/time_field.rb +1 -2
  49. data/lib/action_view/helpers/tags/translator.rb +1 -6
  50. data/lib/action_view/helpers/tags/week_field.rb +1 -2
  51. data/lib/action_view/helpers/text_helper.rb +3 -4
  52. data/lib/action_view/helpers/translation_helper.rb +93 -55
  53. data/lib/action_view/helpers/url_helper.rb +121 -27
  54. data/lib/action_view/layouts.rb +8 -10
  55. data/lib/action_view/log_subscriber.rb +30 -15
  56. data/lib/action_view/lookup_context.rb +63 -35
  57. data/lib/action_view/path_set.rb +3 -12
  58. data/lib/action_view/railtie.rb +42 -26
  59. data/lib/action_view/record_identifier.rb +2 -3
  60. data/lib/action_view/renderer/abstract_renderer.rb +142 -11
  61. data/lib/action_view/renderer/collection_renderer.rb +196 -0
  62. data/lib/action_view/renderer/object_renderer.rb +34 -0
  63. data/lib/action_view/renderer/partial_renderer.rb +21 -273
  64. data/lib/action_view/renderer/partial_renderer/collection_caching.rb +61 -16
  65. data/lib/action_view/renderer/renderer.rb +59 -4
  66. data/lib/action_view/renderer/streaming_template_renderer.rb +10 -8
  67. data/lib/action_view/renderer/template_renderer.rb +35 -27
  68. data/lib/action_view/rendering.rb +54 -33
  69. data/lib/action_view/routing_url_for.rb +13 -12
  70. data/lib/action_view/template.rb +66 -75
  71. data/lib/action_view/template/error.rb +30 -15
  72. data/lib/action_view/template/handlers.rb +1 -1
  73. data/lib/action_view/template/handlers/builder.rb +2 -2
  74. data/lib/action_view/template/handlers/erb.rb +16 -11
  75. data/lib/action_view/template/handlers/erb/erubi.rb +15 -9
  76. data/lib/action_view/template/handlers/html.rb +1 -1
  77. data/lib/action_view/template/handlers/raw.rb +2 -2
  78. data/lib/action_view/template/html.rb +5 -6
  79. data/lib/action_view/template/inline.rb +22 -0
  80. data/lib/action_view/template/raw_file.rb +25 -0
  81. data/lib/action_view/template/renderable.rb +24 -0
  82. data/lib/action_view/template/resolver.rb +191 -150
  83. data/lib/action_view/template/sources.rb +13 -0
  84. data/lib/action_view/template/sources/file.rb +17 -0
  85. data/lib/action_view/template/text.rb +2 -3
  86. data/lib/action_view/test_case.rb +21 -29
  87. data/lib/action_view/testing/resolvers.rb +18 -27
  88. data/lib/action_view/unbound_template.rb +31 -0
  89. data/lib/action_view/view_paths.rb +59 -38
  90. data/lib/assets/compiled/rails-ujs.js +29 -3
  91. metadata +32 -21
  92. data/lib/action_view/helpers/record_tag_helper.rb +0 -23
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionView
4
+ class Template
5
+ module Sources
6
+ extend ActiveSupport::Autoload
7
+
8
+ eager_autoload do
9
+ autoload :File
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionView
4
+ class Template
5
+ module Sources
6
+ class File
7
+ def initialize(filename)
8
+ @filename = filename
9
+ end
10
+
11
+ def to_s
12
+ ::File.binread @filename
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -8,7 +8,6 @@ module ActionView #:nodoc:
8
8
 
9
9
  def initialize(string)
10
10
  @string = string.to_s
11
- @type = Types[:text]
12
11
  end
13
12
 
14
13
  def identifier
@@ -25,8 +24,8 @@ module ActionView #:nodoc:
25
24
  to_str
26
25
  end
27
26
 
28
- def formats
29
- [@type.ref]
27
+ def format
28
+ :text
30
29
  end
31
30
  end
32
31
  end
@@ -16,11 +16,12 @@ module ActionView
16
16
  attr_accessor :request, :response, :params
17
17
 
18
18
  class << self
19
- attr_writer :controller_path
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 = (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
- _helpers.module_eval <<-end_eval, __FILE__, __LINE__ + 1
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(%(#{method}), *args, &block) # _test_case.send(%(current_user), *args, &block)
79
+ _test_case.send(:'#{method}', *args, &block) # _test_case.send(:'current_user', *args, &block)
79
80
  end # end
81
+ ruby2_keywords(:'#{method}') if respond_to?(:ruby2_keywords, true)
80
82
  end_eval
81
83
  end
82
84
  end
@@ -93,7 +95,6 @@ module ActionView
93
95
  end
94
96
 
95
97
  private
96
-
97
98
  def include_helper_modules!
98
99
  helper(helper_class) if helper_class
99
100
  include _helpers
@@ -101,16 +102,17 @@ module ActionView
101
102
  end
102
103
 
103
104
  def setup_with_controller
104
- @controller = ActionView::TestCase::TestController.new
105
+ controller_class = Class.new(ActionView::TestCase::TestController)
106
+ @controller = controller_class.new
105
107
  @request = @controller.request
106
108
  @view_flow = ActionView::OutputFlow.new
107
109
  # empty string ensures buffer has UTF-8 encoding as
108
110
  # new without arguments returns ASCII-8BIT encoded buffer like String#new
109
111
  @output_buffer = ActiveSupport::SafeBuffer.new ""
110
- @rendered = "".dup
112
+ @rendered = +""
111
113
 
112
- make_test_case_available_to_view!
113
- say_no_to_protect_against_forgery!
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
- def say_no_to_protect_against_forgery!
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
- def make_test_case_available_to_view!
182
- test_case_instance = self
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 < PathResolver
11
- attr_reader :hash
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
- def query(path, exts, _, _)
25
- query = "".dup
26
- EXTENSIONS.each_key do |ext|
27
- query << "(" << exts[ext].map { |e| e && Regexp.escape(".#{e}") }.join("|") << "|)"
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
- templates.sort_by { |t| -t.identifier.match(/^#{query}$/).captures.reject(&:blank?).size }
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
- class_attribute :_view_paths, default: ActionView::PathSet.new.freeze
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
- private
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
@@ -320,6 +320,9 @@ Released under the MIT license
320
320
  if (!input.name || input.disabled) {
321
321
  return;
322
322
  }
323
+ if (matches(input, 'fieldset[disabled] *')) {
324
+ return;
325
+ }
323
326
  if (matches(input, 'select')) {
324
327
  return toArray(input.options).forEach(function(option) {
325
328
  if (option.selected) {
@@ -370,6 +373,10 @@ Released under the MIT license
370
373
  }
371
374
  };
372
375
 
376
+ Rails.confirm = function(message, element) {
377
+ return confirm(message);
378
+ };
379
+
373
380
  allowAction = function(element) {
374
381
  var answer, callback, message;
375
382
  message = element.getAttribute('data-confirm');
@@ -379,7 +386,7 @@ Released under the MIT license
379
386
  answer = false;
380
387
  if (fire(element, 'confirm')) {
381
388
  try {
382
- answer = confirm(message);
389
+ answer = Rails.confirm(message, element);
383
390
  } catch (error) {}
384
391
  callback = fire(element, 'confirm:complete', [answer]);
385
392
  }
@@ -388,7 +395,7 @@ Released under the MIT license
388
395
 
389
396
  }).call(this);
390
397
  (function() {
391
- var disableFormElement, disableFormElements, disableLinkElement, enableFormElement, enableFormElements, enableLinkElement, formElements, getData, matches, setData, stopEverything;
398
+ var disableFormElement, disableFormElements, disableLinkElement, enableFormElement, enableFormElements, enableLinkElement, formElements, getData, isXhrRedirect, matches, setData, stopEverything;
392
399
 
393
400
  matches = Rails.matches, getData = Rails.getData, setData = Rails.setData, stopEverything = Rails.stopEverything, formElements = Rails.formElements;
394
401
 
@@ -402,7 +409,14 @@ Released under the MIT license
402
409
 
403
410
  Rails.enableElement = function(e) {
404
411
  var element;
405
- element = e instanceof Event ? e.target : e;
412
+ if (e instanceof Event) {
413
+ if (isXhrRedirect(e)) {
414
+ return;
415
+ }
416
+ element = e.target;
417
+ } else {
418
+ element = e;
419
+ }
406
420
  if (matches(element, Rails.linkDisableSelector)) {
407
421
  return enableLinkElement(element);
408
422
  } else if (matches(element, Rails.buttonDisableSelector) || matches(element, Rails.formEnableSelector)) {
@@ -426,6 +440,9 @@ Released under the MIT license
426
440
 
427
441
  disableLinkElement = function(element) {
428
442
  var replacement;
443
+ if (getData(element, 'ujs:disabled')) {
444
+ return;
445
+ }
429
446
  replacement = element.getAttribute('data-disable-with');
430
447
  if (replacement != null) {
431
448
  setData(element, 'ujs:enable-with', element.innerHTML);
@@ -452,6 +469,9 @@ Released under the MIT license
452
469
 
453
470
  disableFormElement = function(element) {
454
471
  var replacement;
472
+ if (getData(element, 'ujs:disabled')) {
473
+ return;
474
+ }
455
475
  replacement = element.getAttribute('data-disable-with');
456
476
  if (replacement != null) {
457
477
  if (matches(element, 'button')) {
@@ -485,6 +505,12 @@ Released under the MIT license
485
505
  return setData(element, 'ujs:disabled', null);
486
506
  };
487
507
 
508
+ isXhrRedirect = function(event) {
509
+ var ref, xhr;
510
+ xhr = (ref = event.detail) != null ? ref[0] : void 0;
511
+ return (xhr != null ? xhr.getResponseHeader("X-Xhr-Redirect") : void 0) != null;
512
+ };
513
+
488
514
  }).call(this);
489
515
  (function() {
490
516
  var stopEverything;