actionview 6.1.7.2 → 7.1.3
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 +299 -277
- data/MIT-LICENSE +2 -1
- data/README.rdoc +3 -3
- data/app/assets/javascripts/rails-ujs.esm.js +686 -0
- data/app/assets/javascripts/rails-ujs.js +630 -0
- data/lib/action_view/base.rb +37 -19
- data/lib/action_view/buffers.rb +107 -9
- data/lib/action_view/cache_expiry.rb +48 -37
- data/lib/action_view/context.rb +1 -1
- data/lib/action_view/dependency_tracker/erb_tracker.rb +154 -0
- data/lib/action_view/dependency_tracker/ripper_tracker.rb +59 -0
- data/lib/action_view/dependency_tracker.rb +6 -147
- data/lib/action_view/deprecator.rb +7 -0
- data/lib/action_view/digestor.rb +8 -5
- data/lib/action_view/flows.rb +4 -4
- data/lib/action_view/gem_version.rb +4 -4
- data/lib/action_view/helpers/active_model_helper.rb +3 -3
- data/lib/action_view/helpers/asset_tag_helper.rb +200 -60
- data/lib/action_view/helpers/asset_url_helper.rb +22 -21
- data/lib/action_view/helpers/atom_feed_helper.rb +8 -9
- data/lib/action_view/helpers/cache_helper.rb +55 -12
- data/lib/action_view/helpers/capture_helper.rb +34 -14
- data/lib/action_view/helpers/content_exfiltration_prevention_helper.rb +70 -0
- data/lib/action_view/helpers/controller_helper.rb +8 -2
- data/lib/action_view/helpers/csp_helper.rb +3 -3
- data/lib/action_view/helpers/csrf_helper.rb +4 -4
- data/lib/action_view/helpers/date_helper.rb +123 -57
- data/lib/action_view/helpers/debug_helper.rb +6 -4
- data/lib/action_view/helpers/form_helper.rb +253 -97
- data/lib/action_view/helpers/form_options_helper.rb +72 -34
- data/lib/action_view/helpers/form_tag_helper.rb +189 -58
- data/lib/action_view/helpers/javascript_helper.rb +4 -5
- data/lib/action_view/helpers/number_helper.rb +43 -335
- data/lib/action_view/helpers/output_safety_helper.rb +6 -6
- data/lib/action_view/helpers/rendering_helper.rb +6 -7
- data/lib/action_view/helpers/sanitize_helper.rb +54 -24
- data/lib/action_view/helpers/tag_helper.rb +42 -35
- data/lib/action_view/helpers/tags/base.rb +16 -77
- data/lib/action_view/helpers/tags/check_box.rb +1 -1
- data/lib/action_view/helpers/tags/collection_check_boxes.rb +1 -0
- data/lib/action_view/helpers/tags/collection_radio_buttons.rb +1 -0
- data/lib/action_view/helpers/tags/collection_select.rb +4 -1
- data/lib/action_view/helpers/tags/date_field.rb +1 -1
- data/lib/action_view/helpers/tags/date_select.rb +2 -0
- data/lib/action_view/helpers/tags/datetime_field.rb +14 -6
- data/lib/action_view/helpers/tags/datetime_local_field.rb +11 -2
- data/lib/action_view/helpers/tags/file_field.rb +16 -0
- data/lib/action_view/helpers/tags/grouped_collection_select.rb +3 -0
- data/lib/action_view/helpers/tags/month_field.rb +1 -1
- data/lib/action_view/helpers/tags/select.rb +4 -1
- data/lib/action_view/helpers/tags/select_renderer.rb +56 -0
- data/lib/action_view/helpers/tags/time_field.rb +11 -2
- data/lib/action_view/helpers/tags/time_zone_select.rb +3 -0
- data/lib/action_view/helpers/tags/week_field.rb +1 -1
- data/lib/action_view/helpers/tags/weekday_select.rb +31 -0
- data/lib/action_view/helpers/tags.rb +5 -2
- data/lib/action_view/helpers/text_helper.rb +180 -97
- data/lib/action_view/helpers/translation_helper.rb +14 -45
- data/lib/action_view/helpers/url_helper.rb +230 -132
- data/lib/action_view/helpers.rb +27 -25
- data/lib/action_view/layouts.rb +15 -10
- data/lib/action_view/log_subscriber.rb +49 -32
- data/lib/action_view/lookup_context.rb +58 -61
- data/lib/action_view/model_naming.rb +2 -2
- data/lib/action_view/path_registry.rb +57 -0
- data/lib/action_view/path_set.rb +28 -35
- data/lib/action_view/railtie.rb +44 -9
- data/lib/action_view/record_identifier.rb +16 -9
- data/lib/action_view/render_parser.rb +188 -0
- data/lib/action_view/renderer/abstract_renderer.rb +3 -3
- data/lib/action_view/renderer/collection_renderer.rb +10 -2
- data/lib/action_view/renderer/partial_renderer/collection_caching.rb +21 -3
- data/lib/action_view/renderer/partial_renderer.rb +3 -36
- data/lib/action_view/renderer/renderer.rb +6 -4
- data/lib/action_view/renderer/streaming_template_renderer.rb +6 -5
- data/lib/action_view/renderer/template_renderer.rb +9 -4
- data/lib/action_view/rendering.rb +25 -7
- data/lib/action_view/ripper_ast_parser.rb +198 -0
- data/lib/action_view/routing_url_for.rb +8 -5
- data/lib/action_view/template/error.rb +122 -14
- data/lib/action_view/template/handlers/builder.rb +4 -4
- data/lib/action_view/template/handlers/erb/erubi.rb +23 -27
- data/lib/action_view/template/handlers/erb.rb +79 -1
- data/lib/action_view/template/handlers.rb +4 -4
- data/lib/action_view/template/html.rb +4 -4
- data/lib/action_view/template/inline.rb +3 -3
- data/lib/action_view/template/raw_file.rb +4 -4
- data/lib/action_view/template/renderable.rb +1 -1
- data/lib/action_view/template/resolver.rb +96 -313
- data/lib/action_view/template/text.rb +4 -4
- data/lib/action_view/template/types.rb +25 -32
- data/lib/action_view/template.rb +245 -41
- data/lib/action_view/template_details.rb +66 -0
- data/lib/action_view/template_path.rb +66 -0
- data/lib/action_view/test_case.rb +182 -23
- data/lib/action_view/testing/resolvers.rb +11 -12
- data/lib/action_view/unbound_template.rb +43 -7
- data/lib/action_view/version.rb +1 -1
- data/lib/action_view/view_paths.rb +19 -28
- data/lib/action_view.rb +6 -4
- data/lib/assets/compiled/rails-ujs.js +36 -5
- metadata +32 -25
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require "cgi"
|
|
4
4
|
require "action_view/helpers/date_helper"
|
|
5
|
-
require "action_view/helpers/
|
|
5
|
+
require "action_view/helpers/url_helper"
|
|
6
6
|
require "action_view/helpers/form_tag_helper"
|
|
7
7
|
require "action_view/helpers/active_model_helper"
|
|
8
8
|
require "action_view/model_naming"
|
|
@@ -11,11 +11,11 @@ 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"
|
|
15
14
|
|
|
16
15
|
module ActionView
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
module Helpers # :nodoc:
|
|
17
|
+
# = Action View Form \Helpers
|
|
18
|
+
#
|
|
19
19
|
# Form helpers are designed to make working with resources much easier
|
|
20
20
|
# compared to using vanilla HTML.
|
|
21
21
|
#
|
|
@@ -29,7 +29,7 @@ module ActionView
|
|
|
29
29
|
# when the form is initially displayed, input fields corresponding to attributes
|
|
30
30
|
# of the resource should show the current values of those attributes.
|
|
31
31
|
#
|
|
32
|
-
# In Rails, this is usually achieved by creating the form using +form_for+ and
|
|
32
|
+
# In \Rails, this is usually achieved by creating the form using +form_for+ and
|
|
33
33
|
# a number of related helper methods. +form_for+ generates an appropriate <tt>form</tt>
|
|
34
34
|
# tag and yields a form builder object that knows the model the form is about.
|
|
35
35
|
# Input fields are created by calling methods defined on the form builder, which
|
|
@@ -123,7 +123,7 @@ module ActionView
|
|
|
123
123
|
# of a specific model object.
|
|
124
124
|
#
|
|
125
125
|
# The method can be used in several slightly different ways, depending on
|
|
126
|
-
# how much you wish to rely on Rails to infer automatically from the model
|
|
126
|
+
# how much you wish to rely on \Rails to infer automatically from the model
|
|
127
127
|
# how the form should be constructed. For a generic model object, a form
|
|
128
128
|
# can be created by passing +form_for+ a string or symbol representing
|
|
129
129
|
# the object we are concerned with:
|
|
@@ -252,7 +252,7 @@ module ActionView
|
|
|
252
252
|
# form is going to be sent. However, further simplification is possible
|
|
253
253
|
# if the record passed to +form_for+ is a _resource_, i.e. it corresponds
|
|
254
254
|
# to a set of RESTful routes, e.g. defined using the +resources+ method
|
|
255
|
-
# in <tt>config/routes.rb</tt>. In this case Rails will simply infer the
|
|
255
|
+
# in <tt>config/routes.rb</tt>. In this case \Rails will simply infer the
|
|
256
256
|
# appropriate URL from the record itself. For example,
|
|
257
257
|
#
|
|
258
258
|
# <%= form_for @post do |f| %>
|
|
@@ -283,6 +283,12 @@ module ActionView
|
|
|
283
283
|
# ...
|
|
284
284
|
# <% end %>
|
|
285
285
|
#
|
|
286
|
+
# You can omit the <tt>action</tt> attribute by passing <tt>url: false</tt>:
|
|
287
|
+
#
|
|
288
|
+
# <%= form_for(@post, url: false) do |f| %>
|
|
289
|
+
# ...
|
|
290
|
+
# <% end %>
|
|
291
|
+
#
|
|
286
292
|
# You can also set the answer format, like this:
|
|
287
293
|
#
|
|
288
294
|
# <%= form_for(@post, format: :json) do |f| %>
|
|
@@ -427,50 +433,45 @@ module ActionView
|
|
|
427
433
|
# <% end %>
|
|
428
434
|
def form_for(record, options = {}, &block)
|
|
429
435
|
raise ArgumentError, "Missing block" unless block_given?
|
|
430
|
-
html_options = options[:html] ||= {}
|
|
431
436
|
|
|
432
437
|
case record
|
|
433
438
|
when String, Symbol
|
|
439
|
+
model = nil
|
|
434
440
|
object_name = record
|
|
435
|
-
object = nil
|
|
436
441
|
else
|
|
437
|
-
|
|
442
|
+
model = record
|
|
443
|
+
object = _object_for_form_builder(record)
|
|
438
444
|
raise ArgumentError, "First argument in form cannot contain nil or be empty" unless object
|
|
439
445
|
object_name = options[:as] || model_name_from_record_or_class(object).param_key
|
|
440
|
-
apply_form_for_options!(
|
|
446
|
+
apply_form_for_options!(object, options)
|
|
441
447
|
end
|
|
442
448
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
449
|
+
remote = options.delete(:remote)
|
|
450
|
+
|
|
451
|
+
if remote && !embed_authenticity_token_in_remote_forms && options[:authenticity_token].blank?
|
|
452
|
+
options[:authenticity_token] = false
|
|
453
|
+
end
|
|
448
454
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
455
|
+
options[:model] = model
|
|
456
|
+
options[:scope] = object_name
|
|
457
|
+
options[:local] = !remote
|
|
458
|
+
options[:skip_default_ids] = false
|
|
459
|
+
options[:allow_method_names_outside_object] = options.fetch(:allow_method_names_outside_object, false)
|
|
452
460
|
|
|
453
|
-
|
|
454
|
-
form_tag_with_body(html_options, output)
|
|
461
|
+
form_with(**options, &block)
|
|
455
462
|
end
|
|
456
463
|
|
|
457
|
-
def apply_form_for_options!(
|
|
464
|
+
def apply_form_for_options!(object, options) # :nodoc:
|
|
458
465
|
object = convert_to_model(object)
|
|
459
466
|
|
|
460
467
|
as = options[:as]
|
|
461
468
|
namespace = options[:namespace]
|
|
462
|
-
action
|
|
469
|
+
action = object.respond_to?(:persisted?) && object.persisted? ? :edit : :new
|
|
470
|
+
options[:html] ||= {}
|
|
463
471
|
options[:html].reverse_merge!(
|
|
464
472
|
class: as ? "#{action}_#{as}" : dom_class(object, action),
|
|
465
473
|
id: (as ? [namespace, action, as] : [namespace, dom_id(object, action)]).compact.join("_").presence,
|
|
466
|
-
method: method
|
|
467
474
|
)
|
|
468
|
-
|
|
469
|
-
options[:url] ||= if options.key?(:format)
|
|
470
|
-
polymorphic_path(record, format: options.delete(:format))
|
|
471
|
-
else
|
|
472
|
-
polymorphic_path(record, {})
|
|
473
|
-
end
|
|
474
475
|
end
|
|
475
476
|
private :apply_form_for_options!
|
|
476
477
|
|
|
@@ -478,6 +479,8 @@ module ActionView
|
|
|
478
479
|
|
|
479
480
|
mattr_accessor :form_with_generates_ids, default: false
|
|
480
481
|
|
|
482
|
+
mattr_accessor :multiple_file_field_include_hidden, default: false
|
|
483
|
+
|
|
481
484
|
# Creates a form tag based on mixing URLs, scopes, or models.
|
|
482
485
|
#
|
|
483
486
|
# # Using just a URL:
|
|
@@ -485,7 +488,16 @@ module ActionView
|
|
|
485
488
|
# <%= form.text_field :title %>
|
|
486
489
|
# <% end %>
|
|
487
490
|
# # =>
|
|
488
|
-
# <form action="/posts" method="post"
|
|
491
|
+
# <form action="/posts" method="post">
|
|
492
|
+
# <input type="text" name="title">
|
|
493
|
+
# </form>
|
|
494
|
+
#
|
|
495
|
+
# # With an intentionally empty URL:
|
|
496
|
+
# <%= form_with url: false do |form| %>
|
|
497
|
+
# <%= form.text_field :title %>
|
|
498
|
+
# <% end %>
|
|
499
|
+
# # =>
|
|
500
|
+
# <form method="post">
|
|
489
501
|
# <input type="text" name="title">
|
|
490
502
|
# </form>
|
|
491
503
|
#
|
|
@@ -494,7 +506,7 @@ module ActionView
|
|
|
494
506
|
# <%= form.text_field :title %>
|
|
495
507
|
# <% end %>
|
|
496
508
|
# # =>
|
|
497
|
-
# <form action="/posts" method="post"
|
|
509
|
+
# <form action="/posts" method="post">
|
|
498
510
|
# <input type="text" name="post[title]">
|
|
499
511
|
# </form>
|
|
500
512
|
#
|
|
@@ -503,7 +515,7 @@ module ActionView
|
|
|
503
515
|
# <%= form.text_field :title %>
|
|
504
516
|
# <% end %>
|
|
505
517
|
# # =>
|
|
506
|
-
# <form action="/posts" method="post"
|
|
518
|
+
# <form action="/posts" method="post">
|
|
507
519
|
# <input type="text" name="post[title]">
|
|
508
520
|
# </form>
|
|
509
521
|
#
|
|
@@ -512,7 +524,7 @@ module ActionView
|
|
|
512
524
|
# <%= form.text_field :title %>
|
|
513
525
|
# <% end %>
|
|
514
526
|
# # =>
|
|
515
|
-
# <form action="/posts/1" method="post"
|
|
527
|
+
# <form action="/posts/1" method="post">
|
|
516
528
|
# <input type="hidden" name="_method" value="patch">
|
|
517
529
|
# <input type="text" name="post[title]" value="<the title of the post>">
|
|
518
530
|
# </form>
|
|
@@ -523,7 +535,7 @@ module ActionView
|
|
|
523
535
|
# <%= form.text_field :but_in_forms_they_can %>
|
|
524
536
|
# <% end %>
|
|
525
537
|
# # =>
|
|
526
|
-
# <form action="/cats" method="post"
|
|
538
|
+
# <form action="/cats" method="post">
|
|
527
539
|
# <input type="text" name="cat[cats_dont_have_gills]">
|
|
528
540
|
# <input type="text" name="cat[but_in_forms_they_can]">
|
|
529
541
|
# </form>
|
|
@@ -544,7 +556,7 @@ module ActionView
|
|
|
544
556
|
# is a _resource_. It corresponds to a set of RESTful routes, most likely
|
|
545
557
|
# defined via +resources+ in <tt>config/routes.rb</tt>.
|
|
546
558
|
#
|
|
547
|
-
# So when passing such a model record, Rails infers the URL and method.
|
|
559
|
+
# So when passing such a model record, \Rails infers the URL and method.
|
|
548
560
|
#
|
|
549
561
|
# <%= form_with model: @post do |form| %>
|
|
550
562
|
# ...
|
|
@@ -604,10 +616,16 @@ module ActionView
|
|
|
604
616
|
# This is helpful when fragment-caching the form. Remote forms
|
|
605
617
|
# get the authenticity token from the <tt>meta</tt> tag, so embedding is
|
|
606
618
|
# unnecessary unless you support browsers without JavaScript.
|
|
607
|
-
# * <tt>:local</tt> -
|
|
608
|
-
#
|
|
609
|
-
#
|
|
610
|
-
#
|
|
619
|
+
# * <tt>:local</tt> - Whether to use standard HTTP form submission.
|
|
620
|
+
# When set to <tt>true</tt>, the form is submitted via standard HTTP.
|
|
621
|
+
# When set to <tt>false</tt>, the form is submitted as a "remote form", which
|
|
622
|
+
# is handled by \Rails UJS as an XHR. When unspecified, the behavior is derived
|
|
623
|
+
# from <tt>config.action_view.form_with_generates_remote_forms</tt> where the
|
|
624
|
+
# config's value is actually the inverse of what <tt>local</tt>'s value would be.
|
|
625
|
+
# As of \Rails 6.1, that configuration option defaults to <tt>false</tt>
|
|
626
|
+
# (which has the equivalent effect of passing <tt>local: true</tt>).
|
|
627
|
+
# In previous versions of \Rails, that configuration option defaults to
|
|
628
|
+
# <tt>true</tt> (the equivalent of passing <tt>local: false</tt>).
|
|
611
629
|
# * <tt>:skip_enforcing_utf8</tt> - If set to true, a hidden input with name
|
|
612
630
|
# utf8 is not output.
|
|
613
631
|
# * <tt>:builder</tt> - Override the object used to build the form.
|
|
@@ -735,13 +753,18 @@ module ActionView
|
|
|
735
753
|
# form_with(**options.merge(builder: LabellingFormBuilder), &block)
|
|
736
754
|
# end
|
|
737
755
|
def form_with(model: nil, scope: nil, url: nil, format: nil, **options, &block)
|
|
738
|
-
options
|
|
739
|
-
options[:skip_default_ids] = !form_with_generates_ids
|
|
756
|
+
options = { allow_method_names_outside_object: true, skip_default_ids: !form_with_generates_ids }.merge!(options)
|
|
740
757
|
|
|
741
758
|
if model
|
|
742
|
-
url
|
|
759
|
+
if url != false
|
|
760
|
+
url ||= if format.nil?
|
|
761
|
+
polymorphic_path(model, {})
|
|
762
|
+
else
|
|
763
|
+
polymorphic_path(model, format: format)
|
|
764
|
+
end
|
|
765
|
+
end
|
|
743
766
|
|
|
744
|
-
model = model
|
|
767
|
+
model = convert_to_model(_object_for_form_builder(model))
|
|
745
768
|
scope ||= model_name_from_record_or_class(model).param_key
|
|
746
769
|
end
|
|
747
770
|
|
|
@@ -983,8 +1006,8 @@ module ActionView
|
|
|
983
1006
|
# <% end %>
|
|
984
1007
|
#
|
|
985
1008
|
# When a collection is used you might want to know the index of each
|
|
986
|
-
# object
|
|
987
|
-
#
|
|
1009
|
+
# object in the array. For this purpose, the <tt>index</tt> method is
|
|
1010
|
+
# available in the FormBuilder object.
|
|
988
1011
|
#
|
|
989
1012
|
# <%= form_for @person do |person_form| %>
|
|
990
1013
|
# ...
|
|
@@ -996,12 +1019,14 @@ module ActionView
|
|
|
996
1019
|
# <% end %>
|
|
997
1020
|
#
|
|
998
1021
|
# Note that fields_for will automatically generate a hidden field
|
|
999
|
-
# to store the ID of the record
|
|
1000
|
-
# hidden field is not needed and you
|
|
1001
|
-
# to prevent fields_for from
|
|
1022
|
+
# to store the ID of the record if it responds to <tt>persisted?</tt>.
|
|
1023
|
+
# There are circumstances where this hidden field is not needed and you
|
|
1024
|
+
# can pass <tt>include_id: false</tt> to prevent fields_for from
|
|
1025
|
+
# rendering it automatically.
|
|
1002
1026
|
def fields_for(record_name, record_object = nil, options = {}, &block)
|
|
1003
|
-
|
|
1004
|
-
|
|
1027
|
+
options = { model: record_object, allow_method_names_outside_object: false, skip_default_ids: false }.merge!(options)
|
|
1028
|
+
|
|
1029
|
+
fields(record_name, **options, &block)
|
|
1005
1030
|
end
|
|
1006
1031
|
|
|
1007
1032
|
# Scopes input fields with either an explicit scope or model.
|
|
@@ -1050,10 +1075,10 @@ module ActionView
|
|
|
1050
1075
|
# to work with an object as a base, like
|
|
1051
1076
|
# FormOptionsHelper#collection_select and DateHelper#datetime_select.
|
|
1052
1077
|
def fields(scope = nil, model: nil, **options, &block)
|
|
1053
|
-
options
|
|
1054
|
-
options[:skip_default_ids] = !form_with_generates_ids
|
|
1078
|
+
options = { allow_method_names_outside_object: true, skip_default_ids: !form_with_generates_ids }.merge!(options)
|
|
1055
1079
|
|
|
1056
1080
|
if model
|
|
1081
|
+
model = _object_for_form_builder(model)
|
|
1057
1082
|
scope ||= model_name_from_record_or_class(model).param_key
|
|
1058
1083
|
end
|
|
1059
1084
|
|
|
@@ -1063,7 +1088,7 @@ module ActionView
|
|
|
1063
1088
|
|
|
1064
1089
|
# Returns a label tag tailored for labelling an input field for a specified attribute (identified by +method+) on an object
|
|
1065
1090
|
# assigned to the template (identified by +object+). The text of label will default to the attribute name unless a translation
|
|
1066
|
-
# is found in the current I18n locale (through helpers.label.<modelname>.<attribute>) or you specify it explicitly.
|
|
1091
|
+
# is found in the current I18n locale (through <tt>helpers.label.<modelname>.<attribute></tt>) or you specify it explicitly.
|
|
1067
1092
|
# Additional options on the label tag can be passed as a hash with +options+. These options will be tagged
|
|
1068
1093
|
# onto the HTML as an HTML element attribute as in the example shown, except for the <tt>:value</tt> option, which is designed to
|
|
1069
1094
|
# target labels for radio_button tags (where the value is used in the ID of the input tag).
|
|
@@ -1093,6 +1118,8 @@ module ActionView
|
|
|
1093
1118
|
# post:
|
|
1094
1119
|
# cost: "Total cost"
|
|
1095
1120
|
#
|
|
1121
|
+
# <code></code>
|
|
1122
|
+
#
|
|
1096
1123
|
# label(:post, :cost)
|
|
1097
1124
|
# # => <label for="post_cost">Total cost</label>
|
|
1098
1125
|
#
|
|
@@ -1197,6 +1224,7 @@ module ActionView
|
|
|
1197
1224
|
# * Creates standard HTML attributes for the tag.
|
|
1198
1225
|
# * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
|
|
1199
1226
|
# * <tt>:multiple</tt> - If set to true, *in most updated browsers* the user will be allowed to select multiple files.
|
|
1227
|
+
# * <tt>:include_hidden</tt> - When <tt>multiple: true</tt> and <tt>include_hidden: true</tt>, the field will be prefixed with an <tt><input type="hidden"></tt> field with an empty value to support submitting an empty collection of files.
|
|
1200
1228
|
# * <tt>:accept</tt> - If set to one or multiple mime-types, the user will be suggested a filter when choosing a file. You still need to set up model validations.
|
|
1201
1229
|
#
|
|
1202
1230
|
# ==== Examples
|
|
@@ -1215,6 +1243,8 @@ module ActionView
|
|
|
1215
1243
|
# file_field(:attachment, :file, class: 'file_input')
|
|
1216
1244
|
# # => <input type="file" id="attachment_file" name="attachment[file]" class="file_input" />
|
|
1217
1245
|
def file_field(object_name, method, options = {})
|
|
1246
|
+
options = { include_hidden: multiple_file_field_include_hidden }.merge!(options)
|
|
1247
|
+
|
|
1218
1248
|
Tags::FileField.new(object_name, method, self, convert_direct_upload_option_to_url(options.dup)).render
|
|
1219
1249
|
end
|
|
1220
1250
|
|
|
@@ -1252,6 +1282,12 @@ module ActionView
|
|
|
1252
1282
|
# Additional options on the input tag can be passed as a hash with +options+. The +checked_value+ defaults to 1
|
|
1253
1283
|
# while the default +unchecked_value+ is set to 0 which is convenient for boolean values.
|
|
1254
1284
|
#
|
|
1285
|
+
# ==== Options
|
|
1286
|
+
#
|
|
1287
|
+
# * Any standard HTML attributes for the tag can be passed in, for example +:class+.
|
|
1288
|
+
# * <tt>:checked</tt> - +true+ or +false+ forces the state of the checkbox to be checked or not.
|
|
1289
|
+
# * <tt>:include_hidden</tt> - If set to false, the auxiliary hidden field described below will not be generated.
|
|
1290
|
+
#
|
|
1255
1291
|
# ==== Gotcha
|
|
1256
1292
|
#
|
|
1257
1293
|
# The HTML specification says unchecked check boxes are not successful, and
|
|
@@ -1265,7 +1301,7 @@ module ActionView
|
|
|
1265
1301
|
# wouldn't update the flag.
|
|
1266
1302
|
#
|
|
1267
1303
|
# To prevent this the helper generates an auxiliary hidden field before
|
|
1268
|
-
#
|
|
1304
|
+
# every check box. The hidden field has the same name and its
|
|
1269
1305
|
# attributes mimic an unchecked check box.
|
|
1270
1306
|
#
|
|
1271
1307
|
# This way, the client either sends only the hidden field (representing
|
|
@@ -1282,13 +1318,15 @@ module ActionView
|
|
|
1282
1318
|
# ...
|
|
1283
1319
|
# <% end %>
|
|
1284
1320
|
#
|
|
1285
|
-
# because parameter name repetition is precisely what Rails seeks to distinguish
|
|
1321
|
+
# because parameter name repetition is precisely what \Rails seeks to distinguish
|
|
1286
1322
|
# the elements of the array. For each item with a checked check box you
|
|
1287
1323
|
# get an extra ghost item with only that attribute, assigned to "0".
|
|
1288
1324
|
#
|
|
1289
1325
|
# In that case it is preferable to either use +check_box_tag+ or to use
|
|
1290
1326
|
# hashes instead of arrays.
|
|
1291
1327
|
#
|
|
1328
|
+
# ==== Examples
|
|
1329
|
+
#
|
|
1292
1330
|
# # Let's say that @post.validated? is 1:
|
|
1293
1331
|
# check_box("post", "validated")
|
|
1294
1332
|
# # => <input name="post[validated]" type="hidden" value="0" />
|
|
@@ -1403,13 +1441,16 @@ module ActionView
|
|
|
1403
1441
|
# Returns a text_field of type "time".
|
|
1404
1442
|
#
|
|
1405
1443
|
# The default value is generated by trying to call +strftime+ with "%T.%L"
|
|
1406
|
-
# on the object's value.
|
|
1407
|
-
# by
|
|
1444
|
+
# on the object's value. If you pass <tt>include_seconds: false</tt>, it will be
|
|
1445
|
+
# formatted by trying to call +strftime+ with "%H:%M" on the object's value.
|
|
1446
|
+
# It is also possible to override this by passing the "value" option.
|
|
1447
|
+
#
|
|
1448
|
+
# ==== Options
|
|
1408
1449
|
#
|
|
1409
|
-
#
|
|
1410
|
-
#
|
|
1450
|
+
# Supports the same options as FormTagHelper#time_field_tag.
|
|
1451
|
+
#
|
|
1452
|
+
# ==== Examples
|
|
1411
1453
|
#
|
|
1412
|
-
# === Example
|
|
1413
1454
|
# time_field("task", "started_at")
|
|
1414
1455
|
# # => <input id="task_started_at" name="task[started_at]" type="time" />
|
|
1415
1456
|
#
|
|
@@ -1425,6 +1466,12 @@ module ActionView
|
|
|
1425
1466
|
# time_field("task", "started_at", min: "01:00:00")
|
|
1426
1467
|
# # => <input id="task_started_at" name="task[started_at]" type="time" min="01:00:00.000" />
|
|
1427
1468
|
#
|
|
1469
|
+
# By default, provided times will be formatted including seconds. You can render just the hour
|
|
1470
|
+
# and minute by passing <tt>include_seconds: false</tt>. Some browsers will render a simpler UI
|
|
1471
|
+
# if you exclude seconds in the timestamp format.
|
|
1472
|
+
#
|
|
1473
|
+
# time_field("task", "started_at", value: Time.now, include_seconds: false)
|
|
1474
|
+
# # => <input id="task_started_at" name="task[started_at]" type="time" value="01:00" />
|
|
1428
1475
|
def time_field(object_name, method, options = {})
|
|
1429
1476
|
Tags::TimeField.new(object_name, method, self, options).render
|
|
1430
1477
|
end
|
|
@@ -1454,6 +1501,12 @@ module ActionView
|
|
|
1454
1501
|
# datetime_field("user", "born_on", min: "2014-05-20T00:00:00")
|
|
1455
1502
|
# # => <input id="user_born_on" name="user[born_on]" type="datetime-local" min="2014-05-20T00:00:00.000" />
|
|
1456
1503
|
#
|
|
1504
|
+
# By default, provided datetimes will be formatted including seconds. You can render just the date, hour,
|
|
1505
|
+
# and minute by passing <tt>include_seconds: false</tt>.
|
|
1506
|
+
#
|
|
1507
|
+
# @user.born_on = Time.current
|
|
1508
|
+
# datetime_field("user", "born_on", include_seconds: false)
|
|
1509
|
+
# # => <input id="user_born_on" name="user[born_on]" type="datetime-local" value="2014-05-20T14:35" />
|
|
1457
1510
|
def datetime_field(object_name, method, options = {})
|
|
1458
1511
|
Tags::DatetimeLocalField.new(object_name, method, self, options).render
|
|
1459
1512
|
end
|
|
@@ -1515,7 +1568,8 @@ module ActionView
|
|
|
1515
1568
|
# Returns an input tag of type "number".
|
|
1516
1569
|
#
|
|
1517
1570
|
# ==== Options
|
|
1518
|
-
#
|
|
1571
|
+
#
|
|
1572
|
+
# Supports the same options as FormTagHelper#number_field_tag.
|
|
1519
1573
|
def number_field(object_name, method, options = {})
|
|
1520
1574
|
Tags::NumberField.new(object_name, method, self, options).render
|
|
1521
1575
|
end
|
|
@@ -1523,39 +1577,30 @@ module ActionView
|
|
|
1523
1577
|
# Returns an input tag of type "range".
|
|
1524
1578
|
#
|
|
1525
1579
|
# ==== Options
|
|
1526
|
-
#
|
|
1580
|
+
#
|
|
1581
|
+
# Supports the same options as FormTagHelper#range_field_tag.
|
|
1527
1582
|
def range_field(object_name, method, options = {})
|
|
1528
1583
|
Tags::RangeField.new(object_name, method, self, options).render
|
|
1529
1584
|
end
|
|
1530
1585
|
|
|
1586
|
+
def _object_for_form_builder(object) # :nodoc:
|
|
1587
|
+
object.is_a?(Array) ? object.last : object
|
|
1588
|
+
end
|
|
1589
|
+
|
|
1531
1590
|
private
|
|
1532
1591
|
def html_options_for_form_with(url_for_options = nil, model = nil, html: {}, local: !form_with_generates_remote_forms,
|
|
1533
1592
|
skip_enforcing_utf8: nil, **options)
|
|
1534
|
-
html_options = options.slice(:id, :class, :multipart, :method, :data).merge(html)
|
|
1593
|
+
html_options = options.slice(:id, :class, :multipart, :method, :data, :authenticity_token).merge!(html)
|
|
1594
|
+
html_options[:remote] = html.delete(:remote) || !local
|
|
1535
1595
|
html_options[:method] ||= :patch if model.respond_to?(:persisted?) && model.persisted?
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
html_options[:action] = url_for(url_for_options || {})
|
|
1543
|
-
html_options[:"accept-charset"] = "UTF-8"
|
|
1544
|
-
html_options[:"data-remote"] = true unless local
|
|
1545
|
-
|
|
1546
|
-
html_options[:authenticity_token] = options.delete(:authenticity_token)
|
|
1547
|
-
|
|
1548
|
-
if !local && html_options[:authenticity_token].blank?
|
|
1549
|
-
html_options[:authenticity_token] = embed_authenticity_token_in_remote_forms
|
|
1550
|
-
end
|
|
1551
|
-
|
|
1552
|
-
if html_options[:authenticity_token] == true
|
|
1553
|
-
# Include the default authenticity_token, which is only generated when it's set to nil,
|
|
1554
|
-
# but we needed the true value to override the default of no authenticity_token on data-remote.
|
|
1555
|
-
html_options[:authenticity_token] = nil
|
|
1596
|
+
if skip_enforcing_utf8.nil?
|
|
1597
|
+
if options.key?(:enforce_utf8)
|
|
1598
|
+
html_options[:enforce_utf8] = options[:enforce_utf8]
|
|
1599
|
+
end
|
|
1600
|
+
else
|
|
1601
|
+
html_options[:enforce_utf8] = !skip_enforcing_utf8
|
|
1556
1602
|
end
|
|
1557
|
-
|
|
1558
|
-
html_options.stringify_keys!
|
|
1603
|
+
html_options_for_form(url_for_options.nil? ? {} : url_for_options, html_options)
|
|
1559
1604
|
end
|
|
1560
1605
|
|
|
1561
1606
|
def instantiate_builder(record_name, record_object, options)
|
|
@@ -1578,6 +1623,8 @@ module ActionView
|
|
|
1578
1623
|
end
|
|
1579
1624
|
end
|
|
1580
1625
|
|
|
1626
|
+
# = Action View Form Builder
|
|
1627
|
+
#
|
|
1581
1628
|
# A +FormBuilder+ object is associated with a particular model object and
|
|
1582
1629
|
# allows you to generate fields associated with the model object. The
|
|
1583
1630
|
# +FormBuilder+ object is yielded when using +form_for+ or +fields_for+.
|
|
@@ -1685,6 +1732,69 @@ module ActionView
|
|
|
1685
1732
|
@index = options[:index] || options[:child_index]
|
|
1686
1733
|
end
|
|
1687
1734
|
|
|
1735
|
+
# Generate an HTML <tt>id</tt> attribute value.
|
|
1736
|
+
#
|
|
1737
|
+
# return the <tt><form></tt> element's <tt>id</tt> attribute.
|
|
1738
|
+
#
|
|
1739
|
+
# <%= form_for @post do |f| %>
|
|
1740
|
+
# <%# ... %>
|
|
1741
|
+
#
|
|
1742
|
+
# <% content_for :sticky_footer do %>
|
|
1743
|
+
# <%= form.button(form: f.id) %>
|
|
1744
|
+
# <% end %>
|
|
1745
|
+
# <% end %>
|
|
1746
|
+
#
|
|
1747
|
+
# In the example above, the <tt>:sticky_footer</tt> content area will
|
|
1748
|
+
# exist outside of the <tt><form></tt> element. By declaring the
|
|
1749
|
+
# <tt>form</tt> HTML attribute, we hint to the browser that the generated
|
|
1750
|
+
# <tt><button></tt> element should be treated as the <tt><form></tt>
|
|
1751
|
+
# element's submit button, regardless of where it exists in the DOM.
|
|
1752
|
+
def id
|
|
1753
|
+
options.dig(:html, :id) || options[:id]
|
|
1754
|
+
end
|
|
1755
|
+
|
|
1756
|
+
# Generate an HTML <tt>id</tt> attribute value for the given field
|
|
1757
|
+
#
|
|
1758
|
+
# Return the value generated by the <tt>FormBuilder</tt> for the given
|
|
1759
|
+
# attribute name.
|
|
1760
|
+
#
|
|
1761
|
+
# <%= form_for @post do |f| %>
|
|
1762
|
+
# <%= f.label :title %>
|
|
1763
|
+
# <%= f.text_field :title, aria: { describedby: f.field_id(:title, :error) } %>
|
|
1764
|
+
# <%= tag.span("is blank", id: f.field_id(:title, :error) %>
|
|
1765
|
+
# <% end %>
|
|
1766
|
+
#
|
|
1767
|
+
# In the example above, the <tt><input type="text"></tt> element built by
|
|
1768
|
+
# the call to <tt>FormBuilder#text_field</tt> declares an
|
|
1769
|
+
# <tt>aria-describedby</tt> attribute referencing the <tt><span></tt>
|
|
1770
|
+
# element, sharing a common <tt>id</tt> root (<tt>post_title</tt>, in this
|
|
1771
|
+
# case).
|
|
1772
|
+
def field_id(method, *suffixes, namespace: @options[:namespace], index: @options[:index])
|
|
1773
|
+
@template.field_id(@object_name, method, *suffixes, namespace: namespace, index: index)
|
|
1774
|
+
end
|
|
1775
|
+
|
|
1776
|
+
# Generate an HTML <tt>name</tt> attribute value for the given name and
|
|
1777
|
+
# field combination
|
|
1778
|
+
#
|
|
1779
|
+
# Return the value generated by the <tt>FormBuilder</tt> for the given
|
|
1780
|
+
# attribute name.
|
|
1781
|
+
#
|
|
1782
|
+
# <%= form_for @post do |f| %>
|
|
1783
|
+
# <%= f.text_field :title, name: f.field_name(:title, :subtitle) %>
|
|
1784
|
+
# <%# => <input type="text" name="post[title][subtitle]"> %>
|
|
1785
|
+
# <% end %>
|
|
1786
|
+
#
|
|
1787
|
+
# <%= form_for @post do |f| %>
|
|
1788
|
+
# <%= f.text_field :tag, name: f.field_name(:tag, multiple: true) %>
|
|
1789
|
+
# <%# => <input type="text" name="post[tag][]"> %>
|
|
1790
|
+
# <% end %>
|
|
1791
|
+
#
|
|
1792
|
+
def field_name(method, *methods, multiple: false, index: @options[:index])
|
|
1793
|
+
object_name = @options.fetch(:as) { @object_name }
|
|
1794
|
+
|
|
1795
|
+
@template.field_name(object_name, method, *methods, index: index, multiple: multiple)
|
|
1796
|
+
end
|
|
1797
|
+
|
|
1688
1798
|
##
|
|
1689
1799
|
# :method: text_field
|
|
1690
1800
|
#
|
|
@@ -1979,6 +2089,18 @@ module ActionView
|
|
|
1979
2089
|
# DateHelper that are designed to work with an object as base, like
|
|
1980
2090
|
# FormOptionsHelper#collection_select and DateHelper#datetime_select.
|
|
1981
2091
|
#
|
|
2092
|
+
# +fields_for+ tries to be smart about parameters, but it can be confused if both
|
|
2093
|
+
# name and value parameters are provided and the provided value has the shape of an
|
|
2094
|
+
# option Hash. To remove the ambiguity, explicitly pass an option Hash, even if empty.
|
|
2095
|
+
#
|
|
2096
|
+
# <%= form_for @person do |person_form| %>
|
|
2097
|
+
# ...
|
|
2098
|
+
# <%= fields_for :permission, @person.permission, {} do |permission_fields| %>
|
|
2099
|
+
# Admin?: <%= check_box_tag permission_fields.field_name(:admin), @person.permission[:admin] %>
|
|
2100
|
+
# <% end %>
|
|
2101
|
+
# ...
|
|
2102
|
+
# <% end %>
|
|
2103
|
+
#
|
|
1982
2104
|
# === Nested Attributes Examples
|
|
1983
2105
|
#
|
|
1984
2106
|
# When the object belonging to the current scope has a nested attribute
|
|
@@ -2143,7 +2265,7 @@ module ActionView
|
|
|
2143
2265
|
# <% end %>
|
|
2144
2266
|
#
|
|
2145
2267
|
# When a collection is used you might want to know the index of each
|
|
2146
|
-
# object
|
|
2268
|
+
# object in the array. For this purpose, the <tt>index</tt> method
|
|
2147
2269
|
# is available in the FormBuilder object.
|
|
2148
2270
|
#
|
|
2149
2271
|
# <%= form_for @person do |person_form| %>
|
|
@@ -2159,8 +2281,9 @@ module ActionView
|
|
|
2159
2281
|
# to store the ID of the record. There are circumstances where this
|
|
2160
2282
|
# hidden field is not needed and you can pass <tt>include_id: false</tt>
|
|
2161
2283
|
# to prevent fields_for from rendering it automatically.
|
|
2162
|
-
def fields_for(record_name, record_object = nil, fields_options =
|
|
2163
|
-
fields_options, record_object = record_object, nil if record_object.is_a?(Hash) && record_object.extractable_options?
|
|
2284
|
+
def fields_for(record_name, record_object = nil, fields_options = nil, &block)
|
|
2285
|
+
fields_options, record_object = record_object, nil if fields_options.nil? && record_object.is_a?(Hash) && record_object.extractable_options?
|
|
2286
|
+
fields_options ||= {}
|
|
2164
2287
|
fields_options[:builder] ||= options[:builder]
|
|
2165
2288
|
fields_options[:namespace] = options[:namespace]
|
|
2166
2289
|
fields_options[:parent_builder] = self
|
|
@@ -2171,7 +2294,7 @@ module ActionView
|
|
|
2171
2294
|
return fields_for_with_nested_attributes(record_name, record_object, fields_options, block)
|
|
2172
2295
|
end
|
|
2173
2296
|
else
|
|
2174
|
-
record_object =
|
|
2297
|
+
record_object = @template._object_for_form_builder(record_name)
|
|
2175
2298
|
record_name = model_name_from_record_or_class(record_object).param_key
|
|
2176
2299
|
end
|
|
2177
2300
|
|
|
@@ -2195,7 +2318,7 @@ module ActionView
|
|
|
2195
2318
|
@template.fields_for(record_name, record_object, fields_options, &block)
|
|
2196
2319
|
end
|
|
2197
2320
|
|
|
2198
|
-
# See the docs for the
|
|
2321
|
+
# See the docs for the ActionView::Helpers::FormHelper#fields helper method.
|
|
2199
2322
|
def fields(scope = nil, model: nil, **options, &block)
|
|
2200
2323
|
options[:allow_method_names_outside_object] = true
|
|
2201
2324
|
options[:skip_default_ids] = !FormHelper.form_with_generates_ids
|
|
@@ -2207,7 +2330,7 @@ module ActionView
|
|
|
2207
2330
|
|
|
2208
2331
|
# Returns a label tag tailored for labelling an input field for a specified attribute (identified by +method+) on an object
|
|
2209
2332
|
# assigned to the template (identified by +object+). The text of label will default to the attribute name unless a translation
|
|
2210
|
-
# is found in the current I18n locale (through helpers.label.<modelname>.<attribute>) or you specify it explicitly.
|
|
2333
|
+
# is found in the current I18n locale (through <tt>helpers.label.<modelname>.<attribute></tt>) or you specify it explicitly.
|
|
2211
2334
|
# Additional options on the label tag can be passed as a hash with +options+. These options will be tagged
|
|
2212
2335
|
# onto the HTML as an HTML element attribute as in the example shown, except for the <tt>:value</tt> option, which is designed to
|
|
2213
2336
|
# target labels for radio_button tags (where the value is used in the ID of the input tag).
|
|
@@ -2237,6 +2360,8 @@ module ActionView
|
|
|
2237
2360
|
# post:
|
|
2238
2361
|
# cost: "Total cost"
|
|
2239
2362
|
#
|
|
2363
|
+
# <code></code>
|
|
2364
|
+
#
|
|
2240
2365
|
# label(:cost)
|
|
2241
2366
|
# # => <label for="post_cost">Total cost</label>
|
|
2242
2367
|
#
|
|
@@ -2281,6 +2406,12 @@ module ActionView
|
|
|
2281
2406
|
# Additional options on the input tag can be passed as a hash with +options+. The +checked_value+ defaults to 1
|
|
2282
2407
|
# while the default +unchecked_value+ is set to 0 which is convenient for boolean values.
|
|
2283
2408
|
#
|
|
2409
|
+
# ==== Options
|
|
2410
|
+
#
|
|
2411
|
+
# * Any standard HTML attributes for the tag can be passed in, for example +:class+.
|
|
2412
|
+
# * <tt>:checked</tt> - +true+ or +false+ forces the state of the checkbox to be checked or not.
|
|
2413
|
+
# * <tt>:include_hidden</tt> - If set to false, the auxiliary hidden field described below will not be generated.
|
|
2414
|
+
#
|
|
2284
2415
|
# ==== Gotcha
|
|
2285
2416
|
#
|
|
2286
2417
|
# The HTML specification says unchecked check boxes are not successful, and
|
|
@@ -2294,7 +2425,7 @@ module ActionView
|
|
|
2294
2425
|
# wouldn't update the flag.
|
|
2295
2426
|
#
|
|
2296
2427
|
# To prevent this the helper generates an auxiliary hidden field before
|
|
2297
|
-
#
|
|
2428
|
+
# every check box. The hidden field has the same name and its
|
|
2298
2429
|
# attributes mimic an unchecked check box.
|
|
2299
2430
|
#
|
|
2300
2431
|
# This way, the client either sends only the hidden field (representing
|
|
@@ -2311,13 +2442,15 @@ module ActionView
|
|
|
2311
2442
|
# ...
|
|
2312
2443
|
# <% end %>
|
|
2313
2444
|
#
|
|
2314
|
-
# because parameter name repetition is precisely what Rails seeks to distinguish
|
|
2445
|
+
# because parameter name repetition is precisely what \Rails seeks to distinguish
|
|
2315
2446
|
# the elements of the array. For each item with a checked check box you
|
|
2316
2447
|
# get an extra ghost item with only that attribute, assigned to "0".
|
|
2317
2448
|
#
|
|
2318
2449
|
# In that case it is preferable to either use +check_box_tag+ or to use
|
|
2319
2450
|
# hashes instead of arrays.
|
|
2320
2451
|
#
|
|
2452
|
+
# ==== Examples
|
|
2453
|
+
#
|
|
2321
2454
|
# # Let's say that @post.validated? is 1:
|
|
2322
2455
|
# check_box("validated")
|
|
2323
2456
|
# # => <input name="post[validated]" type="hidden" value="0" />
|
|
@@ -2386,12 +2519,13 @@ module ActionView
|
|
|
2386
2519
|
# hash with +options+. These options will be tagged onto the HTML as an HTML element attribute as in the example
|
|
2387
2520
|
# shown.
|
|
2388
2521
|
#
|
|
2389
|
-
# Using this method inside a +
|
|
2522
|
+
# Using this method inside a +form_with+ block will set the enclosing form's encoding to <tt>multipart/form-data</tt>.
|
|
2390
2523
|
#
|
|
2391
2524
|
# ==== Options
|
|
2392
2525
|
# * Creates standard HTML attributes for the tag.
|
|
2393
2526
|
# * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
|
|
2394
2527
|
# * <tt>:multiple</tt> - If set to true, *in most updated browsers* the user will be allowed to select multiple files.
|
|
2528
|
+
# * <tt>:include_hidden</tt> - When <tt>multiple: true</tt> and <tt>include_hidden: true</tt>, the field will be prefixed with an <tt><input type="hidden"></tt> field with an empty value to support submitting an empty collection of files. Since <tt>include_hidden</tt> will default to <tt>config.active_storage.multiple_file_field_include_hidden</tt> if you don't specify <tt>include_hidden</tt>, you will need to pass <tt>include_hidden: false</tt> to prevent submitting an empty collection of files when passing <tt>multiple: true</tt>.
|
|
2395
2529
|
# * <tt>:accept</tt> - If set to one or multiple mime-types, the user will be suggested a filter when choosing a file. You still need to set up model validations.
|
|
2396
2530
|
#
|
|
2397
2531
|
# ==== Examples
|
|
@@ -2483,6 +2617,9 @@ module ActionView
|
|
|
2483
2617
|
# button("Create post")
|
|
2484
2618
|
# # => <button name='button' type='submit'>Create post</button>
|
|
2485
2619
|
#
|
|
2620
|
+
# button(:draft, value: true)
|
|
2621
|
+
# # => <button id="post_draft" name="post[draft]" value="true" type="submit">Create post</button>
|
|
2622
|
+
#
|
|
2486
2623
|
# button do
|
|
2487
2624
|
# content_tag(:strong, 'Ask me!')
|
|
2488
2625
|
# end
|
|
@@ -2497,14 +2634,31 @@ module ActionView
|
|
|
2497
2634
|
# # <strong>Create post</strong>
|
|
2498
2635
|
# # </button>
|
|
2499
2636
|
#
|
|
2637
|
+
# button(:draft, value: true) do
|
|
2638
|
+
# content_tag(:strong, "Save as draft")
|
|
2639
|
+
# end
|
|
2640
|
+
# # => <button id="post_draft" name="post[draft]" value="true" type="submit">
|
|
2641
|
+
# # <strong>Save as draft</strong>
|
|
2642
|
+
# # </button>
|
|
2643
|
+
#
|
|
2500
2644
|
def button(value = nil, options = {}, &block)
|
|
2501
|
-
|
|
2645
|
+
case value
|
|
2646
|
+
when Hash
|
|
2647
|
+
value, options = nil, value
|
|
2648
|
+
when Symbol
|
|
2649
|
+
value, options = nil, { name: field_name(value), id: field_id(value) }.merge!(options.to_h)
|
|
2650
|
+
end
|
|
2502
2651
|
value ||= submit_default_value
|
|
2503
2652
|
|
|
2504
2653
|
if block_given?
|
|
2505
2654
|
value = @template.capture { yield(value) }
|
|
2506
2655
|
end
|
|
2507
2656
|
|
|
2657
|
+
formmethod = options[:formmethod]
|
|
2658
|
+
if formmethod.present? && !/post|get/i.match?(formmethod) && !options.key?(:name) && !options.key?(:value)
|
|
2659
|
+
options.merge! formmethod: :post, name: "_method", value: formmethod
|
|
2660
|
+
end
|
|
2661
|
+
|
|
2508
2662
|
@template.button_tag(value, options)
|
|
2509
2663
|
end
|
|
2510
2664
|
|
|
@@ -2565,7 +2719,9 @@ module ActionView
|
|
|
2565
2719
|
else
|
|
2566
2720
|
options[:child_index] = nested_child_index(name)
|
|
2567
2721
|
end
|
|
2568
|
-
|
|
2722
|
+
if content = fields_for_nested_model("#{name}[#{options[:child_index]}]", child, options, block)
|
|
2723
|
+
output << content
|
|
2724
|
+
end
|
|
2569
2725
|
end
|
|
2570
2726
|
output
|
|
2571
2727
|
elsif association
|