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 "action_view/helpers/javascript_helper"
2
4
  require "active_support/core_ext/array/access"
3
5
  require "active_support/core_ext/hash/keys"
@@ -43,7 +45,7 @@ module ActionView
43
45
  def _back_url # :nodoc:
44
46
  _filtered_referrer || "javascript:history.back()"
45
47
  end
46
- protected :_back_url
48
+ private :_back_url
47
49
 
48
50
  def _filtered_referrer # :nodoc:
49
51
  if controller.respond_to?(:request)
@@ -54,12 +56,12 @@ module ActionView
54
56
  end
55
57
  rescue URI::InvalidURIError
56
58
  end
57
- protected :_filtered_referrer
59
+ private :_filtered_referrer
58
60
 
59
61
  # Creates an anchor element of the given +name+ using a URL created by the set of +options+.
60
62
  # See the valid options in the documentation for +url_for+. It's also possible to
61
- # pass a String instead of an options hash, which generates an anchor element that uses the
62
- # value of the String as the href for the link. Using a <tt>:back</tt> Symbol instead
63
+ # pass a \String instead of an options hash, which generates an anchor element that uses the
64
+ # value of the \String as the href for the link. Using a <tt>:back</tt> \Symbol instead
63
65
  # of an options hash will generate a link to the referrer (a JavaScript back link
64
66
  # will be used in place of a referrer if none exists). If +nil+ is passed as the name
65
67
  # the value of the link itself will become the name.
@@ -137,6 +139,11 @@ module ActionView
137
139
  # link_to "Profiles", controller: "profiles"
138
140
  # # => <a href="/profiles">Profiles</a>
139
141
  #
142
+ # When name is +nil+ the href is presented instead
143
+ #
144
+ # link_to nil, "http://example.com"
145
+ # # => <a href="http://www.example.com">http://www.example.com</a>
146
+ #
140
147
  # You can use a block as well if your link target is hard to fit into the name parameter. ERB example:
141
148
  #
142
149
  # <%= link_to(@profile) do %>
@@ -170,7 +177,7 @@ module ActionView
170
177
  # # => <a href="/searches?query=ruby+on+rails">Ruby on Rails search</a>
171
178
  #
172
179
  # link_to "Nonsense search", searches_path(foo: "bar", baz: "quux")
173
- # # => <a href="/searches?foo=bar&amp;baz=quux">Nonsense search</a>
180
+ # # => <a href="/searches?foo=bar&baz=quux">Nonsense search</a>
174
181
  #
175
182
  # The only option specific to +link_to+ (<tt>:method</tt>) is used as follows:
176
183
  #
@@ -193,9 +200,9 @@ module ActionView
193
200
  html_options = convert_options_to_data_attributes(options, html_options)
194
201
 
195
202
  url = url_for(options)
196
- html_options["href".freeze] ||= url
203
+ html_options["href"] ||= url
197
204
 
198
- content_tag("a".freeze, name || url, html_options, &block)
205
+ content_tag("a", name || url, html_options, &block)
199
206
  end
200
207
 
201
208
  # Generates a form containing a single button that submits to the URL created
@@ -219,7 +226,7 @@ module ActionView
219
226
  # The +options+ hash accepts the same options as +url_for+.
220
227
  #
221
228
  # There are a few special +html_options+:
222
- # * <tt>:method</tt> - Symbol of HTTP verb. Supported verbs are <tt>:post</tt>, <tt>:get</tt>,
229
+ # * <tt>:method</tt> - \Symbol of HTTP verb. Supported verbs are <tt>:post</tt>, <tt>:get</tt>,
223
230
  # <tt>:delete</tt>, <tt>:patch</tt>, and <tt>:put</tt>. By default it will be <tt>:post</tt>.
224
231
  # * <tt>:disabled</tt> - If set to true, it will generate a disabled button.
225
232
  # * <tt>:data</tt> - This option can be used to add custom data attributes.
@@ -228,7 +235,7 @@ module ActionView
228
235
  # * <tt>:form</tt> - This hash will be form attributes
229
236
  # * <tt>:form_class</tt> - This controls the class of the form within which the submit button will
230
237
  # be placed
231
- # * <tt>:params</tt> - Hash of parameters to be rendered as hidden fields within the form.
238
+ # * <tt>:params</tt> - \Hash of parameters to be rendered as hidden fields within the form.
232
239
  #
233
240
  # ==== Data attributes
234
241
  #
@@ -246,7 +253,7 @@ module ActionView
246
253
  # # <input value="New" type="submit" />
247
254
  # # </form>"
248
255
  #
249
- # <%= button_to "New", new_articles_path %>
256
+ # <%= button_to "New", new_article_path %>
250
257
  # # => "<form method="post" action="/articles/new" class="button_to">
251
258
  # # <input value="New" type="submit" />
252
259
  # # </form>"
@@ -283,7 +290,7 @@ module ActionView
283
290
  #
284
291
  #
285
292
  # <%= button_to('Destroy', 'http://www.example.com',
286
- # method: "delete", remote: true, data: { confirm: 'Are you sure?', disable_with: 'loading...' }) %>
293
+ # method: :delete, remote: true, data: { confirm: 'Are you sure?', disable_with: 'loading...' }) %>
287
294
  # # => "<form class='button_to' method='post' action='http://www.example.com' data-remote='true'>
288
295
  # # <input name='_method' value='delete' type='hidden' />
289
296
  # # <input value='Destroy' type='submit' data-disable-with='loading...' data-confirm='Are you sure?' />
@@ -301,7 +308,7 @@ module ActionView
301
308
  params = html_options.delete("params")
302
309
 
303
310
  method = html_options.delete("method").to_s
304
- method_tag = BUTTON_TAG_METHOD_VERBS.include?(method) ? method_tag(method) : "".freeze.html_safe
311
+ method_tag = BUTTON_TAG_METHOD_VERBS.include?(method) ? method_tag(method) : "".html_safe
305
312
 
306
313
  form_method = method == "get" ? "get" : "post"
307
314
  form_options = html_options.delete("form") || {}
@@ -314,7 +321,7 @@ module ActionView
314
321
  request_method = method.empty? ? "post" : method
315
322
  token_tag(nil, form_options: { action: url, method: request_method })
316
323
  else
317
- "".freeze
324
+ ""
318
325
  end
319
326
 
320
327
  html_options = convert_options_to_data_attributes(options, html_options)
@@ -405,8 +412,7 @@ module ActionView
405
412
  # Creates a link tag of the given +name+ using a URL created by the set of
406
413
  # +options+ if +condition+ is true, otherwise only the name is
407
414
  # returned. To specialize the default behavior, you can pass a block that
408
- # accepts the name or the full argument list for +link_to_unless+ (see the examples
409
- # in +link_to_unless+).
415
+ # accepts the name or the full argument list for +link_to_if+.
410
416
  #
411
417
  # ==== Examples
412
418
  # <%= link_to_if(@current_user.nil?, "Login", { controller: "sessions", action: "new" }) %>
@@ -480,12 +486,12 @@ module ActionView
480
486
  option = html_options.delete(item).presence || next
481
487
  "#{item.dasherize}=#{ERB::Util.url_encode(option)}"
482
488
  }.compact
483
- extras = extras.empty? ? "".freeze : "?" + extras.join("&")
489
+ extras = extras.empty? ? "" : "?" + extras.join("&")
484
490
 
485
491
  encoded_email_address = ERB::Util.url_encode(email_address).gsub("%40", "@")
486
492
  html_options["href"] = "mailto:#{encoded_email_address}#{extras}"
487
493
 
488
- content_tag("a".freeze, name || email_address, html_options, &block)
494
+ content_tag("a", name || email_address, html_options, &block)
489
495
  end
490
496
 
491
497
  # True if the current request URI was generated by the given +options+.
@@ -543,14 +549,14 @@ module ActionView
543
549
  return false unless request.get? || request.head?
544
550
 
545
551
  check_parameters ||= options.is_a?(Hash) && options.delete(:check_parameters)
546
- url_string = URI.parser.unescape(url_for(options)).force_encoding(Encoding::BINARY)
552
+ url_string = URI::DEFAULT_PARSER.unescape(url_for(options)).force_encoding(Encoding::BINARY)
547
553
 
548
554
  # We ignore any extra parameters in the request_uri if the
549
- # submitted url doesn't have any either. This lets the function
555
+ # submitted URL doesn't have any either. This lets the function
550
556
  # work with things like ?order=asc
551
557
  # the behaviour can be disabled with check_parameters: true
552
558
  request_uri = url_string.index("?") || check_parameters ? request.fullpath : request.path
553
- request_uri = URI.parser.unescape(request_uri).force_encoding(Encoding::BINARY)
559
+ request_uri = URI::DEFAULT_PARSER.unescape(request_uri).force_encoding(Encoding::BINARY)
554
560
 
555
561
  if url_string.start_with?("/") && url_string != "/"
556
562
  url_string.chomp!("/")
@@ -564,41 +570,153 @@ module ActionView
564
570
  end
565
571
  end
566
572
 
573
+ # Creates an SMS anchor link tag to the specified +phone_number+, which is
574
+ # also used as the name of the link unless +name+ is specified. Additional
575
+ # HTML attributes for the link can be passed in +html_options+.
576
+ #
577
+ # When clicked, an SMS message is prepopulated with the passed phone number
578
+ # and optional +body+ value.
579
+ #
580
+ # +sms_to+ has a +body+ option for customizing the SMS message itself by
581
+ # passing special keys to +html_options+.
582
+ #
583
+ # ==== Options
584
+ # * <tt>:body</tt> - Preset the body of the message.
585
+ #
586
+ # ==== Examples
587
+ # sms_to "5155555785"
588
+ # # => <a href="sms:5155555785;">5155555785</a>
589
+ #
590
+ # sms_to "5155555785", "Text me"
591
+ # # => <a href="sms:5155555785;">Text me</a>
592
+ #
593
+ # sms_to "5155555785", "Text me",
594
+ # body: "Hello Jim I have a question about your product."
595
+ # # => <a href="sms:5155555785;?body=Hello%20Jim%20I%20have%20a%20question%20about%20your%20product">Text me</a>
596
+ #
597
+ # You can use a block as well if your link target is hard to fit into the name parameter. \ERB example:
598
+ #
599
+ # <%= sms_to "5155555785" do %>
600
+ # <strong>Text me:</strong>
601
+ # <% end %>
602
+ # # => <a href="sms:5155555785;">
603
+ # <strong>Text me:</strong>
604
+ # </a>
605
+ def sms_to(phone_number, name = nil, html_options = {}, &block)
606
+ html_options, name = name, nil if block_given?
607
+ html_options = (html_options || {}).stringify_keys
608
+
609
+ extras = %w{ body }.map! { |item|
610
+ option = html_options.delete(item).presence || next
611
+ "#{item.dasherize}=#{ERB::Util.url_encode(option)}"
612
+ }.compact
613
+ extras = extras.empty? ? "" : "?&" + extras.join("&")
614
+
615
+ encoded_phone_number = ERB::Util.url_encode(phone_number)
616
+ html_options["href"] = "sms:#{encoded_phone_number};#{extras}"
617
+
618
+ content_tag("a", name || phone_number, html_options, &block)
619
+ end
620
+
621
+ # Creates a TEL anchor link tag to the specified +phone_number+, which is
622
+ # also used as the name of the link unless +name+ is specified. Additional
623
+ # HTML attributes for the link can be passed in +html_options+.
624
+ #
625
+ # When clicked, the default app to make calls is opened, and it
626
+ # is prepopulated with the passed phone number and optional
627
+ # +country_code+ value.
628
+ #
629
+ # +phone_to+ has an optional +country_code+ option which automatically adds the country
630
+ # code as well as the + sign in the phone numer that gets prepopulated,
631
+ # for example if +country_code: "01"+ +\+01+ will be prepended to the
632
+ # phone numer, by passing special keys to +html_options+.
633
+ #
634
+ # ==== Options
635
+ # * <tt>:country_code</tt> - Prepends the country code to the number
636
+ #
637
+ # ==== Examples
638
+ # phone_to "1234567890"
639
+ # # => <a href="tel:1234567890">1234567890</a>
640
+ #
641
+ # phone_to "1234567890", "Phone me"
642
+ # # => <a href="tel:134567890">Phone me</a>
643
+ #
644
+ # phone_to "1234567890", "Phone me", country_code: "01"
645
+ # # => <a href="tel:+015155555785">Phone me</a>
646
+ #
647
+ # You can use a block as well if your link target is hard to fit into the name parameter. \ERB example:
648
+ #
649
+ # <%= phone_to "1234567890" do %>
650
+ # <strong>Phone me:</strong>
651
+ # <% end %>
652
+ # # => <a href="tel:1234567890">
653
+ # <strong>Phone me:</strong>
654
+ # </a>
655
+ def phone_to(phone_number, name = nil, html_options = {}, &block)
656
+ html_options, name = name, nil if block_given?
657
+ html_options = (html_options || {}).stringify_keys
658
+
659
+ country_code = html_options.delete("country_code").presence
660
+ country_code = country_code.nil? ? "" : "+#{ERB::Util.url_encode(country_code)}"
661
+
662
+ encoded_phone_number = ERB::Util.url_encode(phone_number)
663
+ html_options["href"] = "tel:#{country_code}#{encoded_phone_number}"
664
+
665
+ content_tag("a", name || phone_number, html_options, &block)
666
+ end
667
+
567
668
  private
568
669
  def convert_options_to_data_attributes(options, html_options)
569
670
  if html_options
570
671
  html_options = html_options.stringify_keys
571
- html_options["data-remote"] = "true".freeze if link_to_remote_options?(options) || link_to_remote_options?(html_options)
672
+ html_options["data-remote"] = "true" if link_to_remote_options?(options) || link_to_remote_options?(html_options)
572
673
 
573
- method = html_options.delete("method".freeze)
674
+ method = html_options.delete("method")
574
675
 
575
676
  add_method_to_attributes!(html_options, method) if method
576
677
 
577
678
  html_options
578
679
  else
579
- link_to_remote_options?(options) ? { "data-remote" => "true".freeze } : {}
680
+ link_to_remote_options?(options) ? { "data-remote" => "true" } : {}
580
681
  end
581
682
  end
582
683
 
583
684
  def link_to_remote_options?(options)
584
685
  if options.is_a?(Hash)
585
- options.delete("remote".freeze) || options.delete(:remote)
686
+ options.delete("remote") || options.delete(:remote)
586
687
  end
587
688
  end
588
689
 
589
690
  def add_method_to_attributes!(html_options, method)
590
- if method && method.to_s.downcase != "get".freeze && html_options["rel".freeze] !~ /nofollow/
591
- html_options["rel".freeze] = "#{html_options["rel".freeze]} nofollow".lstrip
691
+ if method_not_get_method?(method) && !html_options["rel"]&.match?(/nofollow/)
692
+ if html_options["rel"].blank?
693
+ html_options["rel"] = "nofollow"
694
+ else
695
+ html_options["rel"] = "#{html_options["rel"]} nofollow"
696
+ end
592
697
  end
593
- html_options["data-method".freeze] = method
698
+ html_options["data-method"] = method
699
+ end
700
+
701
+ STRINGIFIED_COMMON_METHODS = {
702
+ get: "get",
703
+ delete: "delete",
704
+ patch: "patch",
705
+ post: "post",
706
+ put: "put",
707
+ }.freeze
708
+
709
+ def method_not_get_method?(method)
710
+ return false unless method
711
+ (STRINGIFIED_COMMON_METHODS[method] || method.to_s.downcase) != "get"
594
712
  end
595
713
 
596
714
  def token_tag(token = nil, form_options: {})
597
- if token != false && protect_against_forgery?
715
+ if token != false && defined?(protect_against_forgery?) && protect_against_forgery?
598
716
  token ||= form_authenticity_token(form_options: form_options)
599
717
  tag(:input, type: "hidden", name: request_forgery_protection_token.to_s, value: token)
600
718
  else
601
- "".freeze
719
+ ""
602
720
  end
603
721
  end
604
722
 
@@ -610,9 +728,9 @@ module ActionView
610
728
  # suitable for use as the names and values of form input fields:
611
729
  #
612
730
  # to_form_params(name: 'David', nationality: 'Danish')
613
- # # => [{name: :name, value: 'David'}, {name: 'nationality', value: 'Danish'}]
731
+ # # => [{name: 'name', value: 'David'}, {name: 'nationality', value: 'Danish'}]
614
732
  #
615
- # to_form_params(country: {name: 'Denmark'})
733
+ # to_form_params(country: { name: 'Denmark' })
616
734
  # # => [{name: 'country[name]', value: 'Denmark'}]
617
735
  #
618
736
  # to_form_params(countries: ['Denmark', 'Sweden']})
@@ -642,7 +760,7 @@ module ActionView
642
760
  params.push(*to_form_params(value, array_prefix))
643
761
  end
644
762
  else
645
- params << { name: namespace, value: attribute.to_param }
763
+ params << { name: namespace.to_s, value: attribute.to_param }
646
764
  end
647
765
 
648
766
  params.sort_by { |pair| pair[:name] }
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "action_view/rendering"
2
- require "active_support/core_ext/module/remove_method"
4
+ require "active_support/core_ext/module/redefine_method"
3
5
 
4
6
  module ActionView
5
7
  # Layouts reverse the common pattern of including shared headers and footers in many templates to isolate changes in
@@ -204,9 +206,9 @@ module ActionView
204
206
  include ActionView::Rendering
205
207
 
206
208
  included do
207
- class_attribute :_layout, :_layout_conditions, instance_accessor: false
208
- self._layout = nil
209
- self._layout_conditions = {}
209
+ class_attribute :_layout, instance_accessor: false
210
+ class_attribute :_layout_conditions, instance_accessor: false, default: {}
211
+
210
212
  _write_layout_method
211
213
  end
212
214
 
@@ -222,7 +224,6 @@ module ActionView
222
224
  # that if no layout conditions are used, this method is not used
223
225
  module LayoutConditions # :nodoc:
224
226
  private
225
-
226
227
  # Determines whether the current action has a layout definition by
227
228
  # checking the action name against the :only and :except conditions
228
229
  # set by the <tt>layout</tt> method.
@@ -277,7 +278,7 @@ module ActionView
277
278
  # If a layout is not explicitly mentioned then look for a layout with the controller's name.
278
279
  # if nothing is found then try same procedure to find super class's layout.
279
280
  def _write_layout_method # :nodoc:
280
- remove_possible_method(:_layout)
281
+ silence_redefinition_of_method(:_layout)
281
282
 
282
283
  prefixes = /\blayouts/.match?(_implied_layout_name) ? [] : ["layouts"]
283
284
  default_behavior = "lookup_context.find_all('#{_implied_layout_name}', #{prefixes.inspect}, false, [], { formats: formats }).first || super"
@@ -305,7 +306,7 @@ module ActionView
305
306
  RUBY
306
307
  when Proc
307
308
  define_method :_layout_from_proc, &_layout
308
- protected :_layout_from_proc
309
+ private :_layout_from_proc
309
310
  <<-RUBY
310
311
  result = _layout_from_proc(#{_layout.arity == 0 ? '' : 'self'})
311
312
  return #{default_behavior} if result.nil?
@@ -320,7 +321,8 @@ module ActionView
320
321
  end
321
322
 
322
323
  class_eval <<-RUBY, __FILE__, __LINE__ + 1
323
- def _layout(formats)
324
+ # frozen_string_literal: true
325
+ def _layout(lookup_context, formats)
324
326
  if _conditional_layout?
325
327
  #{layout_definition}
326
328
  else
@@ -332,7 +334,6 @@ module ActionView
332
334
  end
333
335
 
334
336
  private
335
-
336
337
  # If no layout is supplied, look for a template named the return
337
338
  # value of this method.
338
339
  #
@@ -370,7 +371,6 @@ module ActionView
370
371
  end
371
372
 
372
373
  private
373
-
374
374
  def _conditional_layout?
375
375
  true
376
376
  end
@@ -386,8 +386,8 @@ module ActionView
386
386
  case name
387
387
  when String then _normalize_layout(name)
388
388
  when Proc then name
389
- when true then Proc.new { |formats| _default_layout(formats, true) }
390
- when :default then Proc.new { |formats| _default_layout(formats, false) }
389
+ when true then Proc.new { |lookup_context, formats| _default_layout(lookup_context, formats, true) }
390
+ when :default then Proc.new { |lookup_context, formats| _default_layout(lookup_context, formats, false) }
391
391
  when false, nil then nil
392
392
  else
393
393
  raise ArgumentError,
@@ -396,7 +396,7 @@ module ActionView
396
396
  end
397
397
 
398
398
  def _normalize_layout(value)
399
- value.is_a?(String) && value !~ /\blayouts/ ? "layouts/#{value}" : value
399
+ value.is_a?(String) && !value.match?(/\blayouts/) ? "layouts/#{value}" : value
400
400
  end
401
401
 
402
402
  # Returns the default layout for this controller.
@@ -409,9 +409,9 @@ module ActionView
409
409
  #
410
410
  # ==== Returns
411
411
  # * <tt>template</tt> - The template object for the default layout (or +nil+)
412
- def _default_layout(formats, require_layout = false)
412
+ def _default_layout(lookup_context, formats, require_layout = false)
413
413
  begin
414
- value = _layout(formats) if action_has_layout?
414
+ value = _layout(lookup_context, formats) if action_has_layout?
415
415
  rescue NameError => e
416
416
  raise e, "Could not render layout: #{e.message}"
417
417
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/log_subscriber"
2
4
 
3
5
  module ActionView
@@ -14,35 +16,42 @@ module ActionView
14
16
 
15
17
  def render_template(event)
16
18
  info do
17
- message = " Rendered #{from_rails_root(event.payload[:identifier])}"
19
+ message = +" Rendered #{from_rails_root(event.payload[:identifier])}"
18
20
  message << " within #{from_rails_root(event.payload[:layout])}" if event.payload[:layout]
19
- message << " (#{event.duration.round(1)}ms)"
21
+ message << " (Duration: #{event.duration.round(1)}ms | Allocations: #{event.allocations})"
20
22
  end
21
23
  end
22
24
 
23
25
  def render_partial(event)
24
- info do
25
- message = " Rendered #{from_rails_root(event.payload[:identifier])}"
26
+ debug do
27
+ message = +" Rendered #{from_rails_root(event.payload[:identifier])}"
26
28
  message << " within #{from_rails_root(event.payload[:layout])}" if event.payload[:layout]
27
- message << " (#{event.duration.round(1)}ms)"
29
+ message << " (Duration: #{event.duration.round(1)}ms | Allocations: #{event.allocations})"
28
30
  message << " #{cache_message(event.payload)}" unless event.payload[:cache_hit].nil?
29
31
  message
30
32
  end
31
33
  end
32
34
 
35
+ def render_layout(event)
36
+ info do
37
+ message = +" Rendered layout #{from_rails_root(event.payload[:identifier])}"
38
+ message << " (Duration: #{event.duration.round(1)}ms | Allocations: #{event.allocations})"
39
+ end
40
+ end
41
+
33
42
  def render_collection(event)
34
43
  identifier = event.payload[:identifier] || "templates"
35
44
 
36
- info do
37
- " Rendered collection of #{from_rails_root(identifier)}" \
38
- " #{render_count(event.payload)} (#{event.duration.round(1)}ms)"
45
+ debug do
46
+ message = +" Rendered collection of #{from_rails_root(identifier)}"
47
+ message << " within #{from_rails_root(event.payload[:layout])}" if event.payload[:layout]
48
+ message << " #{render_count(event.payload)} (Duration: #{event.duration.round(1)}ms | Allocations: #{event.allocations})"
49
+ message
39
50
  end
40
51
  end
41
52
 
42
53
  def start(name, id, payload)
43
- if name == "render_template.action_view"
44
- log_rendering_start(payload)
45
- end
54
+ log_rendering_start(payload, name)
46
55
 
47
56
  super
48
57
  end
@@ -52,7 +61,6 @@ module ActionView
52
61
  end
53
62
 
54
63
  private
55
-
56
64
  EMPTY = ""
57
65
  def from_rails_root(string) # :doc:
58
66
  string = string.sub(rails_root, EMPTY)
@@ -81,9 +89,18 @@ module ActionView
81
89
  end
82
90
  end
83
91
 
84
- def log_rendering_start(payload)
85
- info do
86
- message = " Rendering #{from_rails_root(payload[:identifier])}"
92
+ def log_rendering_start(payload, name)
93
+ debug do
94
+ qualifier =
95
+ if name == "render_template.action_view"
96
+ ""
97
+ elsif name == "render_layout.action_view"
98
+ "layout "
99
+ end
100
+
101
+ return unless qualifier
102
+
103
+ message = +" Rendering #{qualifier}#{from_rails_root(payload[:identifier])}"
87
104
  message << " within #{from_rails_root(payload[:layout])}" if payload[:layout]
88
105
  message
89
106
  end