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
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionView
2
- module Helpers
4
+ module Helpers #:nodoc:
3
5
  module Tags #:nodoc:
4
6
  extend ActiveSupport::Autoload
5
7
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionView
2
4
  module Helpers
3
5
  module Tags # :nodoc:
@@ -32,8 +34,7 @@ module ActionView
32
34
  end
33
35
 
34
36
  private
35
-
36
- def value(object)
37
+ def value
37
38
  if @allow_method_names_outside_object
38
39
  object.public_send @method_name if object && object.respond_to?(@method_name)
39
40
  else
@@ -41,19 +42,19 @@ module ActionView
41
42
  end
42
43
  end
43
44
 
44
- def value_before_type_cast(object)
45
+ def value_before_type_cast
45
46
  unless object.nil?
46
47
  method_before_type_cast = @method_name + "_before_type_cast"
47
48
 
48
- if value_came_from_user?(object) && object.respond_to?(method_before_type_cast)
49
+ if value_came_from_user? && object.respond_to?(method_before_type_cast)
49
50
  object.public_send(method_before_type_cast)
50
51
  else
51
- value(object)
52
+ value
52
53
  end
53
54
  end
54
55
  end
55
56
 
56
- def value_came_from_user?(object)
57
+ def value_came_from_user?
57
58
  method_name = "#{@method_name}_came_from_user?"
58
59
  !object.respond_to?(method_name) || object.public_send(method_name)
59
60
  end
@@ -95,7 +96,7 @@ module ActionView
95
96
  index = name_and_id_index(options)
96
97
  options["name"] = options.fetch("name") { tag_name(options["multiple"], index) }
97
98
 
98
- unless skip_default_ids?
99
+ if generate_ids?
99
100
  options["id"] = options.fetch("id") { tag_id(index) }
100
101
  if namespace = options.delete("namespace")
101
102
  options["id"] = options["id"] ? "#{namespace}_#{options['id']}" : namespace
@@ -104,19 +105,19 @@ module ActionView
104
105
  end
105
106
 
106
107
  def tag_name(multiple = false, index = nil)
107
- # a little duplication to construct less strings
108
+ # a little duplication to construct fewer strings
108
109
  case
109
110
  when @object_name.empty?
110
- "#{sanitized_method_name}#{"[]" if multiple}"
111
+ "#{sanitized_method_name}#{multiple ? "[]" : ""}"
111
112
  when index
112
- "#{@object_name}[#{index}][#{sanitized_method_name}]#{"[]" if multiple}"
113
+ "#{@object_name}[#{index}][#{sanitized_method_name}]#{multiple ? "[]" : ""}"
113
114
  else
114
- "#{@object_name}[#{sanitized_method_name}]#{"[]" if multiple}"
115
+ "#{@object_name}[#{sanitized_method_name}]#{multiple ? "[]" : ""}"
115
116
  end
116
117
  end
117
118
 
118
119
  def tag_id(index = nil)
119
- # a little duplication to construct less strings
120
+ # a little duplication to construct fewer strings
120
121
  case
121
122
  when @object_name.empty?
122
123
  sanitized_method_name.dup
@@ -128,15 +129,15 @@ module ActionView
128
129
  end
129
130
 
130
131
  def sanitized_object_name
131
- @sanitized_object_name ||= @object_name.gsub(/\]\[|[^-a-zA-Z0-9:.]/, "_").sub(/_$/, "")
132
+ @sanitized_object_name ||= @object_name.gsub(/\]\[|[^-a-zA-Z0-9:.]/, "_").delete_suffix("_")
132
133
  end
133
134
 
134
135
  def sanitized_method_name
135
- @sanitized_method_name ||= @method_name.sub(/\?$/, "")
136
+ @sanitized_method_name ||= @method_name.delete_suffix("?")
136
137
  end
137
138
 
138
139
  def sanitized_value(value)
139
- value.to_s.gsub(/\s/, "_").gsub(/[^-[[:word:]]]/, "").mb_chars.downcase.to_s
140
+ value.to_s.gsub(/[\s\.]/, "_").gsub(/[^-[[:word:]]]/, "").downcase
140
141
  end
141
142
 
142
143
  def select_content_tag(option_tags, options, html_options)
@@ -148,8 +149,8 @@ module ActionView
148
149
  options[:include_blank] ||= true unless options[:prompt]
149
150
  end
150
151
 
151
- value = options.fetch(:selected) { value(object) }
152
- select = content_tag("select", add_options(option_tags, options, value), html_options.except!("skip_default_ids", "allow_method_names_outside_object"))
152
+ value = options.fetch(:selected) { value() }
153
+ select = content_tag("select", add_options(option_tags, options, value), html_options)
153
154
 
154
155
  if html_options["multiple"] && options.fetch(:include_hidden, true)
155
156
  tag("input", disabled: html_options["disabled"], name: html_options["name"], type: "hidden", value: "") + select
@@ -165,11 +166,19 @@ module ActionView
165
166
 
166
167
  def add_options(option_tags, options, value = nil)
167
168
  if options[:include_blank]
168
- option_tags = tag_builder.content_tag_string("option", options[:include_blank].kind_of?(String) ? options[:include_blank] : nil, value: "") + "\n" + option_tags
169
+ content = (options[:include_blank] if options[:include_blank].is_a?(String))
170
+ label = (" " unless content)
171
+ option_tags = tag_builder.content_tag_string("option", content, value: "", label: label) + "\n" + option_tags
169
172
  end
173
+
170
174
  if value.blank? && options[:prompt]
171
- option_tags = tag_builder.content_tag_string("option", prompt_text(options[:prompt]), value: "") + "\n" + option_tags
175
+ tag_options = { value: "" }.tap do |prompt_opts|
176
+ prompt_opts[:disabled] = true if options[:disabled] == ""
177
+ prompt_opts[:selected] = true if options[:selected] == ""
178
+ end
179
+ option_tags = tag_builder.content_tag_string("option", prompt_text(options[:prompt]), tag_options) + "\n" + option_tags
172
180
  end
181
+
173
182
  option_tags
174
183
  end
175
184
 
@@ -181,8 +190,8 @@ module ActionView
181
190
  end
182
191
  end
183
192
 
184
- def skip_default_ids?
185
- @skip_default_ids
193
+ def generate_ids?
194
+ !@skip_default_ids
186
195
  end
187
196
  end
188
197
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "action_view/helpers/tags/checkable"
2
4
 
3
5
  module ActionView
@@ -16,7 +18,7 @@ module ActionView
16
18
  options = @options.stringify_keys
17
19
  options["type"] = "checkbox"
18
20
  options["value"] = @checked_value
19
- options["checked"] = "checked" if input_checked?(object, options)
21
+ options["checked"] = "checked" if input_checked?(options)
20
22
 
21
23
  if options["multiple"]
22
24
  add_default_name_and_id_for_value(@checked_value, options)
@@ -37,7 +39,6 @@ module ActionView
37
39
  end
38
40
 
39
41
  private
40
-
41
42
  def checked?(value)
42
43
  case value
43
44
  when TrueClass, FalseClass
@@ -1,13 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionView
2
4
  module Helpers
3
5
  module Tags # :nodoc:
4
6
  module Checkable # :nodoc:
5
- def input_checked?(object, options)
7
+ def input_checked?(options)
6
8
  if options.has_key?("checked")
7
9
  checked = options.delete "checked"
8
10
  checked == true || checked == "checked"
9
11
  else
10
- checked?(value(object))
12
+ checked?(value)
11
13
  end
12
14
  end
13
15
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "action_view/helpers/tags/collection_helpers"
2
4
 
3
5
  module ActionView
@@ -20,7 +22,6 @@ module ActionView
20
22
  end
21
23
 
22
24
  private
23
-
24
25
  def render_component(builder)
25
26
  builder.check_box + builder.label
26
27
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionView
2
4
  module Helpers
3
5
  module Tags # :nodoc:
@@ -35,7 +37,6 @@ module ActionView
35
37
  end
36
38
 
37
39
  private
38
-
39
40
  def instantiate_builder(builder_class, item, value, text, html_options)
40
41
  builder_class.new(@template_object, @object_name, @method_name, item,
41
42
  sanitize_attribute_name(value), text, value, html_options)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "action_view/helpers/tags/collection_helpers"
2
4
 
3
5
  module ActionView
@@ -19,7 +21,6 @@ module ActionView
19
21
  end
20
22
 
21
23
  private
22
-
23
24
  def render_component(builder)
24
25
  builder.radio_button + builder.label
25
26
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionView
2
4
  module Helpers
3
5
  module Tags # :nodoc:
@@ -13,7 +15,7 @@ module ActionView
13
15
 
14
16
  def render
15
17
  option_tags_options = {
16
- selected: @options.fetch(:selected) { value(@object) },
18
+ selected: @options.fetch(:selected) { value },
17
19
  disabled: @options[:disabled]
18
20
  }
19
21
 
@@ -1,19 +1,20 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionView
2
4
  module Helpers
3
5
  module Tags # :nodoc:
4
6
  class ColorField < TextField # :nodoc:
5
7
  def render
6
8
  options = @options.stringify_keys
7
- options["value"] ||= validate_color_string(value(object))
9
+ options["value"] ||= validate_color_string(value)
8
10
  @options = options
9
11
  super
10
12
  end
11
13
 
12
14
  private
13
-
14
15
  def validate_color_string(string)
15
16
  regex = /#[0-9a-fA-F]{6}/
16
- if regex.match(string)
17
+ if regex.match?(string)
17
18
  string.downcase
18
19
  else
19
20
  "#000000"
@@ -1,11 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionView
2
4
  module Helpers
3
5
  module Tags # :nodoc:
4
6
  class DateField < DatetimeField # :nodoc:
5
7
  private
6
-
7
8
  def format_date(value)
8
- value.try(:strftime, "%Y-%m-%d")
9
+ value&.strftime("%Y-%m-%d")
9
10
  end
10
11
  end
11
12
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/time/calculations"
2
4
 
3
5
  module ActionView
@@ -11,7 +13,7 @@ module ActionView
11
13
  end
12
14
 
13
15
  def render
14
- error_wrapping(datetime_selector(@options, @html_options).send("select_#{select_type}").html_safe)
16
+ error_wrapping(datetime_selector(@options, @html_options).public_send("select_#{select_type}").html_safe)
15
17
  end
16
18
 
17
19
  class << self
@@ -21,13 +23,12 @@ module ActionView
21
23
  end
22
24
 
23
25
  private
24
-
25
26
  def select_type
26
27
  self.class.select_type
27
28
  end
28
29
 
29
30
  def datetime_selector(options, html_options)
30
- datetime = options.fetch(:selected) { value(object) || default_datetime(options) }
31
+ datetime = options.fetch(:selected) { value || default_datetime(options) }
31
32
  @auto_index ||= nil
32
33
 
33
34
  options = options.dup
@@ -57,7 +58,7 @@ module ActionView
57
58
  time = Time.current
58
59
 
59
60
  [:year, :month, :day, :hour, :min, :sec].each do |key|
60
- default[key] ||= time.send(key)
61
+ default[key] ||= time.public_send(key)
61
62
  end
62
63
 
63
64
  Time.utc(
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionView
2
4
  module Helpers
3
5
  module Tags # :nodoc:
4
6
  class DatetimeField < TextField # :nodoc:
5
7
  def render
6
8
  options = @options.stringify_keys
7
- options["value"] ||= format_date(value(object))
9
+ options["value"] ||= format_date(value)
8
10
  options["min"] = format_date(datetime_value(options["min"]))
9
11
  options["max"] = format_date(datetime_value(options["max"]))
10
12
  @options = options
@@ -12,7 +14,6 @@ module ActionView
12
14
  end
13
15
 
14
16
  private
15
-
16
17
  def format_date(value)
17
18
  raise NotImplementedError
18
19
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionView
2
4
  module Helpers
3
5
  module Tags # :nodoc:
@@ -9,9 +11,8 @@ module ActionView
9
11
  end
10
12
 
11
13
  private
12
-
13
14
  def format_date(value)
14
- value.try(:strftime, "%Y-%m-%dT%T")
15
+ value&.strftime("%Y-%m-%dT%T")
15
16
  end
16
17
  end
17
18
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionView
2
4
  module Helpers
3
5
  module Tags # :nodoc:
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionView
2
4
  module Helpers
3
5
  module Tags # :nodoc:
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionView
2
4
  module Helpers
3
5
  module Tags # :nodoc:
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionView
2
4
  module Helpers
3
5
  module Tags # :nodoc:
@@ -15,7 +17,7 @@ module ActionView
15
17
 
16
18
  def render
17
19
  option_tags_options = {
18
- selected: @options.fetch(:selected) { value(@object) },
20
+ selected: @options.fetch(:selected) { value },
19
21
  disabled: @options[:disabled]
20
22
  }
21
23
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionView
2
4
  module Helpers
3
5
  module Tags # :nodoc:
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionView
2
4
  module Helpers
3
5
  module Tags # :nodoc:
@@ -23,6 +25,10 @@ module ActionView
23
25
 
24
26
  content
25
27
  end
28
+
29
+ def to_s
30
+ translation
31
+ end
26
32
  end
27
33
 
28
34
  def initialize(object_name, method_name, template_object, content_or_options = nil, options = nil)
@@ -69,14 +75,9 @@ module ActionView
69
75
  end
70
76
 
71
77
  private
72
-
73
78
  def render_component(builder)
74
79
  builder.translation
75
80
  end
76
-
77
- def skip_default_ids?
78
- false # The id is used as the `for` attribute.
79
- end
80
81
  end
81
82
  end
82
83
  end
@@ -1,11 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionView
2
4
  module Helpers
3
5
  module Tags # :nodoc:
4
6
  class MonthField < DatetimeField # :nodoc:
5
7
  private
6
-
7
8
  def format_date(value)
8
- value.try(:strftime, "%Y-%m")
9
+ value&.strftime("%Y-%m")
9
10
  end
10
11
  end
11
12
  end