actionview 5.1.4 → 6.1.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of actionview might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +199 -168
- data/MIT-LICENSE +1 -1
- data/README.rdoc +7 -5
- data/lib/action_view.rb +10 -4
- data/lib/action_view/base.rb +87 -23
- data/lib/action_view/buffers.rb +17 -0
- data/lib/action_view/cache_expiry.rb +52 -0
- data/lib/action_view/context.rb +7 -11
- data/lib/action_view/dependency_tracker.rb +12 -4
- data/lib/action_view/digestor.rb +24 -23
- data/lib/action_view/flows.rb +2 -1
- data/lib/action_view/gem_version.rb +4 -2
- data/lib/action_view/helpers.rb +4 -2
- data/lib/action_view/helpers/active_model_helper.rb +9 -4
- data/lib/action_view/helpers/asset_tag_helper.rb +220 -57
- data/lib/action_view/helpers/asset_url_helper.rb +28 -23
- data/lib/action_view/helpers/atom_feed_helper.rb +5 -2
- data/lib/action_view/helpers/cache_helper.rb +39 -28
- data/lib/action_view/helpers/capture_helper.rb +13 -7
- data/lib/action_view/helpers/controller_helper.rb +3 -1
- data/lib/action_view/helpers/csp_helper.rb +26 -0
- data/lib/action_view/helpers/csrf_helper.rb +5 -3
- data/lib/action_view/helpers/date_helper.rb +78 -33
- data/lib/action_view/helpers/debug_helper.rb +4 -2
- data/lib/action_view/helpers/form_helper.rb +357 -106
- data/lib/action_view/helpers/form_options_helper.rb +45 -39
- data/lib/action_view/helpers/form_tag_helper.rb +42 -27
- data/lib/action_view/helpers/javascript_helper.rb +28 -12
- data/lib/action_view/helpers/number_helper.rb +16 -8
- data/lib/action_view/helpers/output_safety_helper.rb +3 -1
- data/lib/action_view/helpers/rendering_helper.rb +20 -9
- data/lib/action_view/helpers/sanitize_helper.rb +15 -19
- data/lib/action_view/helpers/tag_helper.rb +100 -24
- data/lib/action_view/helpers/tags.rb +3 -1
- data/lib/action_view/helpers/tags/base.rb +30 -21
- data/lib/action_view/helpers/tags/check_box.rb +3 -2
- data/lib/action_view/helpers/tags/checkable.rb +4 -2
- data/lib/action_view/helpers/tags/collection_check_boxes.rb +2 -1
- data/lib/action_view/helpers/tags/collection_helpers.rb +2 -1
- data/lib/action_view/helpers/tags/collection_radio_buttons.rb +2 -1
- data/lib/action_view/helpers/tags/collection_select.rb +3 -1
- data/lib/action_view/helpers/tags/color_field.rb +4 -3
- data/lib/action_view/helpers/tags/date_field.rb +3 -2
- data/lib/action_view/helpers/tags/date_select.rb +5 -4
- data/lib/action_view/helpers/tags/datetime_field.rb +3 -2
- data/lib/action_view/helpers/tags/datetime_local_field.rb +3 -2
- data/lib/action_view/helpers/tags/datetime_select.rb +2 -0
- data/lib/action_view/helpers/tags/email_field.rb +2 -0
- data/lib/action_view/helpers/tags/file_field.rb +2 -0
- data/lib/action_view/helpers/tags/grouped_collection_select.rb +3 -1
- data/lib/action_view/helpers/tags/hidden_field.rb +2 -0
- data/lib/action_view/helpers/tags/label.rb +6 -5
- data/lib/action_view/helpers/tags/month_field.rb +3 -2
- data/lib/action_view/helpers/tags/number_field.rb +2 -0
- data/lib/action_view/helpers/tags/password_field.rb +2 -0
- data/lib/action_view/helpers/tags/placeholderable.rb +2 -0
- data/lib/action_view/helpers/tags/radio_button.rb +3 -2
- data/lib/action_view/helpers/tags/range_field.rb +2 -0
- data/lib/action_view/helpers/tags/search_field.rb +2 -0
- data/lib/action_view/helpers/tags/select.rb +4 -3
- data/lib/action_view/helpers/tags/tel_field.rb +2 -0
- data/lib/action_view/helpers/tags/text_area.rb +3 -1
- data/lib/action_view/helpers/tags/text_field.rb +3 -2
- data/lib/action_view/helpers/tags/time_field.rb +3 -2
- data/lib/action_view/helpers/tags/time_select.rb +2 -0
- data/lib/action_view/helpers/tags/time_zone_select.rb +3 -1
- data/lib/action_view/helpers/tags/translator.rb +3 -6
- data/lib/action_view/helpers/tags/url_field.rb +2 -0
- data/lib/action_view/helpers/tags/week_field.rb +3 -2
- data/lib/action_view/helpers/text_helper.rb +11 -10
- data/lib/action_view/helpers/translation_helper.rb +102 -52
- data/lib/action_view/helpers/url_helper.rb +150 -32
- data/lib/action_view/layouts.rb +15 -15
- data/lib/action_view/log_subscriber.rb +32 -15
- data/lib/action_view/lookup_context.rb +67 -39
- data/lib/action_view/model_naming.rb +2 -0
- data/lib/action_view/path_set.rb +5 -12
- data/lib/action_view/railtie.rb +46 -21
- data/lib/action_view/record_identifier.rb +4 -3
- data/lib/action_view/renderer/abstract_renderer.rb +144 -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.rb +33 -283
- data/lib/action_view/renderer/partial_renderer/collection_caching.rb +64 -17
- data/lib/action_view/renderer/renderer.rb +61 -4
- data/lib/action_view/renderer/streaming_template_renderer.rb +14 -8
- data/lib/action_view/renderer/template_renderer.rb +36 -26
- data/lib/action_view/rendering.rb +57 -38
- data/lib/action_view/routing_url_for.rb +15 -12
- data/lib/action_view/tasks/cache_digests.rake +2 -0
- data/lib/action_view/template.rb +69 -76
- data/lib/action_view/template/error.rb +32 -18
- data/lib/action_view/template/handlers.rb +4 -2
- data/lib/action_view/template/handlers/builder.rb +5 -6
- data/lib/action_view/template/handlers/erb.rb +20 -19
- data/lib/action_view/template/handlers/erb/erubi.rb +17 -9
- data/lib/action_view/template/handlers/html.rb +3 -1
- data/lib/action_view/template/handlers/raw.rb +4 -2
- data/lib/action_view/template/html.rb +8 -7
- 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 +194 -152
- data/lib/action_view/template/sources.rb +13 -0
- data/lib/action_view/template/sources/file.rb +17 -0
- data/lib/action_view/template/text.rb +5 -4
- data/lib/action_view/template/types.rb +3 -1
- data/lib/action_view/test_case.rb +38 -30
- data/lib/action_view/testing/resolvers.rb +20 -27
- data/lib/action_view/unbound_template.rb +31 -0
- data/lib/action_view/version.rb +2 -0
- data/lib/action_view/view_paths.rb +61 -40
- data/lib/assets/compiled/rails-ujs.js +84 -23
- metadata +34 -23
- data/lib/action_view/helpers/record_tag_helper.rb +0 -21
- data/lib/action_view/template/handlers/erb/deprecated_erubis.rb +0 -9
- data/lib/action_view/template/handlers/erb/erubis.rb +0 -81
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "cgi"
|
2
4
|
require "erb"
|
3
5
|
require "action_view/helpers/form_helper"
|
@@ -7,19 +9,19 @@ require "active_support/core_ext/array/wrap"
|
|
7
9
|
|
8
10
|
module ActionView
|
9
11
|
# = Action View Form Option Helpers
|
10
|
-
module Helpers
|
12
|
+
module Helpers #:nodoc:
|
11
13
|
# Provides a number of methods for turning different kinds of containers into a set of option tags.
|
12
14
|
#
|
13
15
|
# The <tt>collection_select</tt>, <tt>select</tt> and <tt>time_zone_select</tt> methods take an <tt>options</tt> parameter, a hash:
|
14
16
|
#
|
15
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.
|
16
18
|
#
|
17
|
-
# select("post", "category", Post::CATEGORIES, {include_blank: true})
|
19
|
+
# select("post", "category", Post::CATEGORIES, { include_blank: true })
|
18
20
|
#
|
19
21
|
# could become:
|
20
22
|
#
|
21
23
|
# <select name="post[category]" id="post_category">
|
22
|
-
# <option value=""></option>
|
24
|
+
# <option value="" label=" "></option>
|
23
25
|
# <option value="joke">joke</option>
|
24
26
|
# <option value="poem">poem</option>
|
25
27
|
# </select>
|
@@ -28,7 +30,7 @@ module ActionView
|
|
28
30
|
#
|
29
31
|
# Example with <tt>@post.person_id => 2</tt>:
|
30
32
|
#
|
31
|
-
# 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' })
|
32
34
|
#
|
33
35
|
# could become:
|
34
36
|
#
|
@@ -41,7 +43,7 @@ module ActionView
|
|
41
43
|
#
|
42
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.
|
43
45
|
#
|
44
|
-
# 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' })
|
45
47
|
#
|
46
48
|
# could become:
|
47
49
|
#
|
@@ -67,12 +69,11 @@ module ActionView
|
|
67
69
|
#
|
68
70
|
# * <tt>:disabled</tt> - can be a single value or an array of values that will be disabled options in the final output.
|
69
71
|
#
|
70
|
-
# select("post", "category", Post::CATEGORIES, {disabled: 'restricted'})
|
72
|
+
# select("post", "category", Post::CATEGORIES, { disabled: 'restricted' })
|
71
73
|
#
|
72
74
|
# could become:
|
73
75
|
#
|
74
76
|
# <select name="post[category]" id="post_category">
|
75
|
-
# <option value=""></option>
|
76
77
|
# <option value="joke">joke</option>
|
77
78
|
# <option value="poem">poem</option>
|
78
79
|
# <option disabled="disabled" value="restricted">restricted</option>
|
@@ -80,7 +81,7 @@ module ActionView
|
|
80
81
|
#
|
81
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.
|
82
83
|
#
|
83
|
-
# 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? } })
|
84
85
|
#
|
85
86
|
# If the categories "2008 stuff" and "Christmas" return true when the method <tt>archived?</tt> is called, this would return:
|
86
87
|
# <select name="post[category_id]" id="post_category_id">
|
@@ -105,12 +106,12 @@ module ActionView
|
|
105
106
|
#
|
106
107
|
# For example:
|
107
108
|
#
|
108
|
-
# 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 })
|
109
110
|
#
|
110
111
|
# would become:
|
111
112
|
#
|
112
113
|
# <select name="post[person_id]" id="post_person_id">
|
113
|
-
# <option value=""></option>
|
114
|
+
# <option value="" label=" "></option>
|
114
115
|
# <option value="1" selected="selected">David</option>
|
115
116
|
# <option value="2">Eileen</option>
|
116
117
|
# <option value="3">Rafael</option>
|
@@ -141,7 +142,7 @@ module ActionView
|
|
141
142
|
#
|
142
143
|
# The HTML specification says when +multiple+ parameter passed to select and all options got deselected
|
143
144
|
# web browsers do not send any value to server. Unfortunately this introduces a gotcha:
|
144
|
-
# if
|
145
|
+
# if a +User+ model has many +roles+ and have +role_ids+ accessor, and in the form that edits roles of the user
|
145
146
|
# the user deselects all roles from +role_ids+ multiple select box, no +role_ids+ parameter is sent. So,
|
146
147
|
# any mass-assignment idiom like
|
147
148
|
#
|
@@ -212,9 +213,13 @@ module ActionView
|
|
212
213
|
# * +method+ - The attribute of +object+ corresponding to the select tag
|
213
214
|
# * +collection+ - An array of objects representing the <tt><optgroup></tt> tags.
|
214
215
|
# * +group_method+ - The name of a method which, when called on a member of +collection+, returns an
|
215
|
-
# array of child objects representing the <tt><option></tt> tags.
|
216
|
+
# array of child objects representing the <tt><option></tt> tags. It can also be any object that responds
|
217
|
+
# to +call+, such as a +proc+, that will be called for each member of the +collection+ to retrieve the
|
218
|
+
# value.
|
216
219
|
# * +group_label_method+ - The name of a method which, when called on a member of +collection+, returns a
|
217
|
-
# string to be used as the +label+ attribute for its <tt><optgroup></tt> tag.
|
220
|
+
# string to be used as the +label+ attribute for its <tt><optgroup></tt> tag. It can also be any object
|
221
|
+
# that responds to +call+, such as a +proc+, that will be called for each member of the +collection+ to
|
222
|
+
# retrieve the label.
|
218
223
|
# * +option_key_method+ - The name of a method which, when called on a child object of a member of
|
219
224
|
# +collection+, returns a value to be used as the +value+ attribute for its <tt><option></tt> tag.
|
220
225
|
# * +option_value_method+ - The name of a method which, when called on a child object of a member of
|
@@ -277,17 +282,17 @@ module ActionView
|
|
277
282
|
# Finally, this method supports a <tt>:default</tt> option, which selects
|
278
283
|
# a default ActiveSupport::TimeZone if the object's time zone is +nil+.
|
279
284
|
#
|
280
|
-
# time_zone_select(
|
285
|
+
# time_zone_select("user", "time_zone", nil, include_blank: true)
|
281
286
|
#
|
282
|
-
# time_zone_select(
|
287
|
+
# time_zone_select("user", "time_zone", nil, default: "Pacific Time (US & Canada)")
|
283
288
|
#
|
284
|
-
# time_zone_select(
|
289
|
+
# time_zone_select("user", 'time_zone', ActiveSupport::TimeZone.us_zones, default: "Pacific Time (US & Canada)")
|
285
290
|
#
|
286
|
-
# time_zone_select(
|
291
|
+
# time_zone_select("user", 'time_zone', [ ActiveSupport::TimeZone['Alaska'], ActiveSupport::TimeZone['Hawaii'] ])
|
287
292
|
#
|
288
|
-
# time_zone_select(
|
293
|
+
# time_zone_select("user", 'time_zone', /Australia/)
|
289
294
|
#
|
290
|
-
# time_zone_select(
|
295
|
+
# time_zone_select("user", "time_zone", ActiveSupport::TimeZone.all.sort, model: ActiveSupport::TimeZone)
|
291
296
|
def time_zone_select(object, method, priority_zones = nil, options = {}, html_options = {})
|
292
297
|
Tags::TimeZoneSelect.new(object, method, self, priority_zones, options, html_options).render
|
293
298
|
end
|
@@ -317,12 +322,12 @@ module ActionView
|
|
317
322
|
#
|
318
323
|
# You can optionally provide HTML attributes as the last element of the array.
|
319
324
|
#
|
320
|
-
# options_for_select([ "Denmark", ["USA", {class: 'bold'}], "Sweden" ], ["USA", "Sweden"])
|
325
|
+
# options_for_select([ "Denmark", ["USA", { class: 'bold' }], "Sweden" ], ["USA", "Sweden"])
|
321
326
|
# # => <option value="Denmark">Denmark</option>
|
322
327
|
# # => <option value="USA" class="bold" selected="selected">USA</option>
|
323
328
|
# # => <option value="Sweden" selected="selected">Sweden</option>
|
324
329
|
#
|
325
|
-
# options_for_select([["Dollar", "$", {class: "bold"}], ["Kroner", "DKK", {onclick: "alert('HI');"}]])
|
330
|
+
# options_for_select([["Dollar", "$", { class: "bold" }], ["Kroner", "DKK", { onclick: "alert('HI');" }]])
|
326
331
|
# # => <option value="$" class="bold">Dollar</option>
|
327
332
|
# # => <option value="DKK" onclick="alert('HI');">Kroner</option>
|
328
333
|
#
|
@@ -455,9 +460,9 @@ module ActionView
|
|
455
460
|
def option_groups_from_collection_for_select(collection, group_method, group_label_method, option_key_method, option_value_method, selected_key = nil)
|
456
461
|
collection.map do |group|
|
457
462
|
option_tags = options_from_collection_for_select(
|
458
|
-
group
|
463
|
+
value_for_collection(group, group_method), option_key_method, option_value_method, selected_key)
|
459
464
|
|
460
|
-
content_tag("optgroup"
|
465
|
+
content_tag("optgroup", option_tags, label: value_for_collection(group, group_label_method))
|
461
466
|
end.join.html_safe
|
462
467
|
end
|
463
468
|
|
@@ -529,7 +534,7 @@ module ActionView
|
|
529
534
|
body = "".html_safe
|
530
535
|
|
531
536
|
if prompt
|
532
|
-
body.safe_concat content_tag("option"
|
537
|
+
body.safe_concat content_tag("option", prompt_text(prompt), value: "")
|
533
538
|
end
|
534
539
|
|
535
540
|
grouped_options.each do |container|
|
@@ -542,7 +547,7 @@ module ActionView
|
|
542
547
|
end
|
543
548
|
|
544
549
|
html_attributes = { label: label }.merge!(html_attributes)
|
545
|
-
body.safe_concat content_tag("optgroup"
|
550
|
+
body.safe_concat content_tag("optgroup", options_for_select(container, selected_key), html_attributes)
|
546
551
|
end
|
547
552
|
|
548
553
|
body
|
@@ -560,9 +565,10 @@ module ActionView
|
|
560
565
|
# an ActiveSupport::TimeZone.
|
561
566
|
#
|
562
567
|
# By default, +model+ is the ActiveSupport::TimeZone constant (which can
|
563
|
-
# be obtained in Active Record as a value object). The
|
564
|
-
#
|
565
|
-
#
|
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.
|
566
572
|
#
|
567
573
|
# NOTE: Only the option tags are returned, you have to wrap this call in
|
568
574
|
# a regular HTML select tag.
|
@@ -574,11 +580,11 @@ module ActionView
|
|
574
580
|
|
575
581
|
if priority_zones
|
576
582
|
if priority_zones.is_a?(Regexp)
|
577
|
-
priority_zones = zones.select { |z| z
|
583
|
+
priority_zones = zones.select { |z| z.match?(priority_zones) }
|
578
584
|
end
|
579
585
|
|
580
586
|
zone_options.safe_concat options_for_select(convert_zones[priority_zones], selected)
|
581
|
-
zone_options.safe_concat content_tag("option"
|
587
|
+
zone_options.safe_concat content_tag("option", "-------------", value: "", disabled: true)
|
582
588
|
zone_options.safe_concat "\n"
|
583
589
|
|
584
590
|
zones = zones - priority_zones
|
@@ -648,7 +654,7 @@ module ActionView
|
|
648
654
|
#
|
649
655
|
# ==== Gotcha
|
650
656
|
#
|
651
|
-
# The HTML specification says when nothing is
|
657
|
+
# The HTML specification says when nothing is selected on a collection of radio buttons
|
652
658
|
# web browsers do not send any value to server.
|
653
659
|
# Unfortunately this introduces a gotcha:
|
654
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,
|
@@ -788,7 +794,7 @@ module ActionView
|
|
788
794
|
def extract_values_from_collection(collection, value_method, selected)
|
789
795
|
if selected.is_a?(Proc)
|
790
796
|
collection.map do |element|
|
791
|
-
element.
|
797
|
+
element.public_send(value_method) if selected.call(element)
|
792
798
|
end.compact
|
793
799
|
else
|
794
800
|
selected
|
@@ -796,7 +802,7 @@ module ActionView
|
|
796
802
|
end
|
797
803
|
|
798
804
|
def value_for_collection(item, value)
|
799
|
-
value.respond_to?(:call) ? value.call(item) : item.
|
805
|
+
value.respond_to?(:call) ? value.call(item) : item.public_send(value)
|
800
806
|
end
|
801
807
|
|
802
808
|
def prompt_text(prompt)
|
@@ -814,7 +820,7 @@ module ActionView
|
|
814
820
|
#
|
815
821
|
# Please refer to the documentation of the base helper for details.
|
816
822
|
def select(method, choices = nil, options = {}, html_options = {}, &block)
|
817
|
-
@template.select(@object_name, method, choices, objectify_options(options), @
|
823
|
+
@template.select(@object_name, method, choices, objectify_options(options), @default_html_options.merge(html_options), &block)
|
818
824
|
end
|
819
825
|
|
820
826
|
# Wraps ActionView::Helpers::FormOptionsHelper#collection_select for form builders:
|
@@ -826,7 +832,7 @@ module ActionView
|
|
826
832
|
#
|
827
833
|
# Please refer to the documentation of the base helper for details.
|
828
834
|
def collection_select(method, collection, value_method, text_method, options = {}, html_options = {})
|
829
|
-
@template.collection_select(@object_name, method, collection, value_method, text_method, objectify_options(options), @
|
835
|
+
@template.collection_select(@object_name, method, collection, value_method, text_method, objectify_options(options), @default_html_options.merge(html_options))
|
830
836
|
end
|
831
837
|
|
832
838
|
# Wraps ActionView::Helpers::FormOptionsHelper#grouped_collection_select for form builders:
|
@@ -838,7 +844,7 @@ module ActionView
|
|
838
844
|
#
|
839
845
|
# Please refer to the documentation of the base helper for details.
|
840
846
|
def grouped_collection_select(method, collection, group_method, group_label_method, option_key_method, option_value_method, options = {}, html_options = {})
|
841
|
-
@template.grouped_collection_select(@object_name, method, collection, group_method, group_label_method, option_key_method, option_value_method, objectify_options(options), @
|
847
|
+
@template.grouped_collection_select(@object_name, method, collection, group_method, group_label_method, option_key_method, option_value_method, objectify_options(options), @default_html_options.merge(html_options))
|
842
848
|
end
|
843
849
|
|
844
850
|
# Wraps ActionView::Helpers::FormOptionsHelper#time_zone_select for form builders:
|
@@ -850,7 +856,7 @@ module ActionView
|
|
850
856
|
#
|
851
857
|
# Please refer to the documentation of the base helper for details.
|
852
858
|
def time_zone_select(method, priority_zones = nil, options = {}, html_options = {})
|
853
|
-
@template.time_zone_select(@object_name, method, priority_zones, objectify_options(options), @
|
859
|
+
@template.time_zone_select(@object_name, method, priority_zones, objectify_options(options), @default_html_options.merge(html_options))
|
854
860
|
end
|
855
861
|
|
856
862
|
# Wraps ActionView::Helpers::FormOptionsHelper#collection_check_boxes for form builders:
|
@@ -862,7 +868,7 @@ module ActionView
|
|
862
868
|
#
|
863
869
|
# Please refer to the documentation of the base helper for details.
|
864
870
|
def collection_check_boxes(method, collection, value_method, text_method, options = {}, html_options = {}, &block)
|
865
|
-
@template.collection_check_boxes(@object_name, method, collection, value_method, text_method, objectify_options(options), @
|
871
|
+
@template.collection_check_boxes(@object_name, method, collection, value_method, text_method, objectify_options(options), @default_html_options.merge(html_options), &block)
|
866
872
|
end
|
867
873
|
|
868
874
|
# Wraps ActionView::Helpers::FormOptionsHelper#collection_radio_buttons for form builders:
|
@@ -874,7 +880,7 @@ module ActionView
|
|
874
880
|
#
|
875
881
|
# Please refer to the documentation of the base helper for details.
|
876
882
|
def collection_radio_buttons(method, collection, value_method, text_method, options = {}, html_options = {}, &block)
|
877
|
-
@template.collection_radio_buttons(@object_name, method, collection, value_method, text_method, objectify_options(options), @
|
883
|
+
@template.collection_radio_buttons(@object_name, method, collection, value_method, text_method, objectify_options(options), @default_html_options.merge(html_options), &block)
|
878
884
|
end
|
879
885
|
end
|
880
886
|
end
|
@@ -1,11 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "cgi"
|
2
4
|
require "action_view/helpers/tag_helper"
|
3
5
|
require "active_support/core_ext/string/output_safety"
|
4
6
|
require "active_support/core_ext/module/attribute_accessors"
|
7
|
+
require "active_support/core_ext/symbol/starts_ends_with"
|
5
8
|
|
6
9
|
module ActionView
|
7
10
|
# = Action View Form Tag Helpers
|
8
|
-
module Helpers
|
11
|
+
module Helpers #:nodoc:
|
9
12
|
# Provides a number of methods for creating form tags that don't rely on an Active Record object assigned to the template like
|
10
13
|
# FormHelper does. Instead, you provide the names and values manually.
|
11
14
|
#
|
@@ -20,7 +23,9 @@ module ActionView
|
|
20
23
|
mattr_accessor :embed_authenticity_token_in_remote_forms
|
21
24
|
self.embed_authenticity_token_in_remote_forms = nil
|
22
25
|
|
23
|
-
|
26
|
+
mattr_accessor :default_enforce_utf8, default: true
|
27
|
+
|
28
|
+
# Starts a form tag that points the action to a URL configured with <tt>url_for_options</tt> just like
|
24
29
|
# ActionController::Base#url_for. The method for the form defaults to POST.
|
25
30
|
#
|
26
31
|
# ==== Options
|
@@ -113,7 +118,7 @@ module ActionView
|
|
113
118
|
# # <option>Write</option></select>
|
114
119
|
#
|
115
120
|
# select_tag "people", options_from_collection_for_select(@people, "id", "name"), include_blank: true
|
116
|
-
# # => <select id="people" name="people"><option value=""></option><option value="1">David</option></select>
|
121
|
+
# # => <select id="people" name="people"><option value="" label=" "></option><option value="1">David</option></select>
|
117
122
|
#
|
118
123
|
# select_tag "people", options_from_collection_for_select(@people, "id", "name"), include_blank: "All"
|
119
124
|
# # => <select id="people" name="people"><option value="">All</option><option value="1">David</option></select>
|
@@ -130,10 +135,11 @@ module ActionView
|
|
130
135
|
# # <option selected="selected">MasterCard</option></select>
|
131
136
|
def select_tag(name, option_tags = nil, options = {})
|
132
137
|
option_tags ||= ""
|
133
|
-
html_name = (options[:multiple] == true && !name.
|
138
|
+
html_name = (options[:multiple] == true && !name.end_with?("[]")) ? "#{name}[]" : name
|
134
139
|
|
135
140
|
if options.include?(:include_blank)
|
136
|
-
include_blank = options
|
141
|
+
include_blank = options[:include_blank]
|
142
|
+
options = options.except(:include_blank)
|
137
143
|
options_for_blank_options_tag = { value: "" }
|
138
144
|
|
139
145
|
if include_blank == true
|
@@ -142,15 +148,15 @@ module ActionView
|
|
142
148
|
end
|
143
149
|
|
144
150
|
if include_blank
|
145
|
-
option_tags = content_tag("option"
|
151
|
+
option_tags = content_tag("option", include_blank, options_for_blank_options_tag).safe_concat(option_tags)
|
146
152
|
end
|
147
153
|
end
|
148
154
|
|
149
155
|
if prompt = options.delete(:prompt)
|
150
|
-
option_tags = content_tag("option"
|
156
|
+
option_tags = content_tag("option", prompt, value: "").safe_concat(option_tags)
|
151
157
|
end
|
152
158
|
|
153
|
-
content_tag "select"
|
159
|
+
content_tag "select", option_tags, { "name" => html_name, "id" => sanitize_to_id(name) }.update(options.stringify_keys)
|
154
160
|
end
|
155
161
|
|
156
162
|
# Creates a standard text field; use these text fields to input smaller chunks of text like a username
|
@@ -161,6 +167,8 @@ module ActionView
|
|
161
167
|
# * <tt>:size</tt> - The number of visible characters that will fit in the input.
|
162
168
|
# * <tt>:maxlength</tt> - The maximum number of characters that the browser will allow the user to enter.
|
163
169
|
# * <tt>:placeholder</tt> - The text contained in the field by default which is removed when the field receives focus.
|
170
|
+
# If set to true, use a translation is found in the current I18n locale
|
171
|
+
# (through helpers.placeholders.<modelname>.<attribute>).
|
164
172
|
# * Any other key creates standard HTML attributes for the tag.
|
165
173
|
#
|
166
174
|
# ==== Examples
|
@@ -272,7 +280,7 @@ module ActionView
|
|
272
280
|
# file_field_tag 'file', accept: 'text/html', class: 'upload', value: 'index.html'
|
273
281
|
# # => <input accept="text/html" class="upload" id="file" name="file" type="file" value="index.html" />
|
274
282
|
def file_field_tag(name, options = {})
|
275
|
-
text_field_tag(name, nil, options.merge(type: :file))
|
283
|
+
text_field_tag(name, nil, convert_direct_upload_option_to_url(options.merge(type: :file)))
|
276
284
|
end
|
277
285
|
|
278
286
|
# Creates a password field, a masked text field that will hide the users input behind a mask character.
|
@@ -385,14 +393,14 @@ module ActionView
|
|
385
393
|
# * Any other key creates standard HTML options for the tag.
|
386
394
|
#
|
387
395
|
# ==== Examples
|
388
|
-
# radio_button_tag '
|
389
|
-
# # => <input id="
|
396
|
+
# radio_button_tag 'favorite_color', 'maroon'
|
397
|
+
# # => <input id="favorite_color_maroon" name="favorite_color" type="radio" value="maroon" />
|
390
398
|
#
|
391
399
|
# radio_button_tag 'receive_updates', 'no', true
|
392
400
|
# # => <input checked="checked" id="receive_updates_no" name="receive_updates" type="radio" value="no" />
|
393
401
|
#
|
394
402
|
# radio_button_tag 'time_slot', "3:00 p.m.", false, disabled: true
|
395
|
-
# # => <input disabled="disabled" id="
|
403
|
+
# # => <input disabled="disabled" id="time_slot_3:00_p.m." name="time_slot" type="radio" value="3:00 p.m." />
|
396
404
|
#
|
397
405
|
# radio_button_tag 'color', "green", true, class: "color_input"
|
398
406
|
# # => <input checked="checked" class="color_input" id="color_green" name="color" type="radio" value="green" />
|
@@ -454,7 +462,7 @@ module ActionView
|
|
454
462
|
# submit tag but it isn't supported in legacy browsers. However,
|
455
463
|
# the button tag does allow for richer labels such as images and emphasis,
|
456
464
|
# so this helper will also accept a block. By default, it will create
|
457
|
-
# a button tag with type
|
465
|
+
# a button tag with type <tt>submit</tt>, if type is not given.
|
458
466
|
#
|
459
467
|
# ==== Options
|
460
468
|
# * <tt>:data</tt> - This option can be used to add custom data attributes.
|
@@ -532,22 +540,23 @@ module ActionView
|
|
532
540
|
#
|
533
541
|
# ==== Examples
|
534
542
|
# image_submit_tag("login.png")
|
535
|
-
# # => <input
|
543
|
+
# # => <input src="/assets/login.png" type="image" />
|
536
544
|
#
|
537
545
|
# image_submit_tag("purchase.png", disabled: true)
|
538
|
-
# # => <input
|
546
|
+
# # => <input disabled="disabled" src="/assets/purchase.png" type="image" />
|
539
547
|
#
|
540
548
|
# image_submit_tag("search.png", class: 'search_button', alt: 'Find')
|
541
|
-
# # => <input
|
549
|
+
# # => <input class="search_button" src="/assets/search.png" type="image" />
|
542
550
|
#
|
543
551
|
# image_submit_tag("agree.png", disabled: true, class: "agree_disagree_button")
|
544
|
-
# # => <input
|
552
|
+
# # => <input class="agree_disagree_button" disabled="disabled" src="/assets/agree.png" type="image" />
|
545
553
|
#
|
546
554
|
# image_submit_tag("save.png", data: { confirm: "Are you sure?" })
|
547
|
-
# # => <input
|
555
|
+
# # => <input src="/assets/save.png" data-confirm="Are you sure?" type="image" />
|
548
556
|
def image_submit_tag(source, options = {})
|
549
557
|
options = options.stringify_keys
|
550
|
-
|
558
|
+
src = path_to_image(source, skip_pipeline: options.delete("skip_pipeline"))
|
559
|
+
tag :input, { "type" => "image", "src" => src }.update(options)
|
551
560
|
end
|
552
561
|
|
553
562
|
# Creates a field set for grouping HTML form elements.
|
@@ -572,7 +581,7 @@ module ActionView
|
|
572
581
|
# # => <fieldset class="format"><p><input id="name" name="name" type="text" /></p></fieldset>
|
573
582
|
def field_set_tag(legend = nil, options = nil, &block)
|
574
583
|
output = tag(:fieldset, options, true)
|
575
|
-
output.safe_concat(content_tag("legend"
|
584
|
+
output.safe_concat(content_tag("legend", legend)) unless legend.blank?
|
576
585
|
output.concat(capture(&block)) if block_given?
|
577
586
|
output.safe_concat("</fieldset>")
|
578
587
|
end
|
@@ -864,7 +873,7 @@ module ActionView
|
|
864
873
|
})
|
865
874
|
end
|
866
875
|
|
867
|
-
if html_options.delete("enforce_utf8") {
|
876
|
+
if html_options.delete("enforce_utf8") { default_enforce_utf8 }
|
868
877
|
utf8_enforcer_tag + method_tag
|
869
878
|
else
|
870
879
|
method_tag
|
@@ -888,20 +897,26 @@ module ActionView
|
|
888
897
|
end
|
889
898
|
|
890
899
|
def set_default_disable_with(value, tag_options)
|
891
|
-
|
892
|
-
data = tag_options["data"]
|
900
|
+
data = tag_options.fetch("data", {})
|
893
901
|
|
894
|
-
|
902
|
+
if tag_options["data-disable-with"] == false || data["disable_with"] == false
|
903
|
+
data.delete("disable_with")
|
904
|
+
elsif ActionView::Base.automatically_disable_submit_tag
|
895
905
|
disable_with_text = tag_options["data-disable-with"]
|
896
|
-
disable_with_text ||= data["disable_with"]
|
906
|
+
disable_with_text ||= data["disable_with"]
|
897
907
|
disable_with_text ||= value.to_s.clone
|
898
908
|
tag_options.deep_merge!("data" => { "disable_with" => disable_with_text })
|
899
|
-
else
|
900
|
-
data.delete("disable_with") if data
|
901
909
|
end
|
902
910
|
|
903
911
|
tag_options.delete("data-disable-with")
|
904
912
|
end
|
913
|
+
|
914
|
+
def convert_direct_upload_option_to_url(options)
|
915
|
+
if options.delete(:direct_upload) && respond_to?(:rails_direct_uploads_url)
|
916
|
+
options["data-direct-upload-url"] = rails_direct_uploads_url
|
917
|
+
end
|
918
|
+
options
|
919
|
+
end
|
905
920
|
end
|
906
921
|
end
|
907
922
|
end
|