actionview 5.2.8.1 → 6.0.0.beta2

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.

Potentially problematic release.


This version of actionview might be problematic. Click here for more details.

Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +121 -152
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/lib/action_view/base.rb +107 -10
  6. data/lib/action_view/buffers.rb +15 -0
  7. data/lib/action_view/context.rb +5 -9
  8. data/lib/action_view/digestor.rb +8 -11
  9. data/lib/action_view/file_template.rb +33 -0
  10. data/lib/action_view/gem_version.rb +4 -4
  11. data/lib/action_view/helpers/asset_tag_helper.rb +7 -30
  12. data/lib/action_view/helpers/asset_url_helper.rb +4 -3
  13. data/lib/action_view/helpers/cache_helper.rb +18 -10
  14. data/lib/action_view/helpers/capture_helper.rb +4 -0
  15. data/lib/action_view/helpers/csp_helper.rb +4 -2
  16. data/lib/action_view/helpers/csrf_helper.rb +1 -1
  17. data/lib/action_view/helpers/date_helper.rb +69 -25
  18. data/lib/action_view/helpers/form_helper.rb +240 -8
  19. data/lib/action_view/helpers/form_options_helper.rb +23 -15
  20. data/lib/action_view/helpers/form_tag_helper.rb +9 -9
  21. data/lib/action_view/helpers/javascript_helper.rb +10 -11
  22. data/lib/action_view/helpers/number_helper.rb +5 -0
  23. data/lib/action_view/helpers/rendering_helper.rb +6 -4
  24. data/lib/action_view/helpers/sanitize_helper.rb +3 -3
  25. data/lib/action_view/helpers/tag_helper.rb +13 -43
  26. data/lib/action_view/helpers/tags/base.rb +9 -5
  27. data/lib/action_view/helpers/tags/color_field.rb +1 -1
  28. data/lib/action_view/helpers/tags/translator.rb +1 -6
  29. data/lib/action_view/helpers/text_helper.rb +3 -3
  30. data/lib/action_view/helpers/translation_helper.rb +12 -19
  31. data/lib/action_view/helpers/url_helper.rb +14 -14
  32. data/lib/action_view/helpers.rb +0 -2
  33. data/lib/action_view/layouts.rb +5 -5
  34. data/lib/action_view/log_subscriber.rb +6 -6
  35. data/lib/action_view/lookup_context.rb +63 -28
  36. data/lib/action_view/railtie.rb +23 -0
  37. data/lib/action_view/record_identifier.rb +2 -2
  38. data/lib/action_view/renderer/abstract_renderer.rb +56 -3
  39. data/lib/action_view/renderer/partial_renderer/collection_caching.rb +49 -10
  40. data/lib/action_view/renderer/partial_renderer.rb +66 -52
  41. data/lib/action_view/renderer/renderer.rb +16 -4
  42. data/lib/action_view/renderer/streaming_template_renderer.rb +4 -4
  43. data/lib/action_view/renderer/template_renderer.rb +18 -18
  44. data/lib/action_view/rendering.rb +49 -30
  45. data/lib/action_view/routing_url_for.rb +12 -11
  46. data/lib/action_view/template/handlers/builder.rb +2 -2
  47. data/lib/action_view/template/handlers/erb/erubi.rb +7 -3
  48. data/lib/action_view/template/handlers/erb.rb +17 -7
  49. data/lib/action_view/template/handlers/html.rb +1 -1
  50. data/lib/action_view/template/handlers/raw.rb +2 -2
  51. data/lib/action_view/template/handlers.rb +27 -1
  52. data/lib/action_view/template/html.rb +14 -5
  53. data/lib/action_view/template/inline.rb +22 -0
  54. data/lib/action_view/template/resolver.rb +70 -23
  55. data/lib/action_view/template/text.rb +5 -3
  56. data/lib/action_view/template.rb +75 -36
  57. data/lib/action_view/test_case.rb +1 -1
  58. data/lib/action_view/testing/resolvers.rb +7 -5
  59. data/lib/action_view/view_paths.rb +25 -1
  60. data/lib/action_view.rb +2 -2
  61. data/lib/assets/compiled/rails-ujs.js +39 -22
  62. metadata +19 -18
  63. data/lib/action_view/helpers/record_tag_helper.rb +0 -23
@@ -590,6 +590,9 @@ module ActionView
590
590
  # Skipped if a <tt>:url</tt> is passed.
591
591
  # * <tt>:scope</tt> - The scope to prefix input field names with and
592
592
  # thereby how the submitted parameters are grouped in controllers.
593
+ # * <tt>:namespace</tt> - A namespace for your form to ensure uniqueness of
594
+ # id attributes on form elements. The namespace attribute will be prefixed
595
+ # with underscore on the generated HTML id.
593
596
  # * <tt>:model</tt> - A model object to infer the <tt>:url</tt> and
594
597
  # <tt>:scope</tt> by, plus fill out input field values.
595
598
  # So if a +title+ attribute is set to "Ahoy!" then a +title+ input
@@ -610,8 +613,8 @@ module ActionView
610
613
  # unnecessary unless you support browsers without JavaScript.
611
614
  # * <tt>:local</tt> - By default form submits are remote and unobtrusive XHRs.
612
615
  # Disable remote submits with <tt>local: true</tt>.
613
- # * <tt>:skip_enforcing_utf8</tt> - By default a hidden field named +utf8+
614
- # is output to enforce UTF-8 submits. Set to true to skip the field.
616
+ # * <tt>:skip_enforcing_utf8</tt> - If set to true, a hidden input with name
617
+ # utf8 is not output.
615
618
  # * <tt>:builder</tt> - Override the object used to build the form.
616
619
  # * <tt>:id</tt> - Optional HTML id attribute.
617
620
  # * <tt>:class</tt> - Optional HTML class attribute.
@@ -736,7 +739,7 @@ module ActionView
736
739
  # def labelled_form_with(**options, &block)
737
740
  # form_with(**options.merge(builder: LabellingFormBuilder), &block)
738
741
  # end
739
- def form_with(model: nil, scope: nil, url: nil, format: nil, **options, &block)
742
+ def form_with(model: nil, scope: nil, url: nil, format: nil, **options)
740
743
  options[:allow_method_names_outside_object] = true
741
744
  options[:skip_default_ids] = !form_with_generates_ids
742
745
 
@@ -749,7 +752,7 @@ module ActionView
749
752
 
750
753
  if block_given?
751
754
  builder = instantiate_builder(scope, model, options)
752
- output = capture(builder, &block)
755
+ output = capture(builder, &Proc.new)
753
756
  options[:multipart] ||= builder.multipart?
754
757
 
755
758
  html_options = html_options_for_form_with(url, model, options)
@@ -1127,6 +1130,9 @@ module ActionView
1127
1130
  # text_field(:post, :title, class: "create_input")
1128
1131
  # # => <input type="text" id="post_title" name="post[title]" value="#{@post.title}" class="create_input" />
1129
1132
  #
1133
+ # text_field(:post, :title, maxlength: 30, class: "title_input")
1134
+ # # => <input type="text" id="post_title" name="post[title]" maxlength="30" size="30" value="#{@post.title}" class="title_input" />
1135
+ #
1130
1136
  # text_field(:session, :user, onchange: "if ($('#session_user').val() === 'admin') { alert('Your login cannot be admin!'); }")
1131
1137
  # # => <input type="text" id="session_user" name="session[user]" value="#{@session.user}" onchange="if ($('#session_user').val() === 'admin') { alert('Your login cannot be admin!'); }"/>
1132
1138
  #
@@ -1519,10 +1525,10 @@ module ActionView
1519
1525
 
1520
1526
  private
1521
1527
  def html_options_for_form_with(url_for_options = nil, model = nil, html: {}, local: !form_with_generates_remote_forms,
1522
- skip_enforcing_utf8: false, **options)
1528
+ skip_enforcing_utf8: nil, **options)
1523
1529
  html_options = options.slice(:id, :class, :multipart, :method, :data).merge(html)
1524
1530
  html_options[:method] ||= :patch if model.respond_to?(:persisted?) && model.persisted?
1525
- html_options[:enforce_utf8] = !skip_enforcing_utf8
1531
+ html_options[:enforce_utf8] = !skip_enforcing_utf8 unless skip_enforcing_utf8.nil?
1526
1532
 
1527
1533
  html_options[:enctype] = "multipart/form-data" if html_options.delete(:multipart)
1528
1534
 
@@ -1674,6 +1680,227 @@ module ActionView
1674
1680
  @index = options[:index] || options[:child_index]
1675
1681
  end
1676
1682
 
1683
+ ##
1684
+ # :method: text_field
1685
+ #
1686
+ # :call-seq: text_field(method, options = {})
1687
+ #
1688
+ # Wraps ActionView::Helpers::FormHelper#text_field for form builders:
1689
+ #
1690
+ # <%= form_with model: @user do |f| %>
1691
+ # <%= f.text_field :name %>
1692
+ # <% end %>
1693
+ #
1694
+ # Please refer to the documentation of the base helper for details.
1695
+
1696
+ ##
1697
+ # :method: password_field
1698
+ #
1699
+ # :call-seq: password_field(method, options = {})
1700
+ #
1701
+ # Wraps ActionView::Helpers::FormHelper#password_field for form builders:
1702
+ #
1703
+ # <%= form_with model: @user do |f| %>
1704
+ # <%= f.password_field :password %>
1705
+ # <% end %>
1706
+ #
1707
+ # Please refer to the documentation of the base helper for details.
1708
+
1709
+ ##
1710
+ # :method: text_area
1711
+ #
1712
+ # :call-seq: text_area(method, options = {})
1713
+ #
1714
+ # Wraps ActionView::Helpers::FormHelper#text_area for form builders:
1715
+ #
1716
+ # <%= form_with model: @user do |f| %>
1717
+ # <%= f.text_area :detail %>
1718
+ # <% end %>
1719
+ #
1720
+ # Please refer to the documentation of the base helper for details.
1721
+
1722
+ ##
1723
+ # :method: color_field
1724
+ #
1725
+ # :call-seq: color_field(method, options = {})
1726
+ #
1727
+ # Wraps ActionView::Helpers::FormHelper#color_field for form builders:
1728
+ #
1729
+ # <%= form_with model: @user do |f| %>
1730
+ # <%= f.color_field :favorite_color %>
1731
+ # <% end %>
1732
+ #
1733
+ # Please refer to the documentation of the base helper for details.
1734
+
1735
+ ##
1736
+ # :method: search_field
1737
+ #
1738
+ # :call-seq: search_field(method, options = {})
1739
+ #
1740
+ # Wraps ActionView::Helpers::FormHelper#search_field for form builders:
1741
+ #
1742
+ # <%= form_with model: @user do |f| %>
1743
+ # <%= f.search_field :name %>
1744
+ # <% end %>
1745
+ #
1746
+ # Please refer to the documentation of the base helper for details.
1747
+
1748
+ ##
1749
+ # :method: telephone_field
1750
+ #
1751
+ # :call-seq: telephone_field(method, options = {})
1752
+ #
1753
+ # Wraps ActionView::Helpers::FormHelper#telephone_field for form builders:
1754
+ #
1755
+ # <%= form_with model: @user do |f| %>
1756
+ # <%= f.telephone_field :phone %>
1757
+ # <% end %>
1758
+ #
1759
+ # Please refer to the documentation of the base helper for details.
1760
+
1761
+ ##
1762
+ # :method: phone_field
1763
+ #
1764
+ # :call-seq: phone_field(method, options = {})
1765
+ #
1766
+ # Wraps ActionView::Helpers::FormHelper#phone_field for form builders:
1767
+ #
1768
+ # <%= form_with model: @user do |f| %>
1769
+ # <%= f.phone_field :phone %>
1770
+ # <% end %>
1771
+ #
1772
+ # Please refer to the documentation of the base helper for details.
1773
+
1774
+ ##
1775
+ # :method: date_field
1776
+ #
1777
+ # :call-seq: date_field(method, options = {})
1778
+ #
1779
+ # Wraps ActionView::Helpers::FormHelper#date_field for form builders:
1780
+ #
1781
+ # <%= form_with model: @user do |f| %>
1782
+ # <%= f.date_field :born_on %>
1783
+ # <% end %>
1784
+ #
1785
+ # Please refer to the documentation of the base helper for details.
1786
+
1787
+ ##
1788
+ # :method: time_field
1789
+ #
1790
+ # :call-seq: time_field(method, options = {})
1791
+ #
1792
+ # Wraps ActionView::Helpers::FormHelper#time_field for form builders:
1793
+ #
1794
+ # <%= form_with model: @user do |f| %>
1795
+ # <%= f.time_field :borned_at %>
1796
+ # <% end %>
1797
+ #
1798
+ # Please refer to the documentation of the base helper for details.
1799
+
1800
+ ##
1801
+ # :method: datetime_field
1802
+ #
1803
+ # :call-seq: datetime_field(method, options = {})
1804
+ #
1805
+ # Wraps ActionView::Helpers::FormHelper#datetime_field for form builders:
1806
+ #
1807
+ # <%= form_with model: @user do |f| %>
1808
+ # <%= f.datetime_field :graduation_day %>
1809
+ # <% end %>
1810
+ #
1811
+ # Please refer to the documentation of the base helper for details.
1812
+
1813
+ ##
1814
+ # :method: datetime_local_field
1815
+ #
1816
+ # :call-seq: datetime_local_field(method, options = {})
1817
+ #
1818
+ # Wraps ActionView::Helpers::FormHelper#datetime_local_field for form builders:
1819
+ #
1820
+ # <%= form_with model: @user do |f| %>
1821
+ # <%= f.datetime_local_field :graduation_day %>
1822
+ # <% end %>
1823
+ #
1824
+ # Please refer to the documentation of the base helper for details.
1825
+
1826
+ ##
1827
+ # :method: month_field
1828
+ #
1829
+ # :call-seq: month_field(method, options = {})
1830
+ #
1831
+ # Wraps ActionView::Helpers::FormHelper#month_field for form builders:
1832
+ #
1833
+ # <%= form_with model: @user do |f| %>
1834
+ # <%= f.month_field :birthday_month %>
1835
+ # <% end %>
1836
+ #
1837
+ # Please refer to the documentation of the base helper for details.
1838
+
1839
+ ##
1840
+ # :method: week_field
1841
+ #
1842
+ # :call-seq: week_field(method, options = {})
1843
+ #
1844
+ # Wraps ActionView::Helpers::FormHelper#week_field for form builders:
1845
+ #
1846
+ # <%= form_with model: @user do |f| %>
1847
+ # <%= f.week_field :birthday_week %>
1848
+ # <% end %>
1849
+ #
1850
+ # Please refer to the documentation of the base helper for details.
1851
+
1852
+ ##
1853
+ # :method: url_field
1854
+ #
1855
+ # :call-seq: url_field(method, options = {})
1856
+ #
1857
+ # Wraps ActionView::Helpers::FormHelper#url_field for form builders:
1858
+ #
1859
+ # <%= form_with model: @user do |f| %>
1860
+ # <%= f.url_field :homepage %>
1861
+ # <% end %>
1862
+ #
1863
+ # Please refer to the documentation of the base helper for details.
1864
+
1865
+ ##
1866
+ # :method: email_field
1867
+ #
1868
+ # :call-seq: email_field(method, options = {})
1869
+ #
1870
+ # Wraps ActionView::Helpers::FormHelper#email_field for form builders:
1871
+ #
1872
+ # <%= form_with model: @user do |f| %>
1873
+ # <%= f.email_field :address %>
1874
+ # <% end %>
1875
+ #
1876
+ # Please refer to the documentation of the base helper for details.
1877
+
1878
+ ##
1879
+ # :method: number_field
1880
+ #
1881
+ # :call-seq: number_field(method, options = {})
1882
+ #
1883
+ # Wraps ActionView::Helpers::FormHelper#number_field for form builders:
1884
+ #
1885
+ # <%= form_with model: @user do |f| %>
1886
+ # <%= f.number_field :age %>
1887
+ # <% end %>
1888
+ #
1889
+ # Please refer to the documentation of the base helper for details.
1890
+
1891
+ ##
1892
+ # :method: range_field
1893
+ #
1894
+ # :call-seq: range_field(method, options = {})
1895
+ #
1896
+ # Wraps ActionView::Helpers::FormHelper#range_field for form builders:
1897
+ #
1898
+ # <%= form_with model: @user do |f| %>
1899
+ # <%= f.range_field :age %>
1900
+ # <% end %>
1901
+ #
1902
+ # Please refer to the documentation of the base helper for details.
1903
+
1677
1904
  (field_helpers - [:label, :check_box, :radio_button, :fields_for, :fields, :hidden_field, :file_field]).each do |selector|
1678
1905
  class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
1679
1906
  def #{selector}(method, options = {}) # def text_field(method, options = {})
@@ -2247,7 +2474,7 @@ module ActionView
2247
2474
  @template.button_tag(value, options, &block)
2248
2475
  end
2249
2476
 
2250
- def emitted_hidden_id?
2477
+ def emitted_hidden_id? # :nodoc:
2251
2478
  @emitted_hidden_id ||= nil
2252
2479
  end
2253
2480
 
@@ -2267,7 +2494,12 @@ module ActionView
2267
2494
  end
2268
2495
 
2269
2496
  defaults = []
2270
- defaults << :"helpers.submit.#{object_name}.#{key}"
2497
+ # Object is a model and it is not overwritten by as and scope option.
2498
+ if object.respond_to?(:model_name) && object_name.to_s == model.downcase
2499
+ defaults << :"helpers.submit.#{object.model_name.i18n_key}.#{key}"
2500
+ else
2501
+ defaults << :"helpers.submit.#{object_name}.#{key}"
2502
+ end
2271
2503
  defaults << :"helpers.submit.#{key}"
2272
2504
  defaults << "#{key.to_s.humanize} #{model}"
2273
2505
 
@@ -16,7 +16,7 @@ module ActionView
16
16
  #
17
17
  # * <tt>:include_blank</tt> - set to true or a prompt string if the first option element of the select element is a blank. Useful if there is not a default value required for the select element.
18
18
  #
19
- # select("post", "category", Post::CATEGORIES, {include_blank: true})
19
+ # select("post", "category", Post::CATEGORIES, { include_blank: true })
20
20
  #
21
21
  # could become:
22
22
  #
@@ -30,7 +30,7 @@ module ActionView
30
30
  #
31
31
  # Example with <tt>@post.person_id => 2</tt>:
32
32
  #
33
- # select("post", "person_id", Person.all.collect {|p| [ p.name, p.id ] }, {include_blank: 'None'})
33
+ # select("post", "person_id", Person.all.collect { |p| [ p.name, p.id ] }, { include_blank: 'None' })
34
34
  #
35
35
  # could become:
36
36
  #
@@ -43,7 +43,7 @@ module ActionView
43
43
  #
44
44
  # * <tt>:prompt</tt> - set to true or a prompt string. When the select element doesn't have a value yet, this prepends an option with a generic prompt -- "Please select" -- or the given prompt string.
45
45
  #
46
- # select("post", "person_id", Person.all.collect {|p| [ p.name, p.id ] }, {prompt: 'Select Person'})
46
+ # select("post", "person_id", Person.all.collect { |p| [ p.name, p.id ] }, { prompt: 'Select Person' })
47
47
  #
48
48
  # could become:
49
49
  #
@@ -69,7 +69,7 @@ module ActionView
69
69
  #
70
70
  # * <tt>:disabled</tt> - can be a single value or an array of values that will be disabled options in the final output.
71
71
  #
72
- # select("post", "category", Post::CATEGORIES, {disabled: 'restricted'})
72
+ # select("post", "category", Post::CATEGORIES, { disabled: 'restricted' })
73
73
  #
74
74
  # could become:
75
75
  #
@@ -82,7 +82,7 @@ module ActionView
82
82
  #
83
83
  # When used with the <tt>collection_select</tt> helper, <tt>:disabled</tt> can also be a Proc that identifies those options that should be disabled.
84
84
  #
85
- # collection_select(:post, :category_id, Category.all, :id, :name, {disabled: -> (category) { category.archived? }})
85
+ # collection_select(:post, :category_id, Category.all, :id, :name, { disabled: -> (category) { category.archived? } })
86
86
  #
87
87
  # If the categories "2008 stuff" and "Christmas" return true when the method <tt>archived?</tt> is called, this would return:
88
88
  # <select name="post[category_id]" id="post_category_id">
@@ -107,7 +107,7 @@ module ActionView
107
107
  #
108
108
  # For example:
109
109
  #
110
- # select("post", "person_id", Person.all.collect {|p| [ p.name, p.id ] }, { include_blank: true })
110
+ # select("post", "person_id", Person.all.collect { |p| [ p.name, p.id ] }, { include_blank: true })
111
111
  #
112
112
  # would become:
113
113
  #
@@ -323,12 +323,12 @@ module ActionView
323
323
  #
324
324
  # You can optionally provide HTML attributes as the last element of the array.
325
325
  #
326
- # options_for_select([ "Denmark", ["USA", {class: 'bold'}], "Sweden" ], ["USA", "Sweden"])
326
+ # options_for_select([ "Denmark", ["USA", { class: 'bold' }], "Sweden" ], ["USA", "Sweden"])
327
327
  # # => <option value="Denmark">Denmark</option>
328
328
  # # => <option value="USA" class="bold" selected="selected">USA</option>
329
329
  # # => <option value="Sweden" selected="selected">Sweden</option>
330
330
  #
331
- # options_for_select([["Dollar", "$", {class: "bold"}], ["Kroner", "DKK", {onclick: "alert('HI');"}]])
331
+ # options_for_select([["Dollar", "$", { class: "bold" }], ["Kroner", "DKK", { onclick: "alert('HI');" }]])
332
332
  # # => <option value="$" class="bold">Dollar</option>
333
333
  # # => <option value="DKK" onclick="alert('HI');">Kroner</option>
334
334
  #
@@ -463,7 +463,7 @@ module ActionView
463
463
  option_tags = options_from_collection_for_select(
464
464
  value_for_collection(group, group_method), option_key_method, option_value_method, selected_key)
465
465
 
466
- content_tag("optgroup".freeze, option_tags, label: value_for_collection(group, group_label_method))
466
+ content_tag("optgroup", option_tags, label: value_for_collection(group, group_label_method))
467
467
  end.join.html_safe
468
468
  end
469
469
 
@@ -535,7 +535,7 @@ module ActionView
535
535
  body = "".html_safe
536
536
 
537
537
  if prompt
538
- body.safe_concat content_tag("option".freeze, prompt_text(prompt), value: "")
538
+ body.safe_concat content_tag("option", prompt_text(prompt), value: "")
539
539
  end
540
540
 
541
541
  grouped_options.each do |container|
@@ -548,7 +548,7 @@ module ActionView
548
548
  end
549
549
 
550
550
  html_attributes = { label: label }.merge!(html_attributes)
551
- body.safe_concat content_tag("optgroup".freeze, options_for_select(container, selected_key), html_attributes)
551
+ body.safe_concat content_tag("optgroup", options_for_select(container, selected_key), html_attributes)
552
552
  end
553
553
 
554
554
  body
@@ -584,7 +584,7 @@ module ActionView
584
584
  end
585
585
 
586
586
  zone_options.safe_concat options_for_select(convert_zones[priority_zones], selected)
587
- zone_options.safe_concat content_tag("option".freeze, "-------------", value: "", disabled: true)
587
+ zone_options.safe_concat content_tag("option", "-------------", value: "", disabled: true)
588
588
  zone_options.safe_concat "\n"
589
589
 
590
590
  zones = zones - priority_zones
@@ -654,7 +654,7 @@ module ActionView
654
654
  #
655
655
  # ==== Gotcha
656
656
  #
657
- # The HTML specification says when nothing is select on a collection of radio buttons
657
+ # The HTML specification says when nothing is selected on a collection of radio buttons
658
658
  # web browsers do not send any value to server.
659
659
  # Unfortunately this introduces a gotcha:
660
660
  # if a +User+ model has a +category_id+ field and in the form no category is selected, no +category_id+ parameter is sent. So,
@@ -794,7 +794,7 @@ module ActionView
794
794
  def extract_values_from_collection(collection, value_method, selected)
795
795
  if selected.is_a?(Proc)
796
796
  collection.map do |element|
797
- element.send(value_method) if selected.call(element)
797
+ public_or_deprecated_send(element, value_method) if selected.call(element)
798
798
  end.compact
799
799
  else
800
800
  selected
@@ -802,7 +802,15 @@ module ActionView
802
802
  end
803
803
 
804
804
  def value_for_collection(item, value)
805
- value.respond_to?(:call) ? value.call(item) : item.send(value)
805
+ value.respond_to?(:call) ? value.call(item) : public_or_deprecated_send(item, value)
806
+ end
807
+
808
+ def public_or_deprecated_send(item, value)
809
+ item.public_send(value)
810
+ rescue NoMethodError
811
+ raise unless item.respond_to?(value, true) && !item.respond_to?(value)
812
+ ActiveSupport::Deprecation.warn "Using private methods from view helpers is deprecated (calling private #{item.class}##{value})"
813
+ item.send(value)
806
814
  end
807
815
 
808
816
  def prompt_text(prompt)
@@ -22,6 +22,8 @@ module ActionView
22
22
  mattr_accessor :embed_authenticity_token_in_remote_forms
23
23
  self.embed_authenticity_token_in_remote_forms = nil
24
24
 
25
+ mattr_accessor :default_enforce_utf8, default: true
26
+
25
27
  # Starts a form tag that points the action to a url configured with <tt>url_for_options</tt> just like
26
28
  # ActionController::Base#url_for. The method for the form defaults to POST.
27
29
  #
@@ -144,15 +146,15 @@ module ActionView
144
146
  end
145
147
 
146
148
  if include_blank
147
- option_tags = content_tag("option".freeze, include_blank, options_for_blank_options_tag).safe_concat(option_tags)
149
+ option_tags = content_tag("option", include_blank, options_for_blank_options_tag).safe_concat(option_tags)
148
150
  end
149
151
  end
150
152
 
151
153
  if prompt = options.delete(:prompt)
152
- option_tags = content_tag("option".freeze, prompt, value: "").safe_concat(option_tags)
154
+ option_tags = content_tag("option", prompt, value: "").safe_concat(option_tags)
153
155
  end
154
156
 
155
- content_tag "select".freeze, option_tags, { "name" => html_name, "id" => sanitize_to_id(name) }.update(options.stringify_keys)
157
+ content_tag "select", option_tags, { "name" => html_name, "id" => sanitize_to_id(name) }.update(options.stringify_keys)
156
158
  end
157
159
 
158
160
  # Creates a standard text field; use these text fields to input smaller chunks of text like a username
@@ -163,8 +165,6 @@ module ActionView
163
165
  # * <tt>:size</tt> - The number of visible characters that will fit in the input.
164
166
  # * <tt>:maxlength</tt> - The maximum number of characters that the browser will allow the user to enter.
165
167
  # * <tt>:placeholder</tt> - The text contained in the field by default which is removed when the field receives focus.
166
- # If set to true, use a translation is found in the current I18n locale
167
- # (through helpers.placeholders.<modelname>.<attribute>).
168
168
  # * Any other key creates standard HTML attributes for the tag.
169
169
  #
170
170
  # ==== Examples
@@ -389,8 +389,8 @@ module ActionView
389
389
  # * Any other key creates standard HTML options for the tag.
390
390
  #
391
391
  # ==== Examples
392
- # radio_button_tag 'gender', 'male'
393
- # # => <input id="gender_male" name="gender" type="radio" value="male" />
392
+ # radio_button_tag 'favorite_color', 'maroon'
393
+ # # => <input id="favorite_color_maroon" name="favorite_color" type="radio" value="maroon" />
394
394
  #
395
395
  # radio_button_tag 'receive_updates', 'no', true
396
396
  # # => <input checked="checked" id="receive_updates_no" name="receive_updates" type="radio" value="no" />
@@ -577,7 +577,7 @@ module ActionView
577
577
  # # => <fieldset class="format"><p><input id="name" name="name" type="text" /></p></fieldset>
578
578
  def field_set_tag(legend = nil, options = nil, &block)
579
579
  output = tag(:fieldset, options, true)
580
- output.safe_concat(content_tag("legend".freeze, legend)) unless legend.blank?
580
+ output.safe_concat(content_tag("legend", legend)) unless legend.blank?
581
581
  output.concat(capture(&block)) if block_given?
582
582
  output.safe_concat("</fieldset>")
583
583
  end
@@ -869,7 +869,7 @@ module ActionView
869
869
  })
870
870
  end
871
871
 
872
- if html_options.delete("enforce_utf8") { true }
872
+ if html_options.delete("enforce_utf8") { default_enforce_utf8 }
873
873
  utf8_enforcer_tag + method_tag
874
874
  else
875
875
  method_tag
@@ -12,13 +12,11 @@ module ActionView
12
12
  "\n" => '\n',
13
13
  "\r" => '\n',
14
14
  '"' => '\\"',
15
- "'" => "\\'",
16
- "`" => "\\`",
17
- "$" => "\\$"
15
+ "'" => "\\'"
18
16
  }
19
17
 
20
- JS_ESCAPE_MAP["\342\200\250".dup.force_encoding(Encoding::UTF_8).encode!] = "&#x2028;"
21
- JS_ESCAPE_MAP["\342\200\251".dup.force_encoding(Encoding::UTF_8).encode!] = "&#x2029;"
18
+ JS_ESCAPE_MAP[(+"\342\200\250").force_encoding(Encoding::UTF_8).encode!] = "&#x2028;"
19
+ JS_ESCAPE_MAP[(+"\342\200\251").force_encoding(Encoding::UTF_8).encode!] = "&#x2029;"
22
20
 
23
21
  # Escapes carriage returns and single and double quotes for JavaScript segments.
24
22
  #
@@ -27,12 +25,13 @@ module ActionView
27
25
  #
28
26
  # $('some_element').replaceWith('<%= j render 'some/element_template' %>');
29
27
  def escape_javascript(javascript)
30
- if javascript
31
- result = javascript.gsub(/(\\|<\/|\r\n|\342\200\250|\342\200\251|[\n\r"']|[`]|[$])/u) { |match| JS_ESCAPE_MAP[match] }
32
- javascript.html_safe? ? result.html_safe : result
28
+ javascript = javascript.to_s
29
+ if javascript.empty?
30
+ result = ""
33
31
  else
34
- ""
32
+ result = javascript.gsub(/(\\|<\/|\r\n|\342\200\250|\342\200\251|[\n\r"'])/u) { |match| JS_ESCAPE_MAP[match] }
35
33
  end
34
+ javascript.html_safe? ? result.html_safe : result
36
35
  end
37
36
 
38
37
  alias_method :j, :escape_javascript
@@ -67,7 +66,7 @@ module ActionView
67
66
  # <% end -%>
68
67
  #
69
68
  # If you have a content security policy enabled then you can add an automatic
70
- # nonce value by passing +nonce: true+ as part of +html_options+. Example:
69
+ # nonce value by passing <tt>nonce: true</tt> as part of +html_options+. Example:
71
70
  #
72
71
  # <%= javascript_tag nonce: true do -%>
73
72
  # alert('All is good')
@@ -85,7 +84,7 @@ module ActionView
85
84
  html_options[:nonce] = content_security_policy_nonce
86
85
  end
87
86
 
88
- content_tag("script".freeze, javascript_cdata_section(content), html_options)
87
+ content_tag("script", javascript_cdata_section(content), html_options)
89
88
  end
90
89
 
91
90
  def javascript_cdata_section(content) #:nodoc:
@@ -100,6 +100,9 @@ module ActionView
100
100
  # absolute value of the number.
101
101
  # * <tt>:raise</tt> - If true, raises +InvalidNumberError+ when
102
102
  # the argument is invalid.
103
+ # * <tt>:strip_insignificant_zeros</tt> - If +true+ removes
104
+ # insignificant zeros after the decimal separator (defaults to
105
+ # +false+).
103
106
  #
104
107
  # ==== Examples
105
108
  #
@@ -117,6 +120,8 @@ module ActionView
117
120
  # # => R$1234567890,50
118
121
  # number_to_currency(1234567890.50, unit: "R$", separator: ",", delimiter: "", format: "%n %u")
119
122
  # # => 1234567890,50 R$
123
+ # number_to_currency(1234567890.50, strip_insignificant_zeros: true)
124
+ # # => "$1,234,567,890.5"
120
125
  def number_to_currency(number, options = {})
121
126
  delegate_number_helper_method(:number_to_currency, number, options)
122
127
  end
@@ -27,10 +27,12 @@ module ActionView
27
27
  def render(options = {}, locals = {}, &block)
28
28
  case options
29
29
  when Hash
30
- if block_given?
31
- view_renderer.render_partial(self, options.merge(partial: options[:layout]), &block)
32
- else
33
- view_renderer.render(self, options)
30
+ in_rendering_context(options) do |renderer|
31
+ if block_given?
32
+ view_renderer.render_partial(self, options.merge(partial: options[:layout]), &block)
33
+ else
34
+ view_renderer.render(self, options)
35
+ end
34
36
  end
35
37
  else
36
38
  view_renderer.render_partial(self, partial: options, locals: locals, &block)
@@ -10,7 +10,7 @@ module ActionView
10
10
  # These helper methods extend Action View making them callable within your template files.
11
11
  module SanitizeHelper
12
12
  extend ActiveSupport::Concern
13
- # Sanitizes HTML input, stripping all tags and attributes that aren't whitelisted.
13
+ # Sanitizes HTML input, stripping all but known-safe tags and attributes.
14
14
  #
15
15
  # It also strips href/src attributes with unsafe protocols like
16
16
  # <tt>javascript:</tt>, while also protecting against attempts to use Unicode,
@@ -40,7 +40,7 @@ module ActionView
40
40
  #
41
41
  # <%= sanitize @comment.body %>
42
42
  #
43
- # Providing custom whitelisted tags and attributes:
43
+ # Providing custom lists of permitted tags and attributes:
44
44
  #
45
45
  # <%= sanitize @comment.body, tags: %w(strong em a), attributes: %w(href) %>
46
46
  #
@@ -126,7 +126,7 @@ module ActionView
126
126
  attr_writer :full_sanitizer, :link_sanitizer, :white_list_sanitizer
127
127
 
128
128
  # Vendors the full, link and white list sanitizers.
129
- # Provided strictly for compatibility and can be removed in Rails 5.1.
129
+ # Provided strictly for compatibility and can be removed in Rails 6.
130
130
  def sanitizer_vendor
131
131
  Rails::Html::Sanitizer
132
132
  end