actionview 7.2.3 → 8.0.5
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +82 -108
- data/lib/action_view/dependency_tracker/erb_tracker.rb +36 -27
- data/lib/action_view/dependency_tracker/ruby_tracker.rb +2 -19
- data/lib/action_view/dependency_tracker/wildcard_resolver.rb +32 -0
- data/lib/action_view/dependency_tracker.rb +1 -0
- data/lib/action_view/gem_version.rb +3 -3
- data/lib/action_view/helpers/atom_feed_helper.rb +0 -2
- data/lib/action_view/helpers/cache_helper.rb +8 -0
- data/lib/action_view/helpers/date_helper.rb +3 -3
- data/lib/action_view/helpers/form_helper.rb +76 -75
- data/lib/action_view/helpers/form_options_helper.rb +25 -22
- data/lib/action_view/helpers/form_tag_helper.rb +20 -17
- data/lib/action_view/helpers/rendering_helper.rb +160 -50
- data/lib/action_view/helpers/sanitize_helper.rb +6 -0
- data/lib/action_view/helpers/tag_helper.rb +31 -41
- data/lib/action_view/helpers/tags/base.rb +11 -9
- data/lib/action_view/helpers/tags/check_box.rb +2 -2
- data/lib/action_view/helpers/tags/collection_check_boxes.rb +4 -3
- data/lib/action_view/helpers/tags/file_field.rb +4 -1
- data/lib/action_view/helpers/tags/label.rb +3 -10
- data/lib/action_view/helpers/tags/radio_button.rb +1 -1
- data/lib/action_view/helpers/tags/select_renderer.rb +1 -1
- data/lib/action_view/helpers/tags/text_area.rb +1 -1
- data/lib/action_view/helpers/tags/text_field.rb +1 -1
- data/lib/action_view/helpers/url_helper.rb +2 -4
- data/lib/action_view/layouts.rb +1 -1
- data/lib/action_view/record_identifier.rb +1 -1
- data/lib/action_view/render_parser/prism_render_parser.rb +13 -1
- data/lib/action_view/render_parser/ripper_render_parser.rb +10 -1
- data/lib/action_view/renderer/partial_renderer/collection_caching.rb +5 -1
- data/lib/action_view/renderer/streaming_template_renderer.rb +8 -2
- data/lib/action_view/rendering.rb +2 -3
- data/lib/action_view/template/handlers/erb/erubi.rb +1 -1
- data/lib/action_view/template/raw_file.rb +4 -0
- data/lib/action_view/template/resolver.rb +0 -1
- data/lib/action_view/template.rb +9 -4
- metadata +13 -26
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "cgi"
|
|
3
|
+
require "cgi/escape"
|
|
4
|
+
require "cgi/util" if RUBY_VERSION < "3.5"
|
|
4
5
|
require "action_view/helpers/date_helper"
|
|
5
6
|
require "action_view/helpers/url_helper"
|
|
6
7
|
require "action_view/helpers/form_tag_helper"
|
|
@@ -30,20 +31,21 @@ module ActionView
|
|
|
30
31
|
# when the form is initially displayed, input fields corresponding to attributes
|
|
31
32
|
# of the resource should show the current values of those attributes.
|
|
32
33
|
#
|
|
33
|
-
# In \Rails, this is usually achieved by creating the form using
|
|
34
|
-
# a number of related helper methods.
|
|
35
|
-
#
|
|
36
|
-
#
|
|
37
|
-
#
|
|
34
|
+
# In \Rails, this is usually achieved by creating the form using either
|
|
35
|
+
# #form_with or #form_for and a number of related helper methods. These
|
|
36
|
+
# methods generate an appropriate <tt>form</tt> tag and yield a form
|
|
37
|
+
# builder object that knows the model the form is about. Input fields are
|
|
38
|
+
# created by calling methods defined on the form builder, which means they
|
|
39
|
+
# are able to generate the appropriate names and default values
|
|
38
40
|
# corresponding to the model attributes, as well as convenient IDs, etc.
|
|
39
|
-
# Conventions in the generated field names allow controllers to receive form
|
|
40
|
-
# nicely structured in +params+ with no effort on your side.
|
|
41
|
+
# Conventions in the generated field names allow controllers to receive form
|
|
42
|
+
# data nicely structured in +params+ with no effort on your side.
|
|
41
43
|
#
|
|
42
44
|
# For example, to create a new person you typically set up a new instance of
|
|
43
45
|
# +Person+ in the <tt>PeopleController#new</tt> action, <tt>@person</tt>, and
|
|
44
|
-
# in the view template pass that object to #form_for:
|
|
46
|
+
# in the view template pass that object to #form_with or #form_for:
|
|
45
47
|
#
|
|
46
|
-
# <%=
|
|
48
|
+
# <%= form_with model: @person do |f| %>
|
|
47
49
|
# <%= f.label :first_name %>:
|
|
48
50
|
# <%= f.text_field :first_name %><br />
|
|
49
51
|
#
|
|
@@ -132,8 +134,8 @@ module ActionView
|
|
|
132
134
|
# <%= form_for :person do |f| %>
|
|
133
135
|
# First name: <%= f.text_field :first_name %><br />
|
|
134
136
|
# Last name : <%= f.text_field :last_name %><br />
|
|
135
|
-
# Biography : <%= f.
|
|
136
|
-
# Admin? : <%= f.
|
|
137
|
+
# Biography : <%= f.textarea :biography %><br />
|
|
138
|
+
# Admin? : <%= f.checkbox :admin %><br />
|
|
137
139
|
# <%= f.submit %>
|
|
138
140
|
# <% end %>
|
|
139
141
|
#
|
|
@@ -199,8 +201,8 @@ module ActionView
|
|
|
199
201
|
# <%= form_for :person do |f| %>
|
|
200
202
|
# First name: <%= f.text_field :first_name %>
|
|
201
203
|
# Last name : <%= f.text_field :last_name %>
|
|
202
|
-
# Biography : <%=
|
|
203
|
-
# Admin? : <%=
|
|
204
|
+
# Biography : <%= textarea :person, :biography %>
|
|
205
|
+
# Admin? : <%= checkbox_tag "person[admin]", "1", @person.company.admin? %>
|
|
204
206
|
# <%= f.submit %>
|
|
205
207
|
# <% end %>
|
|
206
208
|
#
|
|
@@ -389,8 +391,8 @@ module ActionView
|
|
|
389
391
|
# <%= form_for @person, url: { action: "create" }, builder: LabellingFormBuilder do |f| %>
|
|
390
392
|
# <%= f.text_field :first_name %>
|
|
391
393
|
# <%= f.text_field :last_name %>
|
|
392
|
-
# <%= f.
|
|
393
|
-
# <%= f.
|
|
394
|
+
# <%= f.textarea :biography %>
|
|
395
|
+
# <%= f.checkbox :admin %>
|
|
394
396
|
# <%= f.submit %>
|
|
395
397
|
# <% end %>
|
|
396
398
|
#
|
|
@@ -668,8 +670,8 @@ module ActionView
|
|
|
668
670
|
# <%= form.text_field :first_name %>
|
|
669
671
|
# <%= form.text_field :last_name %>
|
|
670
672
|
#
|
|
671
|
-
# <%=
|
|
672
|
-
# <%=
|
|
673
|
+
# <%= textarea :person, :biography %>
|
|
674
|
+
# <%= checkbox_tag "person[admin]", "1", @person.company.admin? %>
|
|
673
675
|
#
|
|
674
676
|
# <%= form.submit %>
|
|
675
677
|
# <% end %>
|
|
@@ -730,8 +732,8 @@ module ActionView
|
|
|
730
732
|
# <%= form_with model: @person, url: { action: "create" }, builder: LabellingFormBuilder do |form| %>
|
|
731
733
|
# <%= form.text_field :first_name %>
|
|
732
734
|
# <%= form.text_field :last_name %>
|
|
733
|
-
# <%= form.
|
|
734
|
-
# <%= form.
|
|
735
|
+
# <%= form.textarea :biography %>
|
|
736
|
+
# <%= form.checkbox :admin %>
|
|
735
737
|
# <%= form.submit %>
|
|
736
738
|
# <% end %>
|
|
737
739
|
#
|
|
@@ -753,7 +755,7 @@ module ActionView
|
|
|
753
755
|
# form_with(**options.merge(builder: LabellingFormBuilder), &block)
|
|
754
756
|
# end
|
|
755
757
|
def form_with(model: false, scope: nil, url: nil, format: nil, **options, &block)
|
|
756
|
-
|
|
758
|
+
raise ArgumentError, "Passed nil to the :model argument, expect an object or false" if model.nil?
|
|
757
759
|
|
|
758
760
|
options = { allow_method_names_outside_object: true, skip_default_ids: !form_with_generates_ids }.merge!(options)
|
|
759
761
|
|
|
@@ -784,8 +786,8 @@ module ActionView
|
|
|
784
786
|
end
|
|
785
787
|
|
|
786
788
|
# Creates a scope around a specific model object like #form_with, but
|
|
787
|
-
# doesn't create the form tags themselves. This makes fields_for
|
|
788
|
-
# for specifying additional model objects in the same form.
|
|
789
|
+
# doesn't create the form tags themselves. This makes +fields_for+
|
|
790
|
+
# suitable for specifying additional model objects in the same form.
|
|
789
791
|
#
|
|
790
792
|
# Although the usage and purpose of +fields_for+ is similar to #form_with's,
|
|
791
793
|
# its method signature is slightly different. Like #form_with, it yields
|
|
@@ -804,7 +806,7 @@ module ActionView
|
|
|
804
806
|
# Last name : <%= person_form.text_field :last_name %>
|
|
805
807
|
#
|
|
806
808
|
# <%= fields_for :permission, @person.permission do |permission_fields| %>
|
|
807
|
-
# Admin? : <%= permission_fields.
|
|
809
|
+
# Admin? : <%= permission_fields.checkbox :admin %>
|
|
808
810
|
# <% end %>
|
|
809
811
|
#
|
|
810
812
|
# <%= person_form.submit %>
|
|
@@ -821,7 +823,7 @@ module ActionView
|
|
|
821
823
|
# object to +fields_for+ -
|
|
822
824
|
#
|
|
823
825
|
# <%= fields_for :permission do |permission_fields| %>
|
|
824
|
-
# Admin?: <%= permission_fields.
|
|
826
|
+
# Admin?: <%= permission_fields.checkbox :admin %>
|
|
825
827
|
# <% end %>
|
|
826
828
|
#
|
|
827
829
|
# ...in which case, if <tt>:permission</tt> also happens to be the name of an
|
|
@@ -833,7 +835,7 @@ module ActionView
|
|
|
833
835
|
# name has been omitted) -
|
|
834
836
|
#
|
|
835
837
|
# <%= fields_for @person.permission do |permission_fields| %>
|
|
836
|
-
# Admin?: <%= permission_fields.
|
|
838
|
+
# Admin?: <%= permission_fields.checkbox :admin %>
|
|
837
839
|
# <% end %>
|
|
838
840
|
#
|
|
839
841
|
# and +fields_for+ will derive the required name of the field from the
|
|
@@ -914,7 +916,7 @@ module ActionView
|
|
|
914
916
|
# ...
|
|
915
917
|
# <%= person_form.fields_for :address do |address_fields| %>
|
|
916
918
|
# ...
|
|
917
|
-
# Delete: <%= address_fields.
|
|
919
|
+
# Delete: <%= address_fields.checkbox :_destroy %>
|
|
918
920
|
# <% end %>
|
|
919
921
|
# ...
|
|
920
922
|
# <% end %>
|
|
@@ -1002,7 +1004,7 @@ module ActionView
|
|
|
1002
1004
|
# <%= form_with model: @person do |person_form| %>
|
|
1003
1005
|
# ...
|
|
1004
1006
|
# <%= person_form.fields_for :projects do |project_fields| %>
|
|
1005
|
-
# Delete: <%= project_fields.
|
|
1007
|
+
# Delete: <%= project_fields.checkbox :_destroy %>
|
|
1006
1008
|
# <% end %>
|
|
1007
1009
|
# ...
|
|
1008
1010
|
# <% end %>
|
|
@@ -1069,8 +1071,8 @@ module ActionView
|
|
|
1069
1071
|
# <%= fields model: @comment do |fields| %>
|
|
1070
1072
|
# <%= fields.text_field :body %>
|
|
1071
1073
|
#
|
|
1072
|
-
# <%=
|
|
1073
|
-
# <%=
|
|
1074
|
+
# <%= textarea :commenter, :biography %>
|
|
1075
|
+
# <%= checkbox_tag "comment[all_caps]", "1", @comment.commenter.hulk_mode? %>
|
|
1074
1076
|
# <% end %>
|
|
1075
1077
|
#
|
|
1076
1078
|
# Same goes for the methods in FormOptionsHelper and DateHelper designed
|
|
@@ -1255,28 +1257,29 @@ module ActionView
|
|
|
1255
1257
|
# hash with +options+.
|
|
1256
1258
|
#
|
|
1257
1259
|
# ==== Examples
|
|
1258
|
-
#
|
|
1260
|
+
# textarea(:article, :body, cols: 20, rows: 40)
|
|
1259
1261
|
# # => <textarea cols="20" rows="40" id="article_body" name="article[body]">
|
|
1260
1262
|
# # #{@article.body}
|
|
1261
1263
|
# # </textarea>
|
|
1262
1264
|
#
|
|
1263
|
-
#
|
|
1265
|
+
# textarea(:comment, :text, size: "20x30")
|
|
1264
1266
|
# # => <textarea cols="20" rows="30" id="comment_text" name="comment[text]">
|
|
1265
1267
|
# # #{@comment.text}
|
|
1266
1268
|
# # </textarea>
|
|
1267
1269
|
#
|
|
1268
|
-
#
|
|
1270
|
+
# textarea(:application, :notes, cols: 40, rows: 15, class: 'app_input')
|
|
1269
1271
|
# # => <textarea cols="40" rows="15" id="application_notes" name="application[notes]" class="app_input">
|
|
1270
1272
|
# # #{@application.notes}
|
|
1271
1273
|
# # </textarea>
|
|
1272
1274
|
#
|
|
1273
|
-
#
|
|
1275
|
+
# textarea(:entry, :body, size: "20x20", disabled: 'disabled')
|
|
1274
1276
|
# # => <textarea cols="20" rows="20" id="entry_body" name="entry[body]" disabled="disabled">
|
|
1275
1277
|
# # #{@entry.body}
|
|
1276
1278
|
# # </textarea>
|
|
1277
|
-
def
|
|
1279
|
+
def textarea(object_name, method, options = {})
|
|
1278
1280
|
Tags::TextArea.new(object_name, method, self, options).render
|
|
1279
1281
|
end
|
|
1282
|
+
alias_method :text_area, :textarea
|
|
1280
1283
|
|
|
1281
1284
|
# Returns a checkbox tag tailored for accessing a specified attribute (identified by +method+) on an object
|
|
1282
1285
|
# assigned to the template (identified by +object+). This object must be an instance object (@object) and not a local object.
|
|
@@ -1316,7 +1319,7 @@ module ActionView
|
|
|
1316
1319
|
# within an array-like parameter, as in
|
|
1317
1320
|
#
|
|
1318
1321
|
# <%= fields_for "project[invoice_attributes][]", invoice, index: nil do |form| %>
|
|
1319
|
-
# <%= form.
|
|
1322
|
+
# <%= form.checkbox :paid %>
|
|
1320
1323
|
# ...
|
|
1321
1324
|
# <% end %>
|
|
1322
1325
|
#
|
|
@@ -1324,27 +1327,28 @@ module ActionView
|
|
|
1324
1327
|
# the elements of the array. For each item with a checked check box you
|
|
1325
1328
|
# get an extra ghost item with only that attribute, assigned to "0".
|
|
1326
1329
|
#
|
|
1327
|
-
# In that case it is preferable to either use FormTagHelper#
|
|
1330
|
+
# In that case it is preferable to either use FormTagHelper#checkbox_tag or to use
|
|
1328
1331
|
# hashes instead of arrays.
|
|
1329
1332
|
#
|
|
1330
1333
|
# ==== Examples
|
|
1331
1334
|
#
|
|
1332
1335
|
# # Let's say that @article.validated? is 1:
|
|
1333
|
-
#
|
|
1336
|
+
# checkbox("article", "validated")
|
|
1334
1337
|
# # => <input name="article[validated]" type="hidden" value="0" />
|
|
1335
1338
|
# # <input checked="checked" type="checkbox" id="article_validated" name="article[validated]" value="1" />
|
|
1336
1339
|
#
|
|
1337
1340
|
# # Let's say that @puppy.gooddog is "no":
|
|
1338
|
-
#
|
|
1341
|
+
# checkbox("puppy", "gooddog", {}, "yes", "no")
|
|
1339
1342
|
# # => <input name="puppy[gooddog]" type="hidden" value="no" />
|
|
1340
1343
|
# # <input type="checkbox" id="puppy_gooddog" name="puppy[gooddog]" value="yes" />
|
|
1341
1344
|
#
|
|
1342
|
-
#
|
|
1345
|
+
# checkbox("eula", "accepted", { class: 'eula_check' }, "yes", "no")
|
|
1343
1346
|
# # => <input name="eula[accepted]" type="hidden" value="no" />
|
|
1344
1347
|
# # <input type="checkbox" class="eula_check" id="eula_accepted" name="eula[accepted]" value="yes" />
|
|
1345
|
-
def
|
|
1348
|
+
def checkbox(object_name, method, options = {}, checked_value = "1", unchecked_value = "0")
|
|
1346
1349
|
Tags::CheckBox.new(object_name, method, self, checked_value, unchecked_value, options).render
|
|
1347
1350
|
end
|
|
1351
|
+
alias_method :check_box, :checkbox
|
|
1348
1352
|
|
|
1349
1353
|
# Returns a radio button tag for accessing a specified attribute (identified by +method+) on an object
|
|
1350
1354
|
# assigned to the template (identified by +object+). If the current value of +method+ is +tag_value+ the
|
|
@@ -1634,12 +1638,12 @@ module ActionView
|
|
|
1634
1638
|
#
|
|
1635
1639
|
# <%= form_with model: @person do |person_form| %>
|
|
1636
1640
|
# Name: <%= person_form.text_field :name %>
|
|
1637
|
-
# Admin: <%= person_form.
|
|
1641
|
+
# Admin: <%= person_form.checkbox :admin %>
|
|
1638
1642
|
# <% end %>
|
|
1639
1643
|
#
|
|
1640
1644
|
# In the above block, a +FormBuilder+ object is yielded as the
|
|
1641
1645
|
# +person_form+ variable. This allows you to generate the +text_field+
|
|
1642
|
-
# and +
|
|
1646
|
+
# and +checkbox+ fields by specifying their eponymous methods, which
|
|
1643
1647
|
# modify the underlying template and associates the <tt>@person</tt> model object
|
|
1644
1648
|
# with the form.
|
|
1645
1649
|
#
|
|
@@ -1681,7 +1685,7 @@ module ActionView
|
|
|
1681
1685
|
# The methods which wrap a form helper call.
|
|
1682
1686
|
class_attribute :field_helpers, default: [
|
|
1683
1687
|
:fields_for, :fields, :label, :text_field, :password_field,
|
|
1684
|
-
:hidden_field, :file_field, :
|
|
1688
|
+
:hidden_field, :file_field, :textarea, :checkbox,
|
|
1685
1689
|
:radio_button, :color_field, :search_field,
|
|
1686
1690
|
:telephone_field, :phone_field, :date_field,
|
|
1687
1691
|
:time_field, :datetime_field, :datetime_local_field,
|
|
@@ -1824,14 +1828,14 @@ module ActionView
|
|
|
1824
1828
|
# Please refer to the documentation of the base helper for details.
|
|
1825
1829
|
|
|
1826
1830
|
##
|
|
1827
|
-
# :method:
|
|
1831
|
+
# :method: textarea
|
|
1828
1832
|
#
|
|
1829
|
-
# :call-seq:
|
|
1833
|
+
# :call-seq: textarea(method, options = {})
|
|
1830
1834
|
#
|
|
1831
|
-
# Wraps ActionView::Helpers::FormHelper#
|
|
1835
|
+
# Wraps ActionView::Helpers::FormHelper#textarea for form builders:
|
|
1832
1836
|
#
|
|
1833
1837
|
# <%= form_with model: @user do |f| %>
|
|
1834
|
-
# <%= f.
|
|
1838
|
+
# <%= f.textarea :detail %>
|
|
1835
1839
|
# <% end %>
|
|
1836
1840
|
#
|
|
1837
1841
|
# Please refer to the documentation of the base helper for details.
|
|
@@ -2019,24 +2023,20 @@ module ActionView
|
|
|
2019
2023
|
# Please refer to the documentation of the base helper for details.
|
|
2020
2024
|
|
|
2021
2025
|
ActiveSupport::CodeGenerator.batch(self, __FILE__, __LINE__) do |code_generator|
|
|
2022
|
-
(field_helpers - [:label, :
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
@template
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
method, # method,
|
|
2030
|
-
objectify_options(options)) # objectify_options(options))
|
|
2031
|
-
end # end
|
|
2032
|
-
RUBY_EVAL
|
|
2026
|
+
(field_helpers - [:label, :checkbox, :radio_button, :fields_for, :fields, :hidden_field, :file_field]).each do |selector|
|
|
2027
|
+
code_generator.class_eval do |batch|
|
|
2028
|
+
batch <<
|
|
2029
|
+
"def #{selector}(method, options = {})" <<
|
|
2030
|
+
" @template.#{selector}(@object_name, method, objectify_options(options))" <<
|
|
2031
|
+
"end"
|
|
2032
|
+
end
|
|
2033
2033
|
end
|
|
2034
|
-
end
|
|
2035
2034
|
end
|
|
2035
|
+
alias_method :text_area, :textarea
|
|
2036
2036
|
|
|
2037
2037
|
# Creates a scope around a specific model object like #form_with, but
|
|
2038
|
-
# doesn't create the form tags themselves. This makes fields_for
|
|
2039
|
-
# for specifying additional model objects in the same form.
|
|
2038
|
+
# doesn't create the form tags themselves. This makes +fields_for+
|
|
2039
|
+
# suitable for specifying additional model objects in the same form.
|
|
2040
2040
|
#
|
|
2041
2041
|
# Although the usage and purpose of +fields_for+ is similar to #form_with's,
|
|
2042
2042
|
# its method signature is slightly different. Like #form_with, it yields
|
|
@@ -2055,7 +2055,7 @@ module ActionView
|
|
|
2055
2055
|
# Last name : <%= person_form.text_field :last_name %>
|
|
2056
2056
|
#
|
|
2057
2057
|
# <%= fields_for :permission, @person.permission do |permission_fields| %>
|
|
2058
|
-
# Admin? : <%= permission_fields.
|
|
2058
|
+
# Admin? : <%= permission_fields.checkbox :admin %>
|
|
2059
2059
|
# <% end %>
|
|
2060
2060
|
#
|
|
2061
2061
|
# <%= person_form.submit %>
|
|
@@ -2072,7 +2072,7 @@ module ActionView
|
|
|
2072
2072
|
# object to +fields_for+ -
|
|
2073
2073
|
#
|
|
2074
2074
|
# <%= fields_for :permission do |permission_fields| %>
|
|
2075
|
-
# Admin?: <%= permission_fields.
|
|
2075
|
+
# Admin?: <%= permission_fields.checkbox :admin %>
|
|
2076
2076
|
# <% end %>
|
|
2077
2077
|
#
|
|
2078
2078
|
# ...in which case, if <tt>:permission</tt> also happens to be the name of an
|
|
@@ -2084,7 +2084,7 @@ module ActionView
|
|
|
2084
2084
|
# name has been omitted) -
|
|
2085
2085
|
#
|
|
2086
2086
|
# <%= fields_for @person.permission do |permission_fields| %>
|
|
2087
|
-
# Admin?: <%= permission_fields.
|
|
2087
|
+
# Admin?: <%= permission_fields.checkbox :admin %>
|
|
2088
2088
|
# <% end %>
|
|
2089
2089
|
#
|
|
2090
2090
|
# and +fields_for+ will derive the required name of the field from the
|
|
@@ -2102,7 +2102,7 @@ module ActionView
|
|
|
2102
2102
|
# <%= form_with model: @person do |person_form| %>
|
|
2103
2103
|
# ...
|
|
2104
2104
|
# <%= fields_for :permission, @person.permission, {} do |permission_fields| %>
|
|
2105
|
-
# Admin?: <%=
|
|
2105
|
+
# Admin?: <%= checkbox_tag permission_fields.field_name(:admin), @person.permission[:admin] %>
|
|
2106
2106
|
# <% end %>
|
|
2107
2107
|
# ...
|
|
2108
2108
|
# <% end %>
|
|
@@ -2177,7 +2177,7 @@ module ActionView
|
|
|
2177
2177
|
# ...
|
|
2178
2178
|
# <%= person_form.fields_for :address do |address_fields| %>
|
|
2179
2179
|
# ...
|
|
2180
|
-
# Delete: <%= address_fields.
|
|
2180
|
+
# Delete: <%= address_fields.checkbox :_destroy %>
|
|
2181
2181
|
# <% end %>
|
|
2182
2182
|
# ...
|
|
2183
2183
|
# <% end %>
|
|
@@ -2265,7 +2265,7 @@ module ActionView
|
|
|
2265
2265
|
# <%= form_with model: @person do |person_form| %>
|
|
2266
2266
|
# ...
|
|
2267
2267
|
# <%= person_form.fields_for :projects do |project_fields| %>
|
|
2268
|
-
# Delete: <%= project_fields.
|
|
2268
|
+
# Delete: <%= project_fields.checkbox :_destroy %>
|
|
2269
2269
|
# <% end %>
|
|
2270
2270
|
# ...
|
|
2271
2271
|
# <% end %>
|
|
@@ -2444,7 +2444,7 @@ module ActionView
|
|
|
2444
2444
|
# within an array-like parameter, as in
|
|
2445
2445
|
#
|
|
2446
2446
|
# <%= fields_for "project[invoice_attributes][]", invoice, index: nil do |form| %>
|
|
2447
|
-
# <%= form.
|
|
2447
|
+
# <%= form.checkbox :paid %>
|
|
2448
2448
|
# ...
|
|
2449
2449
|
# <% end %>
|
|
2450
2450
|
#
|
|
@@ -2452,28 +2452,29 @@ module ActionView
|
|
|
2452
2452
|
# the elements of the array. For each item with a checked check box you
|
|
2453
2453
|
# get an extra ghost item with only that attribute, assigned to "0".
|
|
2454
2454
|
#
|
|
2455
|
-
# In that case it is preferable to either use FormTagHelper#
|
|
2455
|
+
# In that case it is preferable to either use FormTagHelper#checkbox_tag or to use
|
|
2456
2456
|
# hashes instead of arrays.
|
|
2457
2457
|
#
|
|
2458
2458
|
# ==== Examples
|
|
2459
2459
|
#
|
|
2460
2460
|
# # Let's say that @article.validated? is 1:
|
|
2461
|
-
#
|
|
2461
|
+
# checkbox("validated")
|
|
2462
2462
|
# # => <input name="article[validated]" type="hidden" value="0" />
|
|
2463
2463
|
# # <input checked="checked" type="checkbox" id="article_validated" name="article[validated]" value="1" />
|
|
2464
2464
|
#
|
|
2465
2465
|
# # Let's say that @puppy.gooddog is "no":
|
|
2466
|
-
#
|
|
2466
|
+
# checkbox("gooddog", {}, "yes", "no")
|
|
2467
2467
|
# # => <input name="puppy[gooddog]" type="hidden" value="no" />
|
|
2468
2468
|
# # <input type="checkbox" id="puppy_gooddog" name="puppy[gooddog]" value="yes" />
|
|
2469
2469
|
#
|
|
2470
2470
|
# # Let's say that @eula.accepted is "no":
|
|
2471
|
-
#
|
|
2471
|
+
# checkbox("accepted", { class: 'eula_check' }, "yes", "no")
|
|
2472
2472
|
# # => <input name="eula[accepted]" type="hidden" value="no" />
|
|
2473
2473
|
# # <input type="checkbox" class="eula_check" id="eula_accepted" name="eula[accepted]" value="yes" />
|
|
2474
|
-
def
|
|
2475
|
-
@template.
|
|
2474
|
+
def checkbox(method, options = {}, checked_value = "1", unchecked_value = "0")
|
|
2475
|
+
@template.checkbox(@object_name, method, objectify_options(options), checked_value, unchecked_value)
|
|
2476
2476
|
end
|
|
2477
|
+
alias_method :check_box, :checkbox
|
|
2477
2478
|
|
|
2478
2479
|
# Returns a radio button tag for accessing a specified attribute (identified by +method+) on an object
|
|
2479
2480
|
# assigned to the template (identified by +object+). If the current value of +method+ is +tag_value+ the
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "cgi"
|
|
3
|
+
require "cgi/escape"
|
|
4
|
+
require "cgi/util" if RUBY_VERSION < "3.5"
|
|
4
5
|
require "erb"
|
|
5
6
|
require "active_support/core_ext/string/output_safety"
|
|
6
7
|
require "active_support/core_ext/array/extract_options"
|
|
@@ -689,7 +690,7 @@ module ActionView
|
|
|
689
690
|
# if a +User+ model has a +category_id+ field and in the form no category is selected, no +category_id+ parameter is sent. So,
|
|
690
691
|
# any strong parameters idiom like:
|
|
691
692
|
#
|
|
692
|
-
# params.
|
|
693
|
+
# params.expect(user: [...])
|
|
693
694
|
#
|
|
694
695
|
# will raise an error since no <tt>{user: ...}</tt> will be present.
|
|
695
696
|
#
|
|
@@ -726,7 +727,7 @@ module ActionView
|
|
|
726
727
|
# end
|
|
727
728
|
#
|
|
728
729
|
# Sample usage (selecting the associated Author for an instance of Post, <tt>@post</tt>):
|
|
729
|
-
#
|
|
730
|
+
# collection_checkboxes(:post, :author_ids, Author.all, :id, :name_with_initial)
|
|
730
731
|
#
|
|
731
732
|
# If <tt>@post.author_ids</tt> is already <tt>[1]</tt>, this would return:
|
|
732
733
|
# <input id="post_author_ids_1" name="post[author_ids][]" type="checkbox" value="1" checked="checked" />
|
|
@@ -739,8 +740,8 @@ module ActionView
|
|
|
739
740
|
#
|
|
740
741
|
# It is also possible to customize the way the elements will be shown by
|
|
741
742
|
# giving a block to the method:
|
|
742
|
-
#
|
|
743
|
-
# b.label { b.
|
|
743
|
+
# collection_checkboxes(:post, :author_ids, Author.all, :id, :name_with_initial) do |b|
|
|
744
|
+
# b.label { b.checkbox }
|
|
744
745
|
# end
|
|
745
746
|
#
|
|
746
747
|
# The argument passed to the block is a special kind of builder for this
|
|
@@ -749,17 +750,17 @@ module ActionView
|
|
|
749
750
|
# Using it, you can change the label and check box display order or even
|
|
750
751
|
# use the label as wrapper, as in the example above.
|
|
751
752
|
#
|
|
752
|
-
# The builder methods <tt>label</tt> and <tt>
|
|
753
|
+
# The builder methods <tt>label</tt> and <tt>checkbox</tt> also accept
|
|
753
754
|
# extra HTML options:
|
|
754
|
-
#
|
|
755
|
-
# b.label(class: "
|
|
755
|
+
# collection_checkboxes(:post, :author_ids, Author.all, :id, :name_with_initial) do |b|
|
|
756
|
+
# b.label(class: "checkbox") { b.checkbox(class: "checkbox") }
|
|
756
757
|
# end
|
|
757
758
|
#
|
|
758
759
|
# There are also three special methods available: <tt>object</tt>, <tt>text</tt> and
|
|
759
760
|
# <tt>value</tt>, which are the current item being rendered, its text and value methods,
|
|
760
761
|
# respectively. You can use them like this:
|
|
761
|
-
#
|
|
762
|
-
# b.label(:"data-value" => b.value) { b.
|
|
762
|
+
# collection_checkboxes(:post, :author_ids, Author.all, :id, :name_with_initial) do |b|
|
|
763
|
+
# b.label(:"data-value" => b.value) { b.checkbox + b.text }
|
|
763
764
|
# end
|
|
764
765
|
#
|
|
765
766
|
# ==== Gotcha
|
|
@@ -782,9 +783,10 @@ module ActionView
|
|
|
782
783
|
#
|
|
783
784
|
# In the rare case you don't want this hidden field, you can pass the
|
|
784
785
|
# <tt>include_hidden: false</tt> option to the helper method.
|
|
785
|
-
def
|
|
786
|
+
def collection_checkboxes(object, method, collection, value_method, text_method, options = {}, html_options = {}, &block)
|
|
786
787
|
Tags::CollectionCheckBoxes.new(object, method, self, collection, value_method, text_method, options, html_options).render(&block)
|
|
787
788
|
end
|
|
789
|
+
alias_method :collection_check_boxes, :collection_checkboxes
|
|
788
790
|
|
|
789
791
|
private
|
|
790
792
|
def option_html_attributes(element)
|
|
@@ -842,7 +844,7 @@ module ActionView
|
|
|
842
844
|
class FormBuilder
|
|
843
845
|
# Wraps ActionView::Helpers::FormOptionsHelper#select for form builders:
|
|
844
846
|
#
|
|
845
|
-
# <%=
|
|
847
|
+
# <%= form_with model: @post do |f| %>
|
|
846
848
|
# <%= f.select :person_id, Person.all.collect { |p| [ p.name, p.id ] }, include_blank: true %>
|
|
847
849
|
# <%= f.submit %>
|
|
848
850
|
# <% end %>
|
|
@@ -854,7 +856,7 @@ module ActionView
|
|
|
854
856
|
|
|
855
857
|
# Wraps ActionView::Helpers::FormOptionsHelper#collection_select for form builders:
|
|
856
858
|
#
|
|
857
|
-
# <%=
|
|
859
|
+
# <%= form_with model: @post do |f| %>
|
|
858
860
|
# <%= f.collection_select :person_id, Author.all, :id, :name_with_initial, prompt: true %>
|
|
859
861
|
# <%= f.submit %>
|
|
860
862
|
# <% end %>
|
|
@@ -866,7 +868,7 @@ module ActionView
|
|
|
866
868
|
|
|
867
869
|
# Wraps ActionView::Helpers::FormOptionsHelper#grouped_collection_select for form builders:
|
|
868
870
|
#
|
|
869
|
-
# <%=
|
|
871
|
+
# <%= form_with model: @city do |f| %>
|
|
870
872
|
# <%= f.grouped_collection_select :country_id, @continents, :countries, :name, :id, :name %>
|
|
871
873
|
# <%= f.submit %>
|
|
872
874
|
# <% end %>
|
|
@@ -878,7 +880,7 @@ module ActionView
|
|
|
878
880
|
|
|
879
881
|
# Wraps ActionView::Helpers::FormOptionsHelper#time_zone_select for form builders:
|
|
880
882
|
#
|
|
881
|
-
# <%=
|
|
883
|
+
# <%= form_with model: @user do |f| %>
|
|
882
884
|
# <%= f.time_zone_select :time_zone, nil, include_blank: true %>
|
|
883
885
|
# <%= f.submit %>
|
|
884
886
|
# <% end %>
|
|
@@ -890,7 +892,7 @@ module ActionView
|
|
|
890
892
|
|
|
891
893
|
# Wraps ActionView::Helpers::FormOptionsHelper#weekday_select for form builders:
|
|
892
894
|
#
|
|
893
|
-
# <%=
|
|
895
|
+
# <%= form_with model: @user do |f| %>
|
|
894
896
|
# <%= f.weekday_select :weekday, include_blank: true %>
|
|
895
897
|
# <%= f.submit %>
|
|
896
898
|
# <% end %>
|
|
@@ -900,21 +902,22 @@ module ActionView
|
|
|
900
902
|
@template.weekday_select(@object_name, method, objectify_options(options), @default_html_options.merge(html_options))
|
|
901
903
|
end
|
|
902
904
|
|
|
903
|
-
# Wraps ActionView::Helpers::FormOptionsHelper#
|
|
905
|
+
# Wraps ActionView::Helpers::FormOptionsHelper#collection_checkboxes for form builders:
|
|
904
906
|
#
|
|
905
|
-
# <%=
|
|
906
|
-
# <%= f.
|
|
907
|
+
# <%= form_with model: @post do |f| %>
|
|
908
|
+
# <%= f.collection_checkboxes :author_ids, Author.all, :id, :name_with_initial %>
|
|
907
909
|
# <%= f.submit %>
|
|
908
910
|
# <% end %>
|
|
909
911
|
#
|
|
910
912
|
# Please refer to the documentation of the base helper for details.
|
|
911
|
-
def
|
|
912
|
-
@template.
|
|
913
|
+
def collection_checkboxes(method, collection, value_method, text_method, options = {}, html_options = {}, &block)
|
|
914
|
+
@template.collection_checkboxes(@object_name, method, collection, value_method, text_method, objectify_options(options), @default_html_options.merge(html_options), &block)
|
|
913
915
|
end
|
|
916
|
+
alias_method :collection_check_boxes, :collection_checkboxes
|
|
914
917
|
|
|
915
918
|
# Wraps ActionView::Helpers::FormOptionsHelper#collection_radio_buttons for form builders:
|
|
916
919
|
#
|
|
917
|
-
# <%=
|
|
920
|
+
# <%= form_with model: @post do |f| %>
|
|
918
921
|
# <%= f.collection_radio_buttons :author_id, Author.all, :id, :name_with_initial %>
|
|
919
922
|
# <%= f.submit %>
|
|
920
923
|
# <% end %>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "cgi"
|
|
3
|
+
require "cgi/escape"
|
|
4
|
+
require "cgi/util" if RUBY_VERSION < "3.5"
|
|
4
5
|
require "action_view/helpers/content_exfiltration_prevention_helper"
|
|
5
6
|
require "action_view/helpers/url_helper"
|
|
6
7
|
require "action_view/helpers/text_helper"
|
|
@@ -393,24 +394,24 @@ module ActionView
|
|
|
393
394
|
# * Any other key creates standard HTML attributes for the tag.
|
|
394
395
|
#
|
|
395
396
|
# ==== Examples
|
|
396
|
-
#
|
|
397
|
+
# textarea_tag 'post'
|
|
397
398
|
# # => <textarea id="post" name="post"></textarea>
|
|
398
399
|
#
|
|
399
|
-
#
|
|
400
|
+
# textarea_tag 'bio', @user.bio
|
|
400
401
|
# # => <textarea id="bio" name="bio">This is my biography.</textarea>
|
|
401
402
|
#
|
|
402
|
-
#
|
|
403
|
+
# textarea_tag 'body', nil, rows: 10, cols: 25
|
|
403
404
|
# # => <textarea cols="25" id="body" name="body" rows="10"></textarea>
|
|
404
405
|
#
|
|
405
|
-
#
|
|
406
|
+
# textarea_tag 'body', nil, size: "25x10"
|
|
406
407
|
# # => <textarea name="body" id="body" cols="25" rows="10"></textarea>
|
|
407
408
|
#
|
|
408
|
-
#
|
|
409
|
+
# textarea_tag 'description', "Description goes here.", disabled: true
|
|
409
410
|
# # => <textarea disabled="disabled" id="description" name="description">Description goes here.</textarea>
|
|
410
411
|
#
|
|
411
|
-
#
|
|
412
|
+
# textarea_tag 'comment', nil, class: 'comment_input'
|
|
412
413
|
# # => <textarea class="comment_input" id="comment" name="comment"></textarea>
|
|
413
|
-
def
|
|
414
|
+
def textarea_tag(name, content = nil, options = {})
|
|
414
415
|
options = options.stringify_keys
|
|
415
416
|
|
|
416
417
|
if size = options.delete("size")
|
|
@@ -422,12 +423,13 @@ module ActionView
|
|
|
422
423
|
|
|
423
424
|
content_tag :textarea, content.to_s.html_safe, { "name" => name, "id" => sanitize_to_id(name) }.update(options)
|
|
424
425
|
end
|
|
426
|
+
alias_method :text_area_tag, :textarea_tag
|
|
425
427
|
|
|
426
428
|
##
|
|
427
429
|
# :call-seq:
|
|
428
|
-
#
|
|
429
|
-
#
|
|
430
|
-
#
|
|
430
|
+
# checkbox_tag(name, options = {})
|
|
431
|
+
# checkbox_tag(name, value, options = {})
|
|
432
|
+
# checkbox_tag(name, value, checked, options = {})
|
|
431
433
|
#
|
|
432
434
|
# Creates a check box form input tag.
|
|
433
435
|
#
|
|
@@ -438,21 +440,21 @@ module ActionView
|
|
|
438
440
|
# * Any other key creates standard HTML options for the tag.
|
|
439
441
|
#
|
|
440
442
|
# ==== Examples
|
|
441
|
-
#
|
|
443
|
+
# checkbox_tag 'accept'
|
|
442
444
|
# # => <input id="accept" name="accept" type="checkbox" value="1" />
|
|
443
445
|
#
|
|
444
|
-
#
|
|
446
|
+
# checkbox_tag 'rock', 'rock music'
|
|
445
447
|
# # => <input id="rock" name="rock" type="checkbox" value="rock music" />
|
|
446
448
|
#
|
|
447
|
-
#
|
|
449
|
+
# checkbox_tag 'receive_email', 'yes', true
|
|
448
450
|
# # => <input checked="checked" id="receive_email" name="receive_email" type="checkbox" value="yes" />
|
|
449
451
|
#
|
|
450
|
-
#
|
|
452
|
+
# checkbox_tag 'tos', 'yes', false, class: 'accept_tos'
|
|
451
453
|
# # => <input class="accept_tos" id="tos" name="tos" type="checkbox" value="yes" />
|
|
452
454
|
#
|
|
453
|
-
#
|
|
455
|
+
# checkbox_tag 'eula', 'accepted', false, disabled: true
|
|
454
456
|
# # => <input disabled="disabled" id="eula" name="eula" type="checkbox" value="accepted" />
|
|
455
|
-
def
|
|
457
|
+
def checkbox_tag(name, *args)
|
|
456
458
|
if args.length >= 4
|
|
457
459
|
raise ArgumentError, "wrong number of arguments (given #{args.length + 1}, expected 1..4)"
|
|
458
460
|
end
|
|
@@ -462,6 +464,7 @@ module ActionView
|
|
|
462
464
|
html_options["checked"] = "checked" if checked
|
|
463
465
|
tag :input, html_options
|
|
464
466
|
end
|
|
467
|
+
alias_method :check_box_tag, :checkbox_tag
|
|
465
468
|
|
|
466
469
|
##
|
|
467
470
|
# :call-seq:
|