actionview 5.2.7.1 → 6.1.4.6
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +250 -112
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -3
- data/lib/action_view/base.rb +81 -15
- data/lib/action_view/buffers.rb +15 -0
- data/lib/action_view/cache_expiry.rb +52 -0
- data/lib/action_view/context.rb +5 -9
- data/lib/action_view/dependency_tracker.rb +10 -4
- data/lib/action_view/digestor.rb +15 -22
- data/lib/action_view/flows.rb +0 -1
- data/lib/action_view/gem_version.rb +4 -4
- data/lib/action_view/helpers/active_model_helper.rb +0 -1
- data/lib/action_view/helpers/asset_tag_helper.rb +64 -47
- data/lib/action_view/helpers/asset_url_helper.rb +9 -6
- data/lib/action_view/helpers/atom_feed_helper.rb +2 -1
- data/lib/action_view/helpers/cache_helper.rb +23 -22
- data/lib/action_view/helpers/capture_helper.rb +4 -0
- data/lib/action_view/helpers/csp_helper.rb +4 -2
- data/lib/action_view/helpers/csrf_helper.rb +1 -1
- data/lib/action_view/helpers/date_helper.rb +73 -30
- data/lib/action_view/helpers/form_helper.rb +305 -37
- data/lib/action_view/helpers/form_options_helper.rb +23 -23
- data/lib/action_view/helpers/form_tag_helper.rb +19 -16
- data/lib/action_view/helpers/javascript_helper.rb +12 -11
- data/lib/action_view/helpers/number_helper.rb +14 -8
- data/lib/action_view/helpers/output_safety_helper.rb +1 -1
- data/lib/action_view/helpers/rendering_helper.rb +17 -7
- data/lib/action_view/helpers/sanitize_helper.rb +12 -18
- data/lib/action_view/helpers/tag_helper.rb +100 -55
- data/lib/action_view/helpers/tags/base.rb +18 -11
- data/lib/action_view/helpers/tags/check_box.rb +0 -1
- data/lib/action_view/helpers/tags/collection_check_boxes.rb +0 -1
- data/lib/action_view/helpers/tags/collection_helpers.rb +0 -1
- data/lib/action_view/helpers/tags/collection_radio_buttons.rb +0 -1
- data/lib/action_view/helpers/tags/color_field.rb +1 -2
- data/lib/action_view/helpers/tags/date_field.rb +1 -2
- data/lib/action_view/helpers/tags/date_select.rb +2 -3
- data/lib/action_view/helpers/tags/datetime_field.rb +0 -1
- data/lib/action_view/helpers/tags/datetime_local_field.rb +1 -2
- data/lib/action_view/helpers/tags/label.rb +4 -1
- data/lib/action_view/helpers/tags/month_field.rb +1 -2
- data/lib/action_view/helpers/tags/radio_button.rb +0 -1
- data/lib/action_view/helpers/tags/select.rb +1 -2
- data/lib/action_view/helpers/tags/text_field.rb +0 -1
- data/lib/action_view/helpers/tags/time_field.rb +1 -2
- data/lib/action_view/helpers/tags/translator.rb +1 -6
- data/lib/action_view/helpers/tags/week_field.rb +1 -2
- data/lib/action_view/helpers/text_helper.rb +4 -5
- data/lib/action_view/helpers/translation_helper.rb +94 -54
- data/lib/action_view/helpers/url_helper.rb +136 -28
- data/lib/action_view/helpers.rb +0 -2
- data/lib/action_view/layouts.rb +8 -10
- data/lib/action_view/log_subscriber.rb +30 -15
- data/lib/action_view/lookup_context.rb +63 -35
- data/lib/action_view/path_set.rb +3 -12
- data/lib/action_view/railtie.rb +42 -26
- data/lib/action_view/record_identifier.rb +2 -3
- data/lib/action_view/renderer/abstract_renderer.rb +142 -11
- data/lib/action_view/renderer/collection_renderer.rb +196 -0
- data/lib/action_view/renderer/object_renderer.rb +34 -0
- data/lib/action_view/renderer/partial_renderer/collection_caching.rb +61 -16
- data/lib/action_view/renderer/partial_renderer.rb +21 -273
- data/lib/action_view/renderer/renderer.rb +59 -4
- data/lib/action_view/renderer/streaming_template_renderer.rb +10 -8
- data/lib/action_view/renderer/template_renderer.rb +35 -27
- data/lib/action_view/rendering.rb +54 -33
- data/lib/action_view/routing_url_for.rb +13 -12
- data/lib/action_view/template/error.rb +30 -15
- data/lib/action_view/template/handlers/builder.rb +2 -2
- data/lib/action_view/template/handlers/erb/erubi.rb +15 -9
- data/lib/action_view/template/handlers/erb.rb +16 -11
- data/lib/action_view/template/handlers/html.rb +1 -1
- data/lib/action_view/template/handlers/raw.rb +2 -2
- data/lib/action_view/template/handlers.rb +1 -1
- data/lib/action_view/template/html.rb +5 -6
- data/lib/action_view/template/inline.rb +22 -0
- data/lib/action_view/template/raw_file.rb +25 -0
- data/lib/action_view/template/renderable.rb +24 -0
- data/lib/action_view/template/resolver.rb +191 -150
- data/lib/action_view/template/sources/file.rb +17 -0
- data/lib/action_view/template/sources.rb +13 -0
- data/lib/action_view/template/text.rb +2 -3
- data/lib/action_view/template.rb +66 -75
- data/lib/action_view/test_case.rb +21 -29
- data/lib/action_view/testing/resolvers.rb +18 -27
- data/lib/action_view/unbound_template.rb +31 -0
- data/lib/action_view/view_paths.rb +59 -38
- data/lib/action_view.rb +7 -2
- data/lib/assets/compiled/rails-ujs.js +32 -6
- metadata +29 -18
- data/lib/action_view/helpers/record_tag_helper.rb +0 -23
@@ -11,6 +11,7 @@ require "active_support/core_ext/module/attribute_accessors"
|
|
11
11
|
require "active_support/core_ext/hash/slice"
|
12
12
|
require "active_support/core_ext/string/output_safety"
|
13
13
|
require "active_support/core_ext/string/inflections"
|
14
|
+
require "active_support/core_ext/symbol/starts_ends_with"
|
14
15
|
|
15
16
|
module ActionView
|
16
17
|
# = Action View Form Helpers
|
@@ -185,8 +186,7 @@ module ActionView
|
|
185
186
|
# get the authenticity token from the <tt>meta</tt> tag, so embedding is
|
186
187
|
# unnecessary unless you support browsers without JavaScript.
|
187
188
|
# * <tt>:remote</tt> - If set to true, will allow the Unobtrusive
|
188
|
-
# JavaScript drivers to control the submit behavior.
|
189
|
-
# behavior is an ajax submit.
|
189
|
+
# JavaScript drivers to control the submit behavior.
|
190
190
|
# * <tt>:enforce_utf8</tt> - If set to false, a hidden input with name
|
191
191
|
# utf8 is not output.
|
192
192
|
# * <tt>:html</tt> - Optional HTML attributes for the form tag.
|
@@ -322,10 +322,8 @@ module ActionView
|
|
322
322
|
# remote: true
|
323
323
|
#
|
324
324
|
# in the options hash creates a form that will allow the unobtrusive JavaScript drivers to modify its
|
325
|
-
# behavior. The
|
326
|
-
#
|
327
|
-
# Even though it's using JavaScript to serialize the form elements, the form submission will work just like
|
328
|
-
# a regular submission as viewed by the receiving side (all elements available in <tt>params</tt>).
|
325
|
+
# behavior. The form submission will work just like a regular submission as viewed by the receiving
|
326
|
+
# side (all elements available in <tt>params</tt>).
|
329
327
|
#
|
330
328
|
# Example:
|
331
329
|
#
|
@@ -535,11 +533,6 @@ module ActionView
|
|
535
533
|
# accessible as <tt>params[:title]</tt> and <tt>params[:post][:title]</tt>
|
536
534
|
# respectively.
|
537
535
|
#
|
538
|
-
# By default +form_with+ attaches the <tt>data-remote</tt> attribute
|
539
|
-
# submitting the form via an XMLHTTPRequest in the background if an
|
540
|
-
# Unobtrusive JavaScript driver, like rails-ujs, is used. See the
|
541
|
-
# <tt>:local</tt> option for more.
|
542
|
-
#
|
543
536
|
# For ease of comparison the examples above left out the submit button,
|
544
537
|
# as well as the auto generated hidden fields that enable UTF-8 support
|
545
538
|
# and adds an authenticity token needed for cross site request forgery
|
@@ -590,6 +583,9 @@ module ActionView
|
|
590
583
|
# Skipped if a <tt>:url</tt> is passed.
|
591
584
|
# * <tt>:scope</tt> - The scope to prefix input field names with and
|
592
585
|
# thereby how the submitted parameters are grouped in controllers.
|
586
|
+
# * <tt>:namespace</tt> - A namespace for your form to ensure uniqueness of
|
587
|
+
# id attributes on form elements. The namespace attribute will be prefixed
|
588
|
+
# with underscore on the generated HTML id.
|
593
589
|
# * <tt>:model</tt> - A model object to infer the <tt>:url</tt> and
|
594
590
|
# <tt>:scope</tt> by, plus fill out input field values.
|
595
591
|
# So if a +title+ attribute is set to "Ahoy!" then a +title+ input
|
@@ -608,10 +604,12 @@ module ActionView
|
|
608
604
|
# This is helpful when fragment-caching the form. Remote forms
|
609
605
|
# get the authenticity token from the <tt>meta</tt> tag, so embedding is
|
610
606
|
# unnecessary unless you support browsers without JavaScript.
|
611
|
-
# * <tt>:local</tt> - By default form submits
|
612
|
-
#
|
613
|
-
#
|
614
|
-
#
|
607
|
+
# * <tt>:local</tt> - By default form submits via typical HTTP requests.
|
608
|
+
# Enable remote and unobtrusive XHRs submits with <tt>local: false</tt>.
|
609
|
+
# Remote forms may be enabled by default by setting
|
610
|
+
# <tt>config.action_view.form_with_generates_remote_forms = true</tt>.
|
611
|
+
# * <tt>:skip_enforcing_utf8</tt> - If set to true, a hidden input with name
|
612
|
+
# utf8 is not output.
|
615
613
|
# * <tt>:builder</tt> - Override the object used to build the form.
|
616
614
|
# * <tt>:id</tt> - Optional HTML id attribute.
|
617
615
|
# * <tt>:class</tt> - Optional HTML class attribute.
|
@@ -752,10 +750,10 @@ module ActionView
|
|
752
750
|
output = capture(builder, &block)
|
753
751
|
options[:multipart] ||= builder.multipart?
|
754
752
|
|
755
|
-
html_options = html_options_for_form_with(url, model, options)
|
753
|
+
html_options = html_options_for_form_with(url, model, **options)
|
756
754
|
form_tag_with_body(html_options, output)
|
757
755
|
else
|
758
|
-
html_options = html_options_for_form_with(url, model, options)
|
756
|
+
html_options = html_options_for_form_with(url, model, **options)
|
759
757
|
form_tag_html(html_options)
|
760
758
|
end
|
761
759
|
end
|
@@ -885,7 +883,7 @@ module ActionView
|
|
885
883
|
#
|
886
884
|
# Now, when you use a form element with the <tt>_destroy</tt> parameter,
|
887
885
|
# with a value that evaluates to +true+, you will destroy the associated
|
888
|
-
# model (
|
886
|
+
# model (e.g. 1, '1', true, or 'true'):
|
889
887
|
#
|
890
888
|
# <%= form_for @person do |person_form| %>
|
891
889
|
# ...
|
@@ -974,7 +972,7 @@ module ActionView
|
|
974
972
|
# This will allow you to specify which models to destroy in the
|
975
973
|
# attributes hash by adding a form element for the <tt>_destroy</tt>
|
976
974
|
# parameter with a value that evaluates to +true+
|
977
|
-
# (
|
975
|
+
# (e.g. 1, '1', true, or 'true'):
|
978
976
|
#
|
979
977
|
# <%= form_for @person do |person_form| %>
|
980
978
|
# ...
|
@@ -1107,6 +1105,16 @@ module ActionView
|
|
1107
1105
|
# label(:post, :privacy, "Public Post", value: "public")
|
1108
1106
|
# # => <label for="post_privacy_public">Public Post</label>
|
1109
1107
|
#
|
1108
|
+
# label(:post, :cost) do |translation|
|
1109
|
+
# content_tag(:span, translation, class: "cost_label")
|
1110
|
+
# end
|
1111
|
+
# # => <label for="post_cost"><span class="cost_label">Total cost</span></label>
|
1112
|
+
#
|
1113
|
+
# label(:post, :cost) do |builder|
|
1114
|
+
# content_tag(:span, builder.translation, class: "cost_label")
|
1115
|
+
# end
|
1116
|
+
# # => <label for="post_cost"><span class="cost_label">Total cost</span></label>
|
1117
|
+
#
|
1110
1118
|
# label(:post, :terms) do
|
1111
1119
|
# raw('Accept <a href="/terms">Terms</a>.')
|
1112
1120
|
# end
|
@@ -1127,6 +1135,9 @@ module ActionView
|
|
1127
1135
|
# text_field(:post, :title, class: "create_input")
|
1128
1136
|
# # => <input type="text" id="post_title" name="post[title]" value="#{@post.title}" class="create_input" />
|
1129
1137
|
#
|
1138
|
+
# text_field(:post, :title, maxlength: 30, class: "title_input")
|
1139
|
+
# # => <input type="text" id="post_title" name="post[title]" maxlength="30" size="30" value="#{@post.title}" class="title_input" />
|
1140
|
+
#
|
1130
1141
|
# text_field(:session, :user, onchange: "if ($('#session_user').val() === 'admin') { alert('Your login cannot be admin!'); }")
|
1131
1142
|
# # => <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
1143
|
#
|
@@ -1519,10 +1530,10 @@ module ActionView
|
|
1519
1530
|
|
1520
1531
|
private
|
1521
1532
|
def html_options_for_form_with(url_for_options = nil, model = nil, html: {}, local: !form_with_generates_remote_forms,
|
1522
|
-
skip_enforcing_utf8:
|
1533
|
+
skip_enforcing_utf8: nil, **options)
|
1523
1534
|
html_options = options.slice(:id, :class, :multipart, :method, :data).merge(html)
|
1524
1535
|
html_options[:method] ||= :patch if model.respond_to?(:persisted?) && model.persisted?
|
1525
|
-
html_options[:enforce_utf8] = !skip_enforcing_utf8
|
1536
|
+
html_options[:enforce_utf8] = !skip_enforcing_utf8 unless skip_enforcing_utf8.nil?
|
1526
1537
|
|
1527
1538
|
html_options[:enctype] = "multipart/form-data" if html_options.delete(:multipart)
|
1528
1539
|
|
@@ -1662,8 +1673,8 @@ module ActionView
|
|
1662
1673
|
|
1663
1674
|
convert_to_legacy_options(@options)
|
1664
1675
|
|
1665
|
-
if @object_name
|
1666
|
-
if (object ||= @template.instance_variable_get("@#{
|
1676
|
+
if @object_name&.end_with?("[]")
|
1677
|
+
if (object ||= @template.instance_variable_get("@#{@object_name[0..-3]}")) && object.respond_to?(:to_param)
|
1667
1678
|
@auto_index = object.to_param
|
1668
1679
|
else
|
1669
1680
|
raise ArgumentError, "object[] naming but object param and @object var don't exist or don't respond to to_param: #{object.inspect}"
|
@@ -1674,11 +1685,232 @@ module ActionView
|
|
1674
1685
|
@index = options[:index] || options[:child_index]
|
1675
1686
|
end
|
1676
1687
|
|
1688
|
+
##
|
1689
|
+
# :method: text_field
|
1690
|
+
#
|
1691
|
+
# :call-seq: text_field(method, options = {})
|
1692
|
+
#
|
1693
|
+
# Wraps ActionView::Helpers::FormHelper#text_field for form builders:
|
1694
|
+
#
|
1695
|
+
# <%= form_with model: @user do |f| %>
|
1696
|
+
# <%= f.text_field :name %>
|
1697
|
+
# <% end %>
|
1698
|
+
#
|
1699
|
+
# Please refer to the documentation of the base helper for details.
|
1700
|
+
|
1701
|
+
##
|
1702
|
+
# :method: password_field
|
1703
|
+
#
|
1704
|
+
# :call-seq: password_field(method, options = {})
|
1705
|
+
#
|
1706
|
+
# Wraps ActionView::Helpers::FormHelper#password_field for form builders:
|
1707
|
+
#
|
1708
|
+
# <%= form_with model: @user do |f| %>
|
1709
|
+
# <%= f.password_field :password %>
|
1710
|
+
# <% end %>
|
1711
|
+
#
|
1712
|
+
# Please refer to the documentation of the base helper for details.
|
1713
|
+
|
1714
|
+
##
|
1715
|
+
# :method: text_area
|
1716
|
+
#
|
1717
|
+
# :call-seq: text_area(method, options = {})
|
1718
|
+
#
|
1719
|
+
# Wraps ActionView::Helpers::FormHelper#text_area for form builders:
|
1720
|
+
#
|
1721
|
+
# <%= form_with model: @user do |f| %>
|
1722
|
+
# <%= f.text_area :detail %>
|
1723
|
+
# <% end %>
|
1724
|
+
#
|
1725
|
+
# Please refer to the documentation of the base helper for details.
|
1726
|
+
|
1727
|
+
##
|
1728
|
+
# :method: color_field
|
1729
|
+
#
|
1730
|
+
# :call-seq: color_field(method, options = {})
|
1731
|
+
#
|
1732
|
+
# Wraps ActionView::Helpers::FormHelper#color_field for form builders:
|
1733
|
+
#
|
1734
|
+
# <%= form_with model: @user do |f| %>
|
1735
|
+
# <%= f.color_field :favorite_color %>
|
1736
|
+
# <% end %>
|
1737
|
+
#
|
1738
|
+
# Please refer to the documentation of the base helper for details.
|
1739
|
+
|
1740
|
+
##
|
1741
|
+
# :method: search_field
|
1742
|
+
#
|
1743
|
+
# :call-seq: search_field(method, options = {})
|
1744
|
+
#
|
1745
|
+
# Wraps ActionView::Helpers::FormHelper#search_field for form builders:
|
1746
|
+
#
|
1747
|
+
# <%= form_with model: @user do |f| %>
|
1748
|
+
# <%= f.search_field :name %>
|
1749
|
+
# <% end %>
|
1750
|
+
#
|
1751
|
+
# Please refer to the documentation of the base helper for details.
|
1752
|
+
|
1753
|
+
##
|
1754
|
+
# :method: telephone_field
|
1755
|
+
#
|
1756
|
+
# :call-seq: telephone_field(method, options = {})
|
1757
|
+
#
|
1758
|
+
# Wraps ActionView::Helpers::FormHelper#telephone_field for form builders:
|
1759
|
+
#
|
1760
|
+
# <%= form_with model: @user do |f| %>
|
1761
|
+
# <%= f.telephone_field :phone %>
|
1762
|
+
# <% end %>
|
1763
|
+
#
|
1764
|
+
# Please refer to the documentation of the base helper for details.
|
1765
|
+
|
1766
|
+
##
|
1767
|
+
# :method: phone_field
|
1768
|
+
#
|
1769
|
+
# :call-seq: phone_field(method, options = {})
|
1770
|
+
#
|
1771
|
+
# Wraps ActionView::Helpers::FormHelper#phone_field for form builders:
|
1772
|
+
#
|
1773
|
+
# <%= form_with model: @user do |f| %>
|
1774
|
+
# <%= f.phone_field :phone %>
|
1775
|
+
# <% end %>
|
1776
|
+
#
|
1777
|
+
# Please refer to the documentation of the base helper for details.
|
1778
|
+
|
1779
|
+
##
|
1780
|
+
# :method: date_field
|
1781
|
+
#
|
1782
|
+
# :call-seq: date_field(method, options = {})
|
1783
|
+
#
|
1784
|
+
# Wraps ActionView::Helpers::FormHelper#date_field for form builders:
|
1785
|
+
#
|
1786
|
+
# <%= form_with model: @user do |f| %>
|
1787
|
+
# <%= f.date_field :born_on %>
|
1788
|
+
# <% end %>
|
1789
|
+
#
|
1790
|
+
# Please refer to the documentation of the base helper for details.
|
1791
|
+
|
1792
|
+
##
|
1793
|
+
# :method: time_field
|
1794
|
+
#
|
1795
|
+
# :call-seq: time_field(method, options = {})
|
1796
|
+
#
|
1797
|
+
# Wraps ActionView::Helpers::FormHelper#time_field for form builders:
|
1798
|
+
#
|
1799
|
+
# <%= form_with model: @user do |f| %>
|
1800
|
+
# <%= f.time_field :born_at %>
|
1801
|
+
# <% end %>
|
1802
|
+
#
|
1803
|
+
# Please refer to the documentation of the base helper for details.
|
1804
|
+
|
1805
|
+
##
|
1806
|
+
# :method: datetime_field
|
1807
|
+
#
|
1808
|
+
# :call-seq: datetime_field(method, options = {})
|
1809
|
+
#
|
1810
|
+
# Wraps ActionView::Helpers::FormHelper#datetime_field for form builders:
|
1811
|
+
#
|
1812
|
+
# <%= form_with model: @user do |f| %>
|
1813
|
+
# <%= f.datetime_field :graduation_day %>
|
1814
|
+
# <% end %>
|
1815
|
+
#
|
1816
|
+
# Please refer to the documentation of the base helper for details.
|
1817
|
+
|
1818
|
+
##
|
1819
|
+
# :method: datetime_local_field
|
1820
|
+
#
|
1821
|
+
# :call-seq: datetime_local_field(method, options = {})
|
1822
|
+
#
|
1823
|
+
# Wraps ActionView::Helpers::FormHelper#datetime_local_field for form builders:
|
1824
|
+
#
|
1825
|
+
# <%= form_with model: @user do |f| %>
|
1826
|
+
# <%= f.datetime_local_field :graduation_day %>
|
1827
|
+
# <% end %>
|
1828
|
+
#
|
1829
|
+
# Please refer to the documentation of the base helper for details.
|
1830
|
+
|
1831
|
+
##
|
1832
|
+
# :method: month_field
|
1833
|
+
#
|
1834
|
+
# :call-seq: month_field(method, options = {})
|
1835
|
+
#
|
1836
|
+
# Wraps ActionView::Helpers::FormHelper#month_field for form builders:
|
1837
|
+
#
|
1838
|
+
# <%= form_with model: @user do |f| %>
|
1839
|
+
# <%= f.month_field :birthday_month %>
|
1840
|
+
# <% end %>
|
1841
|
+
#
|
1842
|
+
# Please refer to the documentation of the base helper for details.
|
1843
|
+
|
1844
|
+
##
|
1845
|
+
# :method: week_field
|
1846
|
+
#
|
1847
|
+
# :call-seq: week_field(method, options = {})
|
1848
|
+
#
|
1849
|
+
# Wraps ActionView::Helpers::FormHelper#week_field for form builders:
|
1850
|
+
#
|
1851
|
+
# <%= form_with model: @user do |f| %>
|
1852
|
+
# <%= f.week_field :birthday_week %>
|
1853
|
+
# <% end %>
|
1854
|
+
#
|
1855
|
+
# Please refer to the documentation of the base helper for details.
|
1856
|
+
|
1857
|
+
##
|
1858
|
+
# :method: url_field
|
1859
|
+
#
|
1860
|
+
# :call-seq: url_field(method, options = {})
|
1861
|
+
#
|
1862
|
+
# Wraps ActionView::Helpers::FormHelper#url_field for form builders:
|
1863
|
+
#
|
1864
|
+
# <%= form_with model: @user do |f| %>
|
1865
|
+
# <%= f.url_field :homepage %>
|
1866
|
+
# <% end %>
|
1867
|
+
#
|
1868
|
+
# Please refer to the documentation of the base helper for details.
|
1869
|
+
|
1870
|
+
##
|
1871
|
+
# :method: email_field
|
1872
|
+
#
|
1873
|
+
# :call-seq: email_field(method, options = {})
|
1874
|
+
#
|
1875
|
+
# Wraps ActionView::Helpers::FormHelper#email_field for form builders:
|
1876
|
+
#
|
1877
|
+
# <%= form_with model: @user do |f| %>
|
1878
|
+
# <%= f.email_field :address %>
|
1879
|
+
# <% end %>
|
1880
|
+
#
|
1881
|
+
# Please refer to the documentation of the base helper for details.
|
1882
|
+
|
1883
|
+
##
|
1884
|
+
# :method: number_field
|
1885
|
+
#
|
1886
|
+
# :call-seq: number_field(method, options = {})
|
1887
|
+
#
|
1888
|
+
# Wraps ActionView::Helpers::FormHelper#number_field for form builders:
|
1889
|
+
#
|
1890
|
+
# <%= form_with model: @user do |f| %>
|
1891
|
+
# <%= f.number_field :age %>
|
1892
|
+
# <% end %>
|
1893
|
+
#
|
1894
|
+
# Please refer to the documentation of the base helper for details.
|
1895
|
+
|
1896
|
+
##
|
1897
|
+
# :method: range_field
|
1898
|
+
#
|
1899
|
+
# :call-seq: range_field(method, options = {})
|
1900
|
+
#
|
1901
|
+
# Wraps ActionView::Helpers::FormHelper#range_field for form builders:
|
1902
|
+
#
|
1903
|
+
# <%= form_with model: @user do |f| %>
|
1904
|
+
# <%= f.range_field :age %>
|
1905
|
+
# <% end %>
|
1906
|
+
#
|
1907
|
+
# Please refer to the documentation of the base helper for details.
|
1908
|
+
|
1677
1909
|
(field_helpers - [:label, :check_box, :radio_button, :fields_for, :fields, :hidden_field, :file_field]).each do |selector|
|
1678
1910
|
class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
|
1679
1911
|
def #{selector}(method, options = {}) # def text_field(method, options = {})
|
1680
|
-
@template.
|
1681
|
-
#{selector.inspect}, #
|
1912
|
+
@template.public_send( # @template.public_send(
|
1913
|
+
#{selector.inspect}, # :text_field,
|
1682
1914
|
@object_name, # @object_name,
|
1683
1915
|
method, # method,
|
1684
1916
|
objectify_options(options)) # objectify_options(options))
|
@@ -1811,7 +2043,7 @@ module ActionView
|
|
1811
2043
|
#
|
1812
2044
|
# Now, when you use a form element with the <tt>_destroy</tt> parameter,
|
1813
2045
|
# with a value that evaluates to +true+, you will destroy the associated
|
1814
|
-
# model (
|
2046
|
+
# model (e.g. 1, '1', true, or 'true'):
|
1815
2047
|
#
|
1816
2048
|
# <%= form_for @person do |person_form| %>
|
1817
2049
|
# ...
|
@@ -1900,7 +2132,7 @@ module ActionView
|
|
1900
2132
|
# This will allow you to specify which models to destroy in the
|
1901
2133
|
# attributes hash by adding a form element for the <tt>_destroy</tt>
|
1902
2134
|
# parameter with a value that evaluates to +true+
|
1903
|
-
# (
|
2135
|
+
# (e.g. 1, '1', true, or 'true'):
|
1904
2136
|
#
|
1905
2137
|
# <%= form_for @person do |person_form| %>
|
1906
2138
|
# ...
|
@@ -1947,15 +2179,14 @@ module ActionView
|
|
1947
2179
|
index = if options.has_key?(:index)
|
1948
2180
|
options[:index]
|
1949
2181
|
elsif defined?(@auto_index)
|
1950
|
-
object_name = object_name.to_s.
|
2182
|
+
object_name = object_name.to_s.delete_suffix("[]")
|
1951
2183
|
@auto_index
|
1952
2184
|
end
|
1953
2185
|
|
1954
2186
|
record_name = if index
|
1955
2187
|
"#{object_name}[#{index}][#{record_name}]"
|
1956
|
-
elsif record_name.
|
1957
|
-
record_name
|
1958
|
-
"#{object_name}#{record_name}"
|
2188
|
+
elsif record_name.end_with?("[]")
|
2189
|
+
"#{object_name}[#{record_name[0..-3]}][#{record_object.id}]"
|
1959
2190
|
else
|
1960
2191
|
"#{object_name}[#{record_name}]"
|
1961
2192
|
end
|
@@ -2018,6 +2249,24 @@ module ActionView
|
|
2018
2249
|
# label(:privacy, "Public Post", value: "public")
|
2019
2250
|
# # => <label for="post_privacy_public">Public Post</label>
|
2020
2251
|
#
|
2252
|
+
# label(:cost) do |translation|
|
2253
|
+
# content_tag(:span, translation, class: "cost_label")
|
2254
|
+
# end
|
2255
|
+
# # => <label for="post_cost"><span class="cost_label">Total cost</span></label>
|
2256
|
+
#
|
2257
|
+
# label(:cost) do |builder|
|
2258
|
+
# content_tag(:span, builder.translation, class: "cost_label")
|
2259
|
+
# end
|
2260
|
+
# # => <label for="post_cost"><span class="cost_label">Total cost</span></label>
|
2261
|
+
#
|
2262
|
+
# label(:cost) do |builder|
|
2263
|
+
# content_tag(:span, builder.translation, class: [
|
2264
|
+
# "cost_label",
|
2265
|
+
# ("error_label" if builder.object.errors.include?(:cost))
|
2266
|
+
# ])
|
2267
|
+
# end
|
2268
|
+
# # => <label for="post_cost"><span class="cost_label error_label">Total cost</span></label>
|
2269
|
+
#
|
2021
2270
|
# label(:terms) do
|
2022
2271
|
# raw('Accept <a href="/terms">Terms</a>.')
|
2023
2272
|
# end
|
@@ -2241,19 +2490,33 @@ module ActionView
|
|
2241
2490
|
# # <strong>Ask me!</strong>
|
2242
2491
|
# # </button>
|
2243
2492
|
#
|
2493
|
+
# button do |text|
|
2494
|
+
# content_tag(:strong, text)
|
2495
|
+
# end
|
2496
|
+
# # => <button name='button' type='submit'>
|
2497
|
+
# # <strong>Create post</strong>
|
2498
|
+
# # </button>
|
2499
|
+
#
|
2244
2500
|
def button(value = nil, options = {}, &block)
|
2245
2501
|
value, options = nil, value if value.is_a?(Hash)
|
2246
2502
|
value ||= submit_default_value
|
2247
|
-
|
2503
|
+
|
2504
|
+
if block_given?
|
2505
|
+
value = @template.capture { yield(value) }
|
2506
|
+
end
|
2507
|
+
|
2508
|
+
@template.button_tag(value, options)
|
2248
2509
|
end
|
2249
2510
|
|
2250
|
-
def emitted_hidden_id?
|
2511
|
+
def emitted_hidden_id? # :nodoc:
|
2251
2512
|
@emitted_hidden_id ||= nil
|
2252
2513
|
end
|
2253
2514
|
|
2254
2515
|
private
|
2255
2516
|
def objectify_options(options)
|
2256
|
-
@default_options.merge(options
|
2517
|
+
result = @default_options.merge(options)
|
2518
|
+
result[:object] = @object
|
2519
|
+
result
|
2257
2520
|
end
|
2258
2521
|
|
2259
2522
|
def submit_default_value
|
@@ -2267,7 +2530,12 @@ module ActionView
|
|
2267
2530
|
end
|
2268
2531
|
|
2269
2532
|
defaults = []
|
2270
|
-
|
2533
|
+
# Object is a model and it is not overwritten by as and scope option.
|
2534
|
+
if object.respond_to?(:model_name) && object_name.to_s == model.downcase
|
2535
|
+
defaults << :"helpers.submit.#{object.model_name.i18n_key}.#{key}"
|
2536
|
+
else
|
2537
|
+
defaults << :"helpers.submit.#{object_name}.#{key}"
|
2538
|
+
end
|
2271
2539
|
defaults << :"helpers.submit.#{key}"
|
2272
2540
|
defaults << "#{key.to_s.humanize} #{model}"
|
2273
2541
|
|
@@ -2283,9 +2551,9 @@ module ActionView
|
|
2283
2551
|
association = convert_to_model(association)
|
2284
2552
|
|
2285
2553
|
if association.respond_to?(:persisted?)
|
2286
|
-
association = [association] if @object.
|
2554
|
+
association = [association] if @object.public_send(association_name).respond_to?(:to_ary)
|
2287
2555
|
elsif !association.respond_to?(:to_ary)
|
2288
|
-
association = @object.
|
2556
|
+
association = @object.public_send(association_name)
|
2289
2557
|
end
|
2290
2558
|
|
2291
2559
|
if association.respond_to?(:to_ary)
|
@@ -16,12 +16,12 @@ 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
|
#
|
23
23
|
# <select name="post[category]" id="post_category">
|
24
|
-
# <option value=""></option>
|
24
|
+
# <option value="" label=" "></option>
|
25
25
|
# <option value="joke">joke</option>
|
26
26
|
# <option value="poem">poem</option>
|
27
27
|
# </select>
|
@@ -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,12 +69,11 @@ 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
|
#
|
76
76
|
# <select name="post[category]" id="post_category">
|
77
|
-
# <option value=""></option>
|
78
77
|
# <option value="joke">joke</option>
|
79
78
|
# <option value="poem">poem</option>
|
80
79
|
# <option disabled="disabled" value="restricted">restricted</option>
|
@@ -82,7 +81,7 @@ module ActionView
|
|
82
81
|
#
|
83
82
|
# When used with the <tt>collection_select</tt> helper, <tt>:disabled</tt> can also be a Proc that identifies those options that should be disabled.
|
84
83
|
#
|
85
|
-
# collection_select(:post, :category_id, Category.all, :id, :name, {disabled: -> (category) { category.archived? }})
|
84
|
+
# collection_select(:post, :category_id, Category.all, :id, :name, { disabled: -> (category) { category.archived? } })
|
86
85
|
#
|
87
86
|
# If the categories "2008 stuff" and "Christmas" return true when the method <tt>archived?</tt> is called, this would return:
|
88
87
|
# <select name="post[category_id]" id="post_category_id">
|
@@ -107,12 +106,12 @@ module ActionView
|
|
107
106
|
#
|
108
107
|
# For example:
|
109
108
|
#
|
110
|
-
# select("post", "person_id", Person.all.collect {|p| [ p.name, p.id ] }, { include_blank: true })
|
109
|
+
# select("post", "person_id", Person.all.collect { |p| [ p.name, p.id ] }, { include_blank: true })
|
111
110
|
#
|
112
111
|
# would become:
|
113
112
|
#
|
114
113
|
# <select name="post[person_id]" id="post_person_id">
|
115
|
-
# <option value=""></option>
|
114
|
+
# <option value="" label=" "></option>
|
116
115
|
# <option value="1" selected="selected">David</option>
|
117
116
|
# <option value="2">Eileen</option>
|
118
117
|
# <option value="3">Rafael</option>
|
@@ -143,7 +142,7 @@ module ActionView
|
|
143
142
|
#
|
144
143
|
# The HTML specification says when +multiple+ parameter passed to select and all options got deselected
|
145
144
|
# web browsers do not send any value to server. Unfortunately this introduces a gotcha:
|
146
|
-
# if
|
145
|
+
# if a +User+ model has many +roles+ and have +role_ids+ accessor, and in the form that edits roles of the user
|
147
146
|
# the user deselects all roles from +role_ids+ multiple select box, no +role_ids+ parameter is sent. So,
|
148
147
|
# any mass-assignment idiom like
|
149
148
|
#
|
@@ -323,12 +322,12 @@ module ActionView
|
|
323
322
|
#
|
324
323
|
# You can optionally provide HTML attributes as the last element of the array.
|
325
324
|
#
|
326
|
-
# options_for_select([ "Denmark", ["USA", {class: 'bold'}], "Sweden" ], ["USA", "Sweden"])
|
325
|
+
# options_for_select([ "Denmark", ["USA", { class: 'bold' }], "Sweden" ], ["USA", "Sweden"])
|
327
326
|
# # => <option value="Denmark">Denmark</option>
|
328
327
|
# # => <option value="USA" class="bold" selected="selected">USA</option>
|
329
328
|
# # => <option value="Sweden" selected="selected">Sweden</option>
|
330
329
|
#
|
331
|
-
# options_for_select([["Dollar", "$", {class: "bold"}], ["Kroner", "DKK", {onclick: "alert('HI');"}]])
|
330
|
+
# options_for_select([["Dollar", "$", { class: "bold" }], ["Kroner", "DKK", { onclick: "alert('HI');" }]])
|
332
331
|
# # => <option value="$" class="bold">Dollar</option>
|
333
332
|
# # => <option value="DKK" onclick="alert('HI');">Kroner</option>
|
334
333
|
#
|
@@ -463,7 +462,7 @@ module ActionView
|
|
463
462
|
option_tags = options_from_collection_for_select(
|
464
463
|
value_for_collection(group, group_method), option_key_method, option_value_method, selected_key)
|
465
464
|
|
466
|
-
content_tag("optgroup"
|
465
|
+
content_tag("optgroup", option_tags, label: value_for_collection(group, group_label_method))
|
467
466
|
end.join.html_safe
|
468
467
|
end
|
469
468
|
|
@@ -535,7 +534,7 @@ module ActionView
|
|
535
534
|
body = "".html_safe
|
536
535
|
|
537
536
|
if prompt
|
538
|
-
body.safe_concat content_tag("option"
|
537
|
+
body.safe_concat content_tag("option", prompt_text(prompt), value: "")
|
539
538
|
end
|
540
539
|
|
541
540
|
grouped_options.each do |container|
|
@@ -548,7 +547,7 @@ module ActionView
|
|
548
547
|
end
|
549
548
|
|
550
549
|
html_attributes = { label: label }.merge!(html_attributes)
|
551
|
-
body.safe_concat content_tag("optgroup"
|
550
|
+
body.safe_concat content_tag("optgroup", options_for_select(container, selected_key), html_attributes)
|
552
551
|
end
|
553
552
|
|
554
553
|
body
|
@@ -566,9 +565,10 @@ module ActionView
|
|
566
565
|
# an ActiveSupport::TimeZone.
|
567
566
|
#
|
568
567
|
# By default, +model+ is the ActiveSupport::TimeZone constant (which can
|
569
|
-
# be obtained in Active Record as a value object). The
|
570
|
-
#
|
571
|
-
#
|
568
|
+
# be obtained in Active Record as a value object). The +model+ parameter
|
569
|
+
# must respond to +all+ and return an array of objects that represent time
|
570
|
+
# zones; each object must respond to +name+. If a Regexp is given it will
|
571
|
+
# attempt to match the zones using <code>match?</code> method.
|
572
572
|
#
|
573
573
|
# NOTE: Only the option tags are returned, you have to wrap this call in
|
574
574
|
# a regular HTML select tag.
|
@@ -580,11 +580,11 @@ module ActionView
|
|
580
580
|
|
581
581
|
if priority_zones
|
582
582
|
if priority_zones.is_a?(Regexp)
|
583
|
-
priority_zones = zones.select { |z| z
|
583
|
+
priority_zones = zones.select { |z| z.match?(priority_zones) }
|
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"
|
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
|
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.
|
797
|
+
element.public_send(value_method) if selected.call(element)
|
798
798
|
end.compact
|
799
799
|
else
|
800
800
|
selected
|
@@ -802,7 +802,7 @@ module ActionView
|
|
802
802
|
end
|
803
803
|
|
804
804
|
def value_for_collection(item, value)
|
805
|
-
value.respond_to?(:call) ? value.call(item) : item.
|
805
|
+
value.respond_to?(:call) ? value.call(item) : item.public_send(value)
|
806
806
|
end
|
807
807
|
|
808
808
|
def prompt_text(prompt)
|