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,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "cgi"
2
4
  require "erb"
3
5
  require "action_view/helpers/form_helper"
@@ -7,19 +9,19 @@ require "active_support/core_ext/array/wrap"
7
9
 
8
10
  module ActionView
9
11
  # = Action View Form Option Helpers
10
- module Helpers
12
+ module Helpers #:nodoc:
11
13
  # Provides a number of methods for turning different kinds of containers into a set of option tags.
12
14
  #
13
15
  # The <tt>collection_select</tt>, <tt>select</tt> and <tt>time_zone_select</tt> methods take an <tt>options</tt> parameter, a hash:
14
16
  #
15
17
  # * <tt>:include_blank</tt> - set to true or a prompt string if the first option element of the select element is a blank. Useful if there is not a default value required for the select element.
16
18
  #
17
- # select("post", "category", Post::CATEGORIES, {include_blank: true})
19
+ # select("post", "category", Post::CATEGORIES, { include_blank: true })
18
20
  #
19
21
  # could become:
20
22
  #
21
23
  # <select name="post[category]" id="post_category">
22
- # <option value=""></option>
24
+ # <option value="" label=" "></option>
23
25
  # <option value="joke">joke</option>
24
26
  # <option value="poem">poem</option>
25
27
  # </select>
@@ -28,7 +30,7 @@ module ActionView
28
30
  #
29
31
  # Example with <tt>@post.person_id => 2</tt>:
30
32
  #
31
- # select("post", "person_id", Person.all.collect {|p| [ p.name, p.id ] }, {include_blank: 'None'})
33
+ # select("post", "person_id", Person.all.collect { |p| [ p.name, p.id ] }, { include_blank: 'None' })
32
34
  #
33
35
  # could become:
34
36
  #
@@ -41,7 +43,7 @@ module ActionView
41
43
  #
42
44
  # * <tt>:prompt</tt> - set to true or a prompt string. When the select element doesn't have a value yet, this prepends an option with a generic prompt -- "Please select" -- or the given prompt string.
43
45
  #
44
- # select("post", "person_id", Person.all.collect {|p| [ p.name, p.id ] }, {prompt: 'Select Person'})
46
+ # select("post", "person_id", Person.all.collect { |p| [ p.name, p.id ] }, { prompt: 'Select Person' })
45
47
  #
46
48
  # could become:
47
49
  #
@@ -67,12 +69,11 @@ module ActionView
67
69
  #
68
70
  # * <tt>:disabled</tt> - can be a single value or an array of values that will be disabled options in the final output.
69
71
  #
70
- # select("post", "category", Post::CATEGORIES, {disabled: 'restricted'})
72
+ # select("post", "category", Post::CATEGORIES, { disabled: 'restricted' })
71
73
  #
72
74
  # could become:
73
75
  #
74
76
  # <select name="post[category]" id="post_category">
75
- # <option value=""></option>
76
77
  # <option value="joke">joke</option>
77
78
  # <option value="poem">poem</option>
78
79
  # <option disabled="disabled" value="restricted">restricted</option>
@@ -80,7 +81,7 @@ module ActionView
80
81
  #
81
82
  # When used with the <tt>collection_select</tt> helper, <tt>:disabled</tt> can also be a Proc that identifies those options that should be disabled.
82
83
  #
83
- # collection_select(:post, :category_id, Category.all, :id, :name, {disabled: -> (category) { category.archived? }})
84
+ # collection_select(:post, :category_id, Category.all, :id, :name, { disabled: -> (category) { category.archived? } })
84
85
  #
85
86
  # If the categories "2008 stuff" and "Christmas" return true when the method <tt>archived?</tt> is called, this would return:
86
87
  # <select name="post[category_id]" id="post_category_id">
@@ -105,12 +106,12 @@ module ActionView
105
106
  #
106
107
  # For example:
107
108
  #
108
- # select("post", "person_id", Person.all.collect {|p| [ p.name, p.id ] }, { include_blank: true })
109
+ # select("post", "person_id", Person.all.collect { |p| [ p.name, p.id ] }, { include_blank: true })
109
110
  #
110
111
  # would become:
111
112
  #
112
113
  # <select name="post[person_id]" id="post_person_id">
113
- # <option value=""></option>
114
+ # <option value="" label=" "></option>
114
115
  # <option value="1" selected="selected">David</option>
115
116
  # <option value="2">Eileen</option>
116
117
  # <option value="3">Rafael</option>
@@ -141,7 +142,7 @@ module ActionView
141
142
  #
142
143
  # The HTML specification says when +multiple+ parameter passed to select and all options got deselected
143
144
  # web browsers do not send any value to server. Unfortunately this introduces a gotcha:
144
- # if an +User+ model has many +roles+ and have +role_ids+ accessor, and in the form that edits roles of the user
145
+ # if a +User+ model has many +roles+ and have +role_ids+ accessor, and in the form that edits roles of the user
145
146
  # the user deselects all roles from +role_ids+ multiple select box, no +role_ids+ parameter is sent. So,
146
147
  # any mass-assignment idiom like
147
148
  #
@@ -212,9 +213,13 @@ module ActionView
212
213
  # * +method+ - The attribute of +object+ corresponding to the select tag
213
214
  # * +collection+ - An array of objects representing the <tt><optgroup></tt> tags.
214
215
  # * +group_method+ - The name of a method which, when called on a member of +collection+, returns an
215
- # array of child objects representing the <tt><option></tt> tags.
216
+ # array of child objects representing the <tt><option></tt> tags. It can also be any object that responds
217
+ # to +call+, such as a +proc+, that will be called for each member of the +collection+ to retrieve the
218
+ # value.
216
219
  # * +group_label_method+ - The name of a method which, when called on a member of +collection+, returns a
217
- # string to be used as the +label+ attribute for its <tt><optgroup></tt> tag.
220
+ # string to be used as the +label+ attribute for its <tt><optgroup></tt> tag. It can also be any object
221
+ # that responds to +call+, such as a +proc+, that will be called for each member of the +collection+ to
222
+ # retrieve the label.
218
223
  # * +option_key_method+ - The name of a method which, when called on a child object of a member of
219
224
  # +collection+, returns a value to be used as the +value+ attribute for its <tt><option></tt> tag.
220
225
  # * +option_value_method+ - The name of a method which, when called on a child object of a member of
@@ -277,17 +282,17 @@ module ActionView
277
282
  # Finally, this method supports a <tt>:default</tt> option, which selects
278
283
  # a default ActiveSupport::TimeZone if the object's time zone is +nil+.
279
284
  #
280
- # time_zone_select( "user", "time_zone", nil, include_blank: true)
285
+ # time_zone_select("user", "time_zone", nil, include_blank: true)
281
286
  #
282
- # time_zone_select( "user", "time_zone", nil, default: "Pacific Time (US & Canada)" )
287
+ # time_zone_select("user", "time_zone", nil, default: "Pacific Time (US & Canada)")
283
288
  #
284
- # time_zone_select( "user", 'time_zone', ActiveSupport::TimeZone.us_zones, default: "Pacific Time (US & Canada)")
289
+ # time_zone_select("user", 'time_zone', ActiveSupport::TimeZone.us_zones, default: "Pacific Time (US & Canada)")
285
290
  #
286
- # time_zone_select( "user", 'time_zone', [ ActiveSupport::TimeZone['Alaska'], ActiveSupport::TimeZone['Hawaii'] ])
291
+ # time_zone_select("user", 'time_zone', [ ActiveSupport::TimeZone['Alaska'], ActiveSupport::TimeZone['Hawaii'] ])
287
292
  #
288
- # time_zone_select( "user", 'time_zone', /Australia/)
293
+ # time_zone_select("user", 'time_zone', /Australia/)
289
294
  #
290
- # time_zone_select( "user", "time_zone", ActiveSupport::TimeZone.all.sort, model: ActiveSupport::TimeZone)
295
+ # time_zone_select("user", "time_zone", ActiveSupport::TimeZone.all.sort, model: ActiveSupport::TimeZone)
291
296
  def time_zone_select(object, method, priority_zones = nil, options = {}, html_options = {})
292
297
  Tags::TimeZoneSelect.new(object, method, self, priority_zones, options, html_options).render
293
298
  end
@@ -317,12 +322,12 @@ module ActionView
317
322
  #
318
323
  # You can optionally provide HTML attributes as the last element of the array.
319
324
  #
320
- # options_for_select([ "Denmark", ["USA", {class: 'bold'}], "Sweden" ], ["USA", "Sweden"])
325
+ # options_for_select([ "Denmark", ["USA", { class: 'bold' }], "Sweden" ], ["USA", "Sweden"])
321
326
  # # => <option value="Denmark">Denmark</option>
322
327
  # # => <option value="USA" class="bold" selected="selected">USA</option>
323
328
  # # => <option value="Sweden" selected="selected">Sweden</option>
324
329
  #
325
- # options_for_select([["Dollar", "$", {class: "bold"}], ["Kroner", "DKK", {onclick: "alert('HI');"}]])
330
+ # options_for_select([["Dollar", "$", { class: "bold" }], ["Kroner", "DKK", { onclick: "alert('HI');" }]])
326
331
  # # => <option value="$" class="bold">Dollar</option>
327
332
  # # => <option value="DKK" onclick="alert('HI');">Kroner</option>
328
333
  #
@@ -455,9 +460,9 @@ module ActionView
455
460
  def option_groups_from_collection_for_select(collection, group_method, group_label_method, option_key_method, option_value_method, selected_key = nil)
456
461
  collection.map do |group|
457
462
  option_tags = options_from_collection_for_select(
458
- group.send(group_method), option_key_method, option_value_method, selected_key)
463
+ value_for_collection(group, group_method), option_key_method, option_value_method, selected_key)
459
464
 
460
- content_tag("optgroup".freeze, option_tags, label: group.send(group_label_method))
465
+ content_tag("optgroup", option_tags, label: value_for_collection(group, group_label_method))
461
466
  end.join.html_safe
462
467
  end
463
468
 
@@ -529,7 +534,7 @@ module ActionView
529
534
  body = "".html_safe
530
535
 
531
536
  if prompt
532
- body.safe_concat content_tag("option".freeze, prompt_text(prompt), value: "")
537
+ body.safe_concat content_tag("option", prompt_text(prompt), value: "")
533
538
  end
534
539
 
535
540
  grouped_options.each do |container|
@@ -542,7 +547,7 @@ module ActionView
542
547
  end
543
548
 
544
549
  html_attributes = { label: label }.merge!(html_attributes)
545
- body.safe_concat content_tag("optgroup".freeze, options_for_select(container, selected_key), html_attributes)
550
+ body.safe_concat content_tag("optgroup", options_for_select(container, selected_key), html_attributes)
546
551
  end
547
552
 
548
553
  body
@@ -560,9 +565,10 @@ module ActionView
560
565
  # an ActiveSupport::TimeZone.
561
566
  #
562
567
  # By default, +model+ is the ActiveSupport::TimeZone constant (which can
563
- # be obtained in Active Record as a value object). The only requirement
564
- # is that the +model+ parameter be an object that responds to +all+, and
565
- # returns an array of objects that represent time zones.
568
+ # be obtained in Active Record as a value object). The +model+ parameter
569
+ # must respond to +all+ and return an array of objects that represent time
570
+ # zones; each object must respond to +name+. If a Regexp is given it will
571
+ # attempt to match the zones using <code>match?</code> method.
566
572
  #
567
573
  # NOTE: Only the option tags are returned, you have to wrap this call in
568
574
  # a regular HTML select tag.
@@ -574,11 +580,11 @@ module ActionView
574
580
 
575
581
  if priority_zones
576
582
  if priority_zones.is_a?(Regexp)
577
- priority_zones = zones.select { |z| z =~ priority_zones }
583
+ priority_zones = zones.select { |z| z.match?(priority_zones) }
578
584
  end
579
585
 
580
586
  zone_options.safe_concat options_for_select(convert_zones[priority_zones], selected)
581
- zone_options.safe_concat content_tag("option".freeze, "-------------", value: "", disabled: true)
587
+ zone_options.safe_concat content_tag("option", "-------------", value: "", disabled: true)
582
588
  zone_options.safe_concat "\n"
583
589
 
584
590
  zones = zones - priority_zones
@@ -648,7 +654,7 @@ module ActionView
648
654
  #
649
655
  # ==== Gotcha
650
656
  #
651
- # The HTML specification says when nothing is select on a collection of radio buttons
657
+ # The HTML specification says when nothing is selected on a collection of radio buttons
652
658
  # web browsers do not send any value to server.
653
659
  # Unfortunately this introduces a gotcha:
654
660
  # if a +User+ model has a +category_id+ field and in the form no category is selected, no +category_id+ parameter is sent. So,
@@ -788,7 +794,7 @@ module ActionView
788
794
  def extract_values_from_collection(collection, value_method, selected)
789
795
  if selected.is_a?(Proc)
790
796
  collection.map do |element|
791
- element.send(value_method) if selected.call(element)
797
+ element.public_send(value_method) if selected.call(element)
792
798
  end.compact
793
799
  else
794
800
  selected
@@ -796,7 +802,7 @@ module ActionView
796
802
  end
797
803
 
798
804
  def value_for_collection(item, value)
799
- value.respond_to?(:call) ? value.call(item) : item.send(value)
805
+ value.respond_to?(:call) ? value.call(item) : item.public_send(value)
800
806
  end
801
807
 
802
808
  def prompt_text(prompt)
@@ -814,7 +820,7 @@ module ActionView
814
820
  #
815
821
  # Please refer to the documentation of the base helper for details.
816
822
  def select(method, choices = nil, options = {}, html_options = {}, &block)
817
- @template.select(@object_name, method, choices, objectify_options(options), @default_options.merge(html_options), &block)
823
+ @template.select(@object_name, method, choices, objectify_options(options), @default_html_options.merge(html_options), &block)
818
824
  end
819
825
 
820
826
  # Wraps ActionView::Helpers::FormOptionsHelper#collection_select for form builders:
@@ -826,7 +832,7 @@ module ActionView
826
832
  #
827
833
  # Please refer to the documentation of the base helper for details.
828
834
  def collection_select(method, collection, value_method, text_method, options = {}, html_options = {})
829
- @template.collection_select(@object_name, method, collection, value_method, text_method, objectify_options(options), @default_options.merge(html_options))
835
+ @template.collection_select(@object_name, method, collection, value_method, text_method, objectify_options(options), @default_html_options.merge(html_options))
830
836
  end
831
837
 
832
838
  # Wraps ActionView::Helpers::FormOptionsHelper#grouped_collection_select for form builders:
@@ -838,7 +844,7 @@ module ActionView
838
844
  #
839
845
  # Please refer to the documentation of the base helper for details.
840
846
  def grouped_collection_select(method, collection, group_method, group_label_method, option_key_method, option_value_method, options = {}, html_options = {})
841
- @template.grouped_collection_select(@object_name, method, collection, group_method, group_label_method, option_key_method, option_value_method, objectify_options(options), @default_options.merge(html_options))
847
+ @template.grouped_collection_select(@object_name, method, collection, group_method, group_label_method, option_key_method, option_value_method, objectify_options(options), @default_html_options.merge(html_options))
842
848
  end
843
849
 
844
850
  # Wraps ActionView::Helpers::FormOptionsHelper#time_zone_select for form builders:
@@ -850,7 +856,7 @@ module ActionView
850
856
  #
851
857
  # Please refer to the documentation of the base helper for details.
852
858
  def time_zone_select(method, priority_zones = nil, options = {}, html_options = {})
853
- @template.time_zone_select(@object_name, method, priority_zones, objectify_options(options), @default_options.merge(html_options))
859
+ @template.time_zone_select(@object_name, method, priority_zones, objectify_options(options), @default_html_options.merge(html_options))
854
860
  end
855
861
 
856
862
  # Wraps ActionView::Helpers::FormOptionsHelper#collection_check_boxes for form builders:
@@ -862,7 +868,7 @@ module ActionView
862
868
  #
863
869
  # Please refer to the documentation of the base helper for details.
864
870
  def collection_check_boxes(method, collection, value_method, text_method, options = {}, html_options = {}, &block)
865
- @template.collection_check_boxes(@object_name, method, collection, value_method, text_method, objectify_options(options), @default_options.merge(html_options), &block)
871
+ @template.collection_check_boxes(@object_name, method, collection, value_method, text_method, objectify_options(options), @default_html_options.merge(html_options), &block)
866
872
  end
867
873
 
868
874
  # Wraps ActionView::Helpers::FormOptionsHelper#collection_radio_buttons for form builders:
@@ -874,7 +880,7 @@ module ActionView
874
880
  #
875
881
  # Please refer to the documentation of the base helper for details.
876
882
  def collection_radio_buttons(method, collection, value_method, text_method, options = {}, html_options = {}, &block)
877
- @template.collection_radio_buttons(@object_name, method, collection, value_method, text_method, objectify_options(options), @default_options.merge(html_options), &block)
883
+ @template.collection_radio_buttons(@object_name, method, collection, value_method, text_method, objectify_options(options), @default_html_options.merge(html_options), &block)
878
884
  end
879
885
  end
880
886
  end
@@ -1,11 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "cgi"
2
4
  require "action_view/helpers/tag_helper"
3
5
  require "active_support/core_ext/string/output_safety"
4
6
  require "active_support/core_ext/module/attribute_accessors"
7
+ require "active_support/core_ext/symbol/starts_ends_with"
5
8
 
6
9
  module ActionView
7
10
  # = Action View Form Tag Helpers
8
- module Helpers
11
+ module Helpers #:nodoc:
9
12
  # Provides a number of methods for creating form tags that don't rely on an Active Record object assigned to the template like
10
13
  # FormHelper does. Instead, you provide the names and values manually.
11
14
  #
@@ -20,7 +23,9 @@ module ActionView
20
23
  mattr_accessor :embed_authenticity_token_in_remote_forms
21
24
  self.embed_authenticity_token_in_remote_forms = nil
22
25
 
23
- # Starts a form tag that points the action to a url configured with <tt>url_for_options</tt> just like
26
+ mattr_accessor :default_enforce_utf8, default: true
27
+
28
+ # Starts a form tag that points the action to a URL configured with <tt>url_for_options</tt> just like
24
29
  # ActionController::Base#url_for. The method for the form defaults to POST.
25
30
  #
26
31
  # ==== Options
@@ -113,7 +118,7 @@ module ActionView
113
118
  # # <option>Write</option></select>
114
119
  #
115
120
  # select_tag "people", options_from_collection_for_select(@people, "id", "name"), include_blank: true
116
- # # => <select id="people" name="people"><option value=""></option><option value="1">David</option></select>
121
+ # # => <select id="people" name="people"><option value="" label=" "></option><option value="1">David</option></select>
117
122
  #
118
123
  # select_tag "people", options_from_collection_for_select(@people, "id", "name"), include_blank: "All"
119
124
  # # => <select id="people" name="people"><option value="">All</option><option value="1">David</option></select>
@@ -130,10 +135,11 @@ module ActionView
130
135
  # # <option selected="selected">MasterCard</option></select>
131
136
  def select_tag(name, option_tags = nil, options = {})
132
137
  option_tags ||= ""
133
- html_name = (options[:multiple] == true && !name.to_s.ends_with?("[]")) ? "#{name}[]" : name
138
+ html_name = (options[:multiple] == true && !name.end_with?("[]")) ? "#{name}[]" : name
134
139
 
135
140
  if options.include?(:include_blank)
136
- include_blank = options.delete(:include_blank)
141
+ include_blank = options[:include_blank]
142
+ options = options.except(:include_blank)
137
143
  options_for_blank_options_tag = { value: "" }
138
144
 
139
145
  if include_blank == true
@@ -142,15 +148,15 @@ module ActionView
142
148
  end
143
149
 
144
150
  if include_blank
145
- option_tags = content_tag("option".freeze, include_blank, options_for_blank_options_tag).safe_concat(option_tags)
151
+ option_tags = content_tag("option", include_blank, options_for_blank_options_tag).safe_concat(option_tags)
146
152
  end
147
153
  end
148
154
 
149
155
  if prompt = options.delete(:prompt)
150
- option_tags = content_tag("option".freeze, prompt, value: "").safe_concat(option_tags)
156
+ option_tags = content_tag("option", prompt, value: "").safe_concat(option_tags)
151
157
  end
152
158
 
153
- content_tag "select".freeze, option_tags, { "name" => html_name, "id" => sanitize_to_id(name) }.update(options.stringify_keys)
159
+ content_tag "select", option_tags, { "name" => html_name, "id" => sanitize_to_id(name) }.update(options.stringify_keys)
154
160
  end
155
161
 
156
162
  # Creates a standard text field; use these text fields to input smaller chunks of text like a username
@@ -161,6 +167,8 @@ module ActionView
161
167
  # * <tt>:size</tt> - The number of visible characters that will fit in the input.
162
168
  # * <tt>:maxlength</tt> - The maximum number of characters that the browser will allow the user to enter.
163
169
  # * <tt>:placeholder</tt> - The text contained in the field by default which is removed when the field receives focus.
170
+ # If set to true, use a translation is found in the current I18n locale
171
+ # (through helpers.placeholders.<modelname>.<attribute>).
164
172
  # * Any other key creates standard HTML attributes for the tag.
165
173
  #
166
174
  # ==== Examples
@@ -272,7 +280,7 @@ module ActionView
272
280
  # file_field_tag 'file', accept: 'text/html', class: 'upload', value: 'index.html'
273
281
  # # => <input accept="text/html" class="upload" id="file" name="file" type="file" value="index.html" />
274
282
  def file_field_tag(name, options = {})
275
- text_field_tag(name, nil, options.merge(type: :file))
283
+ text_field_tag(name, nil, convert_direct_upload_option_to_url(options.merge(type: :file)))
276
284
  end
277
285
 
278
286
  # Creates a password field, a masked text field that will hide the users input behind a mask character.
@@ -385,14 +393,14 @@ module ActionView
385
393
  # * Any other key creates standard HTML options for the tag.
386
394
  #
387
395
  # ==== Examples
388
- # radio_button_tag 'gender', 'male'
389
- # # => <input id="gender_male" name="gender" type="radio" value="male" />
396
+ # radio_button_tag 'favorite_color', 'maroon'
397
+ # # => <input id="favorite_color_maroon" name="favorite_color" type="radio" value="maroon" />
390
398
  #
391
399
  # radio_button_tag 'receive_updates', 'no', true
392
400
  # # => <input checked="checked" id="receive_updates_no" name="receive_updates" type="radio" value="no" />
393
401
  #
394
402
  # radio_button_tag 'time_slot', "3:00 p.m.", false, disabled: true
395
- # # => <input disabled="disabled" id="time_slot_300_pm" name="time_slot" type="radio" value="3:00 p.m." />
403
+ # # => <input disabled="disabled" id="time_slot_3:00_p.m." name="time_slot" type="radio" value="3:00 p.m." />
396
404
  #
397
405
  # radio_button_tag 'color', "green", true, class: "color_input"
398
406
  # # => <input checked="checked" class="color_input" id="color_green" name="color" type="radio" value="green" />
@@ -454,7 +462,7 @@ module ActionView
454
462
  # submit tag but it isn't supported in legacy browsers. However,
455
463
  # the button tag does allow for richer labels such as images and emphasis,
456
464
  # so this helper will also accept a block. By default, it will create
457
- # a button tag with type `submit`, if type is not given.
465
+ # a button tag with type <tt>submit</tt>, if type is not given.
458
466
  #
459
467
  # ==== Options
460
468
  # * <tt>:data</tt> - This option can be used to add custom data attributes.
@@ -532,22 +540,23 @@ module ActionView
532
540
  #
533
541
  # ==== Examples
534
542
  # image_submit_tag("login.png")
535
- # # => <input alt="Login" src="/assets/login.png" type="image" />
543
+ # # => <input src="/assets/login.png" type="image" />
536
544
  #
537
545
  # image_submit_tag("purchase.png", disabled: true)
538
- # # => <input alt="Purchase" disabled="disabled" src="/assets/purchase.png" type="image" />
546
+ # # => <input disabled="disabled" src="/assets/purchase.png" type="image" />
539
547
  #
540
548
  # image_submit_tag("search.png", class: 'search_button', alt: 'Find')
541
- # # => <input alt="Find" class="search_button" src="/assets/search.png" type="image" />
549
+ # # => <input class="search_button" src="/assets/search.png" type="image" />
542
550
  #
543
551
  # image_submit_tag("agree.png", disabled: true, class: "agree_disagree_button")
544
- # # => <input alt="Agree" class="agree_disagree_button" disabled="disabled" src="/assets/agree.png" type="image" />
552
+ # # => <input class="agree_disagree_button" disabled="disabled" src="/assets/agree.png" type="image" />
545
553
  #
546
554
  # image_submit_tag("save.png", data: { confirm: "Are you sure?" })
547
- # # => <input alt="Save" src="/assets/save.png" data-confirm="Are you sure?" type="image" />
555
+ # # => <input src="/assets/save.png" data-confirm="Are you sure?" type="image" />
548
556
  def image_submit_tag(source, options = {})
549
557
  options = options.stringify_keys
550
- tag :input, { "alt" => image_alt(source), "type" => "image", "src" => path_to_image(source) }.update(options)
558
+ src = path_to_image(source, skip_pipeline: options.delete("skip_pipeline"))
559
+ tag :input, { "type" => "image", "src" => src }.update(options)
551
560
  end
552
561
 
553
562
  # Creates a field set for grouping HTML form elements.
@@ -572,7 +581,7 @@ module ActionView
572
581
  # # => <fieldset class="format"><p><input id="name" name="name" type="text" /></p></fieldset>
573
582
  def field_set_tag(legend = nil, options = nil, &block)
574
583
  output = tag(:fieldset, options, true)
575
- output.safe_concat(content_tag("legend".freeze, legend)) unless legend.blank?
584
+ output.safe_concat(content_tag("legend", legend)) unless legend.blank?
576
585
  output.concat(capture(&block)) if block_given?
577
586
  output.safe_concat("</fieldset>")
578
587
  end
@@ -864,7 +873,7 @@ module ActionView
864
873
  })
865
874
  end
866
875
 
867
- if html_options.delete("enforce_utf8") { true }
876
+ if html_options.delete("enforce_utf8") { default_enforce_utf8 }
868
877
  utf8_enforcer_tag + method_tag
869
878
  else
870
879
  method_tag
@@ -888,20 +897,26 @@ module ActionView
888
897
  end
889
898
 
890
899
  def set_default_disable_with(value, tag_options)
891
- return unless ActionView::Base.automatically_disable_submit_tag
892
- data = tag_options["data"]
900
+ data = tag_options.fetch("data", {})
893
901
 
894
- unless tag_options["data-disable-with"] == false || (data && data["disable_with"] == false)
902
+ if tag_options["data-disable-with"] == false || data["disable_with"] == false
903
+ data.delete("disable_with")
904
+ elsif ActionView::Base.automatically_disable_submit_tag
895
905
  disable_with_text = tag_options["data-disable-with"]
896
- disable_with_text ||= data["disable_with"] if data
906
+ disable_with_text ||= data["disable_with"]
897
907
  disable_with_text ||= value.to_s.clone
898
908
  tag_options.deep_merge!("data" => { "disable_with" => disable_with_text })
899
- else
900
- data.delete("disable_with") if data
901
909
  end
902
910
 
903
911
  tag_options.delete("data-disable-with")
904
912
  end
913
+
914
+ def convert_direct_upload_option_to_url(options)
915
+ if options.delete(:direct_upload) && respond_to?(:rails_direct_uploads_url)
916
+ options["data-direct-upload-url"] = rails_direct_uploads_url
917
+ end
918
+ options
919
+ end
905
920
  end
906
921
  end
907
922
  end