actionview 7.0.4 → 7.1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +343 -232
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +3 -3
  5. data/app/assets/javascripts/rails-ujs.esm.js +686 -0
  6. data/app/assets/javascripts/rails-ujs.js +630 -0
  7. data/lib/action_view/base.rb +34 -14
  8. data/lib/action_view/buffers.rb +106 -8
  9. data/lib/action_view/cache_expiry.rb +40 -43
  10. data/lib/action_view/context.rb +1 -1
  11. data/lib/action_view/deprecator.rb +7 -0
  12. data/lib/action_view/digestor.rb +1 -1
  13. data/lib/action_view/gem_version.rb +4 -4
  14. data/lib/action_view/helpers/active_model_helper.rb +1 -1
  15. data/lib/action_view/helpers/asset_tag_helper.rb +136 -52
  16. data/lib/action_view/helpers/asset_url_helper.rb +6 -5
  17. data/lib/action_view/helpers/atom_feed_helper.rb +5 -5
  18. data/lib/action_view/helpers/cache_helper.rb +7 -13
  19. data/lib/action_view/helpers/capture_helper.rb +32 -12
  20. data/lib/action_view/helpers/content_exfiltration_prevention_helper.rb +70 -0
  21. data/lib/action_view/helpers/controller_helper.rb +6 -0
  22. data/lib/action_view/helpers/csp_helper.rb +2 -2
  23. data/lib/action_view/helpers/csrf_helper.rb +3 -3
  24. data/lib/action_view/helpers/date_helper.rb +67 -59
  25. data/lib/action_view/helpers/debug_helper.rb +3 -3
  26. data/lib/action_view/helpers/form_helper.rb +56 -26
  27. data/lib/action_view/helpers/form_options_helper.rb +4 -1
  28. data/lib/action_view/helpers/form_tag_helper.rb +49 -15
  29. data/lib/action_view/helpers/javascript_helper.rb +1 -0
  30. data/lib/action_view/helpers/number_helper.rb +37 -329
  31. data/lib/action_view/helpers/output_safety_helper.rb +4 -4
  32. data/lib/action_view/helpers/rendering_helper.rb +1 -1
  33. data/lib/action_view/helpers/sanitize_helper.rb +51 -21
  34. data/lib/action_view/helpers/tag_helper.rb +5 -27
  35. data/lib/action_view/helpers/tags/base.rb +11 -52
  36. data/lib/action_view/helpers/tags/collection_check_boxes.rb +1 -0
  37. data/lib/action_view/helpers/tags/collection_radio_buttons.rb +1 -0
  38. data/lib/action_view/helpers/tags/collection_select.rb +3 -0
  39. data/lib/action_view/helpers/tags/date_field.rb +1 -1
  40. data/lib/action_view/helpers/tags/date_select.rb +2 -0
  41. data/lib/action_view/helpers/tags/datetime_field.rb +14 -6
  42. data/lib/action_view/helpers/tags/datetime_local_field.rb +11 -2
  43. data/lib/action_view/helpers/tags/grouped_collection_select.rb +3 -0
  44. data/lib/action_view/helpers/tags/month_field.rb +1 -1
  45. data/lib/action_view/helpers/tags/select.rb +4 -1
  46. data/lib/action_view/helpers/tags/select_renderer.rb +56 -0
  47. data/lib/action_view/helpers/tags/time_field.rb +1 -1
  48. data/lib/action_view/helpers/tags/time_zone_select.rb +3 -0
  49. data/lib/action_view/helpers/tags/week_field.rb +1 -1
  50. data/lib/action_view/helpers/tags/weekday_select.rb +3 -0
  51. data/lib/action_view/helpers/tags.rb +2 -0
  52. data/lib/action_view/helpers/text_helper.rb +156 -84
  53. data/lib/action_view/helpers/translation_helper.rb +3 -3
  54. data/lib/action_view/helpers/url_helper.rb +47 -18
  55. data/lib/action_view/helpers.rb +2 -0
  56. data/lib/action_view/layouts.rb +8 -6
  57. data/lib/action_view/log_subscriber.rb +49 -32
  58. data/lib/action_view/lookup_context.rb +29 -13
  59. data/lib/action_view/path_registry.rb +57 -0
  60. data/lib/action_view/path_set.rb +13 -14
  61. data/lib/action_view/railtie.rb +26 -3
  62. data/lib/action_view/record_identifier.rb +15 -8
  63. data/lib/action_view/renderer/abstract_renderer.rb +1 -1
  64. data/lib/action_view/renderer/collection_renderer.rb +10 -2
  65. data/lib/action_view/renderer/partial_renderer/collection_caching.rb +21 -3
  66. data/lib/action_view/renderer/partial_renderer.rb +2 -1
  67. data/lib/action_view/renderer/renderer.rb +2 -0
  68. data/lib/action_view/renderer/streaming_template_renderer.rb +3 -2
  69. data/lib/action_view/renderer/template_renderer.rb +3 -2
  70. data/lib/action_view/rendering.rb +22 -4
  71. data/lib/action_view/ripper_ast_parser.rb +6 -6
  72. data/lib/action_view/routing_url_for.rb +4 -4
  73. data/lib/action_view/template/error.rb +14 -1
  74. data/lib/action_view/template/handlers/builder.rb +4 -4
  75. data/lib/action_view/template/handlers/erb/erubi.rb +23 -27
  76. data/lib/action_view/template/handlers/erb.rb +73 -1
  77. data/lib/action_view/template/handlers.rb +1 -1
  78. data/lib/action_view/template/html.rb +1 -1
  79. data/lib/action_view/template/raw_file.rb +1 -1
  80. data/lib/action_view/template/renderable.rb +1 -1
  81. data/lib/action_view/template/resolver.rb +15 -5
  82. data/lib/action_view/template/text.rb +1 -1
  83. data/lib/action_view/template/types.rb +25 -34
  84. data/lib/action_view/template.rb +249 -54
  85. data/lib/action_view/template_path.rb +2 -0
  86. data/lib/action_view/test_case.rb +176 -21
  87. data/lib/action_view/unbound_template.rb +17 -7
  88. data/lib/action_view/version.rb +1 -1
  89. data/lib/action_view/view_paths.rb +15 -24
  90. data/lib/action_view.rb +4 -1
  91. metadata +27 -28
  92. data/lib/assets/compiled/rails-ujs.js +0 -746
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActionView
4
- # = Action View CSP Helper
5
4
  module Helpers # :nodoc:
5
+ # = Action View CSP \Helpers
6
6
  module CspHelper
7
7
  # Returns a meta tag "csp-nonce" with the per-session nonce value
8
8
  # for allowing inline <script> tags.
@@ -11,7 +11,7 @@ module ActionView
11
11
  # <%= csp_meta_tag %>
12
12
  # </head>
13
13
  #
14
- # This is used by the Rails UJS helper to create dynamically
14
+ # This is used by the \Rails UJS helper to create dynamically
15
15
  # loaded inline <script> elements.
16
16
  #
17
17
  def csp_meta_tag(**options)
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActionView
4
- # = Action View CSRF Helper
5
4
  module Helpers # :nodoc:
5
+ # = Action View CSRF \Helpers
6
6
  module CsrfHelper
7
7
  # Returns meta tags "csrf-param" and "csrf-token" with the name of the cross-site
8
8
  # request forgery protection parameter and token, respectively.
@@ -16,8 +16,8 @@ module ActionView
16
16
  #
17
17
  # You don't need to use these tags for regular forms as they generate their own hidden fields.
18
18
  #
19
- # For AJAX requests other than GETs, extract the "csrf-token" from the meta-tag and send as the
20
- # "X-CSRF-Token" HTTP header. If you are using rails-ujs this happens automatically.
19
+ # For Ajax requests other than GETs, extract the "csrf-token" from the meta-tag and send as the
20
+ # +X-CSRF-Token+ HTTP header. If you are using rails-ujs, this happens automatically.
21
21
  #
22
22
  def csrf_meta_tags
23
23
  if defined?(protect_against_forgery?) && protect_against_forgery?
@@ -10,7 +10,7 @@ require "active_support/core_ext/object/with_options"
10
10
 
11
11
  module ActionView
12
12
  module Helpers # :nodoc:
13
- # = Action View Date Helpers
13
+ # = Action View \Date \Helpers
14
14
  #
15
15
  # The Date Helper primarily creates select/option tags for different kinds of dates and times or date and time
16
16
  # elements. All of the select-type methods share a number of common options that are as follows:
@@ -72,7 +72,7 @@ module ActionView
72
72
  # distance_of_time_in_words(to_time, from_time, include_seconds: true) # => about 6 years
73
73
  # distance_of_time_in_words(Time.now, Time.now) # => less than a minute
74
74
  #
75
- # With the <tt>scope</tt> option, you can define a custom scope for Rails
75
+ # With the <tt>scope</tt> option, you can define a custom scope for \Rails
76
76
  # to look up the translation.
77
77
  #
78
78
  # For example you can define the following in your locale (e.g. en.yml).
@@ -217,7 +217,7 @@ module ActionView
217
217
  # * <tt>:order</tt> - Set to an array containing <tt>:day</tt>, <tt>:month</tt> and <tt>:year</tt> to
218
218
  # customize the order in which the select fields are shown. If you leave out any of the symbols, the respective
219
219
  # select will not be shown (like when you set <tt>discard_xxx: true</tt>. Defaults to the order defined in
220
- # the respective locale (e.g. [:year, :month, :day] in the en locale that ships with Rails).
220
+ # the respective locale (e.g. [:year, :month, :day] in the en locale that ships with \Rails).
221
221
  # * <tt>:include_blank</tt> - Include a blank option in every select field so it's possible to set empty
222
222
  # dates.
223
223
  # * <tt>:default</tt> - Set a default date if the affected date isn't set or is +nil+.
@@ -320,6 +320,10 @@ module ActionView
320
320
  # # You can set :ampm option to true which will show the hours as: 12 PM, 01 AM .. 11 PM.
321
321
  # time_select 'game', 'game_time', { ampm: true }
322
322
  #
323
+ # # You can set :ignore_date option to true which will remove the hidden inputs for day,
324
+ # # month, and year that are set by default on this helper when you only want the time inputs
325
+ # time_select 'game', 'game_time', { ignore_date: true }
326
+ #
323
327
  # The selects are prepared for multi-parameter assignment to an Active Record object.
324
328
  #
325
329
  # Note: If the day is not included as an option but the month is, the day will be set to the 1st to ensure that
@@ -844,14 +848,14 @@ module ActionView
844
848
  if @options[:use_hidden] || @options[:discard_year]
845
849
  build_hidden(:year, val)
846
850
  else
847
- options = {}
848
- options[:start] = @options[:start_year] || middle_year - 5
849
- options[:end] = @options[:end_year] || middle_year + 5
850
- options[:step] = options[:start] < options[:end] ? 1 : -1
851
- options[:leading_zeros] = false
852
- options[:max_years_allowed] = @options[:max_years_allowed] || 1000
853
-
854
- if (options[:end] - options[:start]).abs > options[:max_years_allowed]
851
+ options = {}
852
+ options[:start] = @options[:start_year] || middle_year - 5
853
+ options[:end] = @options[:end_year] || middle_year + 5
854
+ options[:step] = options[:start] < options[:end] ? 1 : -1
855
+
856
+ max_years_allowed = @options[:max_years_allowed] || 1000
857
+
858
+ if (options[:end] - options[:start]).abs > max_years_allowed
855
859
  raise ArgumentError, "There are too many years options to be built. Are you sure you haven't mistyped something? You can provide the :max_years_allowed parameter."
856
860
  end
857
861
 
@@ -936,7 +940,7 @@ module ActionView
936
940
  #
937
941
  # month_name(1) # => 1
938
942
  #
939
- # If the <tt>:use_two_month_numbers</tt> option is passed:
943
+ # If the <tt>:use_two_digit_numbers</tt> option is passed:
940
944
  #
941
945
  # month_name(1) # => '01'
942
946
  #
@@ -1001,22 +1005,25 @@ module ActionView
1001
1005
  end
1002
1006
 
1003
1007
  # Build select option HTML from date value and options.
1004
- # build_options(15, start: 1, end: 31)
1005
- # => "<option value="1">1</option>
1006
- # <option value="2">2</option>
1007
- # <option value="3">3</option>..."
1008
1008
  #
1009
- # If <tt>use_two_digit_numbers: true</tt> option is passed
1010
- # build_options(15, start: 1, end: 31, use_two_digit_numbers: true)
1011
- # => "<option value="1">01</option>
1012
- # <option value="2">02</option>
1013
- # <option value="3">03</option>..."
1009
+ # build_options(15, start: 1, end: 31)
1010
+ # => "<option value="1">1</option>
1011
+ # <option value="2">2</option>
1012
+ # <option value="3">3</option>..."
1013
+ #
1014
+ # If <tt>use_two_digit_numbers: true</tt> option is passed:
1015
+ #
1016
+ # build_options(15, start: 1, end: 31, use_two_digit_numbers: true)
1017
+ # => "<option value="1">01</option>
1018
+ # <option value="2">02</option>
1019
+ # <option value="3">03</option>..."
1020
+ #
1021
+ # If <tt>:step</tt> options is passed:
1014
1022
  #
1015
- # If <tt>:step</tt> options is passed
1016
- # build_options(15, start: 1, end: 31, step: 2)
1017
- # => "<option value="1">1</option>
1018
- # <option value="3">3</option>
1019
- # <option value="5">5</option>..."
1023
+ # build_options(15, start: 1, end: 31, step: 2)
1024
+ # => "<option value="1">1</option>
1025
+ # <option value="3">3</option>
1026
+ # <option value="5">5</option>..."
1020
1027
  def build_options(selected, options = {})
1021
1028
  options = {
1022
1029
  leading_zeros: true, ampm: false, use_two_digit_numbers: false
@@ -1041,22 +1048,25 @@ module ActionView
1041
1048
  end
1042
1049
 
1043
1050
  # Build select option HTML for day.
1044
- # build_day_options(2)
1045
- # => "<option value="1">1</option>
1046
- # <option value="2" selected="selected">2</option>
1047
- # <option value="3">3</option>..."
1051
+ #
1052
+ # build_day_options(2)
1053
+ # => "<option value="1">1</option>
1054
+ # <option value="2" selected="selected">2</option>
1055
+ # <option value="3">3</option>..."
1048
1056
  #
1049
1057
  # If <tt>day_format: ->(day) { day.ordinalize }</tt> option is passed to DateTimeSelector
1050
- # build_day_options(2)
1051
- # => "<option value="1">1st</option>
1052
- # <option value="2" selected="selected">2nd</option>
1053
- # <option value="3">3rd</option>..."
1058
+ #
1059
+ # build_day_options(2)
1060
+ # => "<option value="1">1st</option>
1061
+ # <option value="2" selected="selected">2nd</option>
1062
+ # <option value="3">3rd</option>..."
1054
1063
  #
1055
1064
  # If <tt>use_two_digit_numbers: true</tt> option is passed to DateTimeSelector
1056
- # build_day_options(2)
1057
- # => "<option value="1">01</option>
1058
- # <option value="2" selected="selected">02</option>
1059
- # <option value="3">03</option>..."
1065
+ #
1066
+ # build_day_options(2)
1067
+ # => "<option value="1">01</option>
1068
+ # <option value="2" selected="selected">02</option>
1069
+ # <option value="3">03</option>..."
1060
1070
  def build_day_options(selected)
1061
1071
  select_options = []
1062
1072
  (1..31).each do |value|
@@ -1070,17 +1080,11 @@ module ActionView
1070
1080
  end
1071
1081
 
1072
1082
  # Build select option HTML for year.
1073
- # If <tt>year_format</tt> option is not passed
1074
- # build_year_options(1998, start: 1998, end: 2000)
1075
- # => "<option value="1998" selected="selected">1998</option>
1076
- # <option value="1999">1999</option>
1077
- # <option value="2000">2000</option>"
1078
1083
  #
1079
- # If <tt>year_format</tt> option is passed
1080
- # build_year_options(1998, start: 1998, end: 2000, year_format: ->year { "Heisei #{ year - 1988 }" })
1081
- # => "<option value="1998" selected="selected">Heisei 10</option>
1082
- # <option value="1999">Heisei 11</option>
1083
- # <option value="2000">Heisei 12</option>"
1084
+ # build_year_options(1998, start: 1998, end: 2000)
1085
+ # => "<option value="1998" selected="selected">1998</option>
1086
+ # <option value="1999">1999</option>
1087
+ # <option value="2000">2000</option>"
1084
1088
  def build_year_options(selected, options = {})
1085
1089
  start = options.delete(:start)
1086
1090
  stop = options.delete(:end)
@@ -1098,10 +1102,11 @@ module ActionView
1098
1102
  end
1099
1103
 
1100
1104
  # Builds select tag from date type and HTML select options.
1101
- # build_select(:month, "<option value="1">January</option>...")
1102
- # => "<select id="post_written_on_2i" name="post[written_on(2i)]">
1103
- # <option value="1">January</option>...
1104
- # </select>"
1105
+ #
1106
+ # build_select(:month, "<option value="1">January</option>...")
1107
+ # => "<select id="post_written_on_2i" name="post[written_on(2i)]">
1108
+ # <option value="1">January</option>...
1109
+ # </select>"
1105
1110
  def build_select(type, select_options_as_html)
1106
1111
  select_options = {
1107
1112
  id: input_id_from_type(type),
@@ -1118,9 +1123,10 @@ module ActionView
1118
1123
  (content_tag("select", select_html.html_safe, select_options) + "\n").html_safe
1119
1124
  end
1120
1125
 
1121
- # Builds the CSS class value for the select element
1122
- # css_class_attribute(:year, 'date optional', { year: 'my-year' })
1123
- # => "date optional my-year"
1126
+ # Builds the CSS class value for the select element.
1127
+ #
1128
+ # css_class_attribute(:year, 'date optional', { year: 'my-year' })
1129
+ # => "date optional my-year"
1124
1130
  def css_class_attribute(type, html_options_class, options) # :nodoc:
1125
1131
  css_class = \
1126
1132
  case options
@@ -1134,8 +1140,9 @@ module ActionView
1134
1140
  end
1135
1141
 
1136
1142
  # Builds a prompt option tag with supplied options or from default options.
1137
- # prompt_option_tag(:month, prompt: 'Select month')
1138
- # => "<option value="">Select month</option>"
1143
+ #
1144
+ # prompt_option_tag(:month, prompt: 'Select month')
1145
+ # => "<option value="">Select month</option>"
1139
1146
  def prompt_option_tag(type, options)
1140
1147
  prompt = \
1141
1148
  case options
@@ -1152,8 +1159,9 @@ module ActionView
1152
1159
  end
1153
1160
 
1154
1161
  # Builds hidden input tag for date part and value.
1155
- # build_hidden(:year, 2008)
1156
- # => "<input type="hidden" id="date_year" name="date[year]" value="2008" autocomplete="off" />"
1162
+ #
1163
+ # build_hidden(:year, 2008)
1164
+ # => "<input type="hidden" id="date_year" name="date[year]" value="2008" autocomplete="off" />"
1157
1165
  def build_hidden(type, value)
1158
1166
  select_options = {
1159
1167
  type: "hidden",
@@ -3,10 +3,10 @@
3
3
  require "action_view/helpers/tag_helper"
4
4
 
5
5
  module ActionView
6
- # = Action View Debug Helper
7
- #
8
- # Provides a set of methods for making it easier to debug Rails objects.
9
6
  module Helpers # :nodoc:
7
+ # = Action View Debug \Helpers
8
+ #
9
+ # Provides a set of methods for making it easier to debug \Rails objects.
10
10
  module DebugHelper
11
11
  include TagHelper
12
12
 
@@ -13,8 +13,9 @@ require "active_support/core_ext/string/output_safety"
13
13
  require "active_support/core_ext/string/inflections"
14
14
 
15
15
  module ActionView
16
- # = Action View Form Helpers
17
16
  module Helpers # :nodoc:
17
+ # = Action View Form \Helpers
18
+ #
18
19
  # Form helpers are designed to make working with resources much easier
19
20
  # compared to using vanilla HTML.
20
21
  #
@@ -28,7 +29,7 @@ module ActionView
28
29
  # when the form is initially displayed, input fields corresponding to attributes
29
30
  # of the resource should show the current values of those attributes.
30
31
  #
31
- # In Rails, this is usually achieved by creating the form using +form_for+ and
32
+ # In \Rails, this is usually achieved by creating the form using +form_for+ and
32
33
  # a number of related helper methods. +form_for+ generates an appropriate <tt>form</tt>
33
34
  # tag and yields a form builder object that knows the model the form is about.
34
35
  # Input fields are created by calling methods defined on the form builder, which
@@ -122,7 +123,7 @@ module ActionView
122
123
  # of a specific model object.
123
124
  #
124
125
  # The method can be used in several slightly different ways, depending on
125
- # how much you wish to rely on Rails to infer automatically from the model
126
+ # how much you wish to rely on \Rails to infer automatically from the model
126
127
  # how the form should be constructed. For a generic model object, a form
127
128
  # can be created by passing +form_for+ a string or symbol representing
128
129
  # the object we are concerned with:
@@ -251,7 +252,7 @@ module ActionView
251
252
  # form is going to be sent. However, further simplification is possible
252
253
  # if the record passed to +form_for+ is a _resource_, i.e. it corresponds
253
254
  # to a set of RESTful routes, e.g. defined using the +resources+ method
254
- # in <tt>config/routes.rb</tt>. In this case Rails will simply infer the
255
+ # in <tt>config/routes.rb</tt>. In this case \Rails will simply infer the
255
256
  # appropriate URL from the record itself. For example,
256
257
  #
257
258
  # <%= form_for @post do |f| %>
@@ -438,7 +439,7 @@ module ActionView
438
439
  model = nil
439
440
  object_name = record
440
441
  else
441
- model = convert_to_model(record)
442
+ model = record
442
443
  object = _object_for_form_builder(record)
443
444
  raise ArgumentError, "First argument in form cannot contain nil or be empty" unless object
444
445
  object_name = options[:as] || model_name_from_record_or_class(object).param_key
@@ -496,7 +497,7 @@ module ActionView
496
497
  # <%= form.text_field :title %>
497
498
  # <% end %>
498
499
  # # =>
499
- # <form method="post" data-remote="true">
500
+ # <form method="post">
500
501
  # <input type="text" name="title">
501
502
  # </form>
502
503
  #
@@ -555,7 +556,7 @@ module ActionView
555
556
  # is a _resource_. It corresponds to a set of RESTful routes, most likely
556
557
  # defined via +resources+ in <tt>config/routes.rb</tt>.
557
558
  #
558
- # So when passing such a model record, Rails infers the URL and method.
559
+ # So when passing such a model record, \Rails infers the URL and method.
559
560
  #
560
561
  # <%= form_with model: @post do |form| %>
561
562
  # ...
@@ -618,12 +619,12 @@ module ActionView
618
619
  # * <tt>:local</tt> - Whether to use standard HTTP form submission.
619
620
  # When set to <tt>true</tt>, the form is submitted via standard HTTP.
620
621
  # When set to <tt>false</tt>, the form is submitted as a "remote form", which
621
- # is handled by Rails UJS as an XHR. When unspecified, the behavior is derived
622
+ # is handled by \Rails UJS as an XHR. When unspecified, the behavior is derived
622
623
  # from <tt>config.action_view.form_with_generates_remote_forms</tt> where the
623
624
  # config's value is actually the inverse of what <tt>local</tt>'s value would be.
624
- # As of Rails 6.1, that configuration option defaults to <tt>false</tt>
625
+ # As of \Rails 6.1, that configuration option defaults to <tt>false</tt>
625
626
  # (which has the equivalent effect of passing <tt>local: true</tt>).
626
- # In previous versions of Rails, that configuration option defaults to
627
+ # In previous versions of \Rails, that configuration option defaults to
627
628
  # <tt>true</tt> (the equivalent of passing <tt>local: false</tt>).
628
629
  # * <tt>:skip_enforcing_utf8</tt> - If set to true, a hidden input with name
629
630
  # utf8 is not output.
@@ -756,10 +757,14 @@ module ActionView
756
757
 
757
758
  if model
758
759
  if url != false
759
- url ||= polymorphic_path(model, format: format)
760
+ url ||= if format.nil?
761
+ polymorphic_path(model, {})
762
+ else
763
+ polymorphic_path(model, format: format)
764
+ end
760
765
  end
761
766
 
762
- model = _object_for_form_builder(model)
767
+ model = convert_to_model(_object_for_form_builder(model))
763
768
  scope ||= model_name_from_record_or_class(model).param_key
764
769
  end
765
770
 
@@ -1001,8 +1006,8 @@ module ActionView
1001
1006
  # <% end %>
1002
1007
  #
1003
1008
  # When a collection is used you might want to know the index of each
1004
- # object into the array. For this purpose, the <tt>index</tt> method
1005
- # is available in the FormBuilder object.
1009
+ # object in the array. For this purpose, the <tt>index</tt> method is
1010
+ # available in the FormBuilder object.
1006
1011
  #
1007
1012
  # <%= form_for @person do |person_form| %>
1008
1013
  # ...
@@ -1113,6 +1118,8 @@ module ActionView
1113
1118
  # post:
1114
1119
  # cost: "Total cost"
1115
1120
  #
1121
+ # <code></code>
1122
+ #
1116
1123
  # label(:post, :cost)
1117
1124
  # # => <label for="post_cost">Total cost</label>
1118
1125
  #
@@ -1311,7 +1318,7 @@ module ActionView
1311
1318
  # ...
1312
1319
  # <% end %>
1313
1320
  #
1314
- # because parameter name repetition is precisely what Rails seeks to distinguish
1321
+ # because parameter name repetition is precisely what \Rails seeks to distinguish
1315
1322
  # the elements of the array. For each item with a checked check box you
1316
1323
  # get an extra ghost item with only that attribute, assigned to "0".
1317
1324
  #
@@ -1494,6 +1501,12 @@ module ActionView
1494
1501
  # datetime_field("user", "born_on", min: "2014-05-20T00:00:00")
1495
1502
  # # => <input id="user_born_on" name="user[born_on]" type="datetime-local" min="2014-05-20T00:00:00.000" />
1496
1503
  #
1504
+ # By default, provided datetimes will be formatted including seconds. You can render just the date, hour,
1505
+ # and minute by passing <tt>include_seconds: false</tt>.
1506
+ #
1507
+ # @user.born_on = Time.current
1508
+ # datetime_field("user", "born_on", include_seconds: false)
1509
+ # # => <input id="user_born_on" name="user[born_on]" type="datetime-local" value="2014-05-20T14:35" />
1497
1510
  def datetime_field(object_name, method, options = {})
1498
1511
  Tags::DatetimeLocalField.new(object_name, method, self, options).render
1499
1512
  end
@@ -1610,6 +1623,8 @@ module ActionView
1610
1623
  end
1611
1624
  end
1612
1625
 
1626
+ # = Action View Form Builder
1627
+ #
1613
1628
  # A +FormBuilder+ object is associated with a particular model object and
1614
1629
  # allows you to generate fields associated with the model object. The
1615
1630
  # +FormBuilder+ object is yielded when using +form_for+ or +fields_for+.
@@ -1735,7 +1750,7 @@ module ActionView
1735
1750
  # <tt><button></tt> element should be treated as the <tt><form></tt>
1736
1751
  # element's submit button, regardless of where it exists in the DOM.
1737
1752
  def id
1738
- options.dig(:html, :id)
1753
+ options.dig(:html, :id) || options[:id]
1739
1754
  end
1740
1755
 
1741
1756
  # Generate an HTML <tt>id</tt> attribute value for the given field
@@ -1754,7 +1769,7 @@ module ActionView
1754
1769
  # <tt>aria-describedby</tt> attribute referencing the <tt><span></tt>
1755
1770
  # element, sharing a common <tt>id</tt> root (<tt>post_title</tt>, in this
1756
1771
  # case).
1757
- def field_id(method, *suffixes, namespace: @options[:namespace], index: @index)
1772
+ def field_id(method, *suffixes, namespace: @options[:namespace], index: @options[:index])
1758
1773
  @template.field_id(@object_name, method, *suffixes, namespace: namespace, index: index)
1759
1774
  end
1760
1775
 
@@ -1766,15 +1781,15 @@ module ActionView
1766
1781
  #
1767
1782
  # <%= form_for @post do |f| %>
1768
1783
  # <%= f.text_field :title, name: f.field_name(:title, :subtitle) %>
1769
- # <%# => <input type="text" name="post[title][subtitle]">
1784
+ # <%# => <input type="text" name="post[title][subtitle]"> %>
1770
1785
  # <% end %>
1771
1786
  #
1772
1787
  # <%= form_for @post do |f| %>
1773
- # <%= f.field_tag :tag, name: f.field_name(:tag, multiple: true) %>
1774
- # <%# => <input type="text" name="post[tag][]">
1788
+ # <%= f.text_field :tag, name: f.field_name(:tag, multiple: true) %>
1789
+ # <%# => <input type="text" name="post[tag][]"> %>
1775
1790
  # <% end %>
1776
1791
  #
1777
- def field_name(method, *methods, multiple: false, index: @index)
1792
+ def field_name(method, *methods, multiple: false, index: @options[:index])
1778
1793
  object_name = @options.fetch(:as) { @object_name }
1779
1794
 
1780
1795
  @template.field_name(object_name, method, *methods, index: index, multiple: multiple)
@@ -2074,6 +2089,18 @@ module ActionView
2074
2089
  # DateHelper that are designed to work with an object as base, like
2075
2090
  # FormOptionsHelper#collection_select and DateHelper#datetime_select.
2076
2091
  #
2092
+ # +fields_for+ tries to be smart about parameters, but it can be confused if both
2093
+ # name and value parameters are provided and the provided value has the shape of an
2094
+ # option Hash. To remove the ambiguity, explicitly pass an option Hash, even if empty.
2095
+ #
2096
+ # <%= form_for @person do |person_form| %>
2097
+ # ...
2098
+ # <%= fields_for :permission, @person.permission, {} do |permission_fields| %>
2099
+ # Admin?: <%= check_box_tag permission_fields.field_name(:admin), @person.permission[:admin] %>
2100
+ # <% end %>
2101
+ # ...
2102
+ # <% end %>
2103
+ #
2077
2104
  # === Nested Attributes Examples
2078
2105
  #
2079
2106
  # When the object belonging to the current scope has a nested attribute
@@ -2238,7 +2265,7 @@ module ActionView
2238
2265
  # <% end %>
2239
2266
  #
2240
2267
  # When a collection is used you might want to know the index of each
2241
- # object into the array. For this purpose, the <tt>index</tt> method
2268
+ # object in the array. For this purpose, the <tt>index</tt> method
2242
2269
  # is available in the FormBuilder object.
2243
2270
  #
2244
2271
  # <%= form_for @person do |person_form| %>
@@ -2254,8 +2281,9 @@ module ActionView
2254
2281
  # to store the ID of the record. There are circumstances where this
2255
2282
  # hidden field is not needed and you can pass <tt>include_id: false</tt>
2256
2283
  # to prevent fields_for from rendering it automatically.
2257
- def fields_for(record_name, record_object = nil, fields_options = {}, &block)
2258
- fields_options, record_object = record_object, nil if record_object.is_a?(Hash) && record_object.extractable_options?
2284
+ def fields_for(record_name, record_object = nil, fields_options = nil, &block)
2285
+ fields_options, record_object = record_object, nil if fields_options.nil? && record_object.is_a?(Hash) && record_object.extractable_options?
2286
+ fields_options ||= {}
2259
2287
  fields_options[:builder] ||= options[:builder]
2260
2288
  fields_options[:namespace] = options[:namespace]
2261
2289
  fields_options[:parent_builder] = self
@@ -2332,6 +2360,8 @@ module ActionView
2332
2360
  # post:
2333
2361
  # cost: "Total cost"
2334
2362
  #
2363
+ # <code></code>
2364
+ #
2335
2365
  # label(:cost)
2336
2366
  # # => <label for="post_cost">Total cost</label>
2337
2367
  #
@@ -2412,7 +2442,7 @@ module ActionView
2412
2442
  # ...
2413
2443
  # <% end %>
2414
2444
  #
2415
- # because parameter name repetition is precisely what Rails seeks to distinguish
2445
+ # because parameter name repetition is precisely what \Rails seeks to distinguish
2416
2446
  # the elements of the array. For each item with a checked check box you
2417
2447
  # get an extra ghost item with only that attribute, assigned to "0".
2418
2448
  #
@@ -2495,7 +2525,7 @@ module ActionView
2495
2525
  # * Creates standard HTML attributes for the tag.
2496
2526
  # * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
2497
2527
  # * <tt>:multiple</tt> - If set to true, *in most updated browsers* the user will be allowed to select multiple files.
2498
- # * <tt>:include_hidden</tt> - When <tt>multiple: true</tt> and <tt>include_hidden: true</tt>, the field will be prefixed with an <tt><input type="hidden"></tt> field with an empty value to support submitting an empty collection of files.
2528
+ # * <tt>:include_hidden</tt> - When <tt>multiple: true</tt> and <tt>include_hidden: true</tt>, the field will be prefixed with an <tt><input type="hidden"></tt> field with an empty value to support submitting an empty collection of files. Since <tt>include_hidden</tt> will default to <tt>config.active_storage.multiple_file_field_include_hidden</tt> if you don't specify <tt>include_hidden</tt>, you will need to pass <tt>include_hidden: false</tt> to prevent submitting an empty collection of files when passing <tt>multiple: true</tt>.
2499
2529
  # * <tt>:accept</tt> - If set to one or multiple mime-types, the user will be suggested a filter when choosing a file. You still need to set up model validations.
2500
2530
  #
2501
2531
  # ==== Examples
@@ -8,8 +8,9 @@ require "active_support/core_ext/array/wrap"
8
8
  require "action_view/helpers/text_helper"
9
9
 
10
10
  module ActionView
11
- # = Action View Form Option Helpers
12
11
  module Helpers # :nodoc:
12
+ # = Action View Form Option \Helpers
13
+ #
13
14
  # Provides a number of methods for turning different kinds of containers into a set of option tags.
14
15
  #
15
16
  # The <tt>collection_select</tt>, <tt>select</tt> and <tt>time_zone_select</tt> methods take an <tt>options</tt> parameter, a hash:
@@ -500,6 +501,8 @@ module ActionView
500
501
  # <tt><optgroup></tt> label while the second value must be an array of options. The second value can be a
501
502
  # nested array of text-value pairs. See <tt>options_for_select</tt> for more info.
502
503
  # Ex. ["North America",[["United States","US"],["Canada","CA"]]]
504
+ # An optional third value can be provided as HTML attributes for the <tt>optgroup</tt>.
505
+ # Ex. ["North America",[["United States","US"],["Canada","CA"]], { disabled: "disabled" }]
503
506
  # * +selected_key+ - A value equal to the +value+ attribute for one of the <tt><option></tt> tags,
504
507
  # which will have the +selected+ attribute set. Note: It is possible for this value to match multiple options
505
508
  # as you might have the same option in multiple groups. Each will then get <tt>selected="selected"</tt>.