actionview 7.1.5.2 → 8.1.2.1
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 +96 -436
- data/README.rdoc +1 -1
- data/lib/action_view/base.rb +29 -11
- data/lib/action_view/buffers.rb +1 -1
- data/lib/action_view/cache_expiry.rb +9 -3
- data/lib/action_view/dependency_tracker/erb_tracker.rb +37 -28
- data/lib/action_view/dependency_tracker/ruby_tracker.rb +43 -0
- data/lib/action_view/dependency_tracker/wildcard_resolver.rb +32 -0
- data/lib/action_view/dependency_tracker.rb +8 -2
- data/lib/action_view/digestor.rb +6 -2
- data/lib/action_view/gem_version.rb +3 -3
- data/lib/action_view/helpers/asset_tag_helper.rb +39 -8
- data/lib/action_view/helpers/atom_feed_helper.rb +1 -3
- data/lib/action_view/helpers/cache_helper.rb +10 -2
- data/lib/action_view/helpers/capture_helper.rb +2 -2
- data/lib/action_view/helpers/controller_helper.rb +6 -2
- data/lib/action_view/helpers/csrf_helper.rb +1 -1
- data/lib/action_view/helpers/date_helper.rb +28 -4
- data/lib/action_view/helpers/form_helper.rb +277 -272
- data/lib/action_view/helpers/form_options_helper.rb +39 -35
- data/lib/action_view/helpers/form_tag_helper.rb +115 -72
- data/lib/action_view/helpers/javascript_helper.rb +5 -1
- data/lib/action_view/helpers/number_helper.rb +14 -0
- data/lib/action_view/helpers/output_safety_helper.rb +5 -6
- 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 +225 -48
- data/lib/action_view/helpers/tags/base.rb +11 -9
- data/lib/action_view/helpers/tags/check_box.rb +9 -3
- data/lib/action_view/helpers/tags/collection_check_boxes.rb +4 -3
- data/lib/action_view/helpers/tags/collection_helpers.rb +2 -1
- data/lib/action_view/helpers/tags/datetime_field.rb +1 -1
- data/lib/action_view/helpers/tags/file_field.rb +7 -2
- data/lib/action_view/helpers/tags/hidden_field.rb +1 -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.rb +6 -1
- data/lib/action_view/helpers/tags/select_renderer.rb +6 -4
- 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/text_helper.rb +11 -4
- data/lib/action_view/helpers/translation_helper.rb +6 -1
- data/lib/action_view/helpers/url_helper.rb +42 -90
- data/lib/action_view/layouts.rb +9 -11
- data/lib/action_view/locale/en.yml +3 -0
- data/lib/action_view/log_subscriber.rb +9 -8
- data/lib/action_view/railtie.rb +12 -2
- data/lib/action_view/record_identifier.rb +22 -1
- data/lib/action_view/render_parser/prism_render_parser.rb +139 -0
- data/lib/action_view/{ripper_ast_parser.rb → render_parser/ripper_render_parser.rb} +162 -10
- data/lib/action_view/render_parser.rb +21 -169
- data/lib/action_view/renderer/abstract_renderer.rb +1 -1
- data/lib/action_view/renderer/partial_renderer.rb +18 -2
- data/lib/action_view/renderer/renderer.rb +32 -38
- data/lib/action_view/renderer/streaming_template_renderer.rb +8 -2
- data/lib/action_view/renderer/template_renderer.rb +3 -3
- data/lib/action_view/rendering.rb +6 -7
- data/lib/action_view/structured_event_subscriber.rb +97 -0
- data/lib/action_view/template/error.rb +18 -3
- data/lib/action_view/template/handlers/erb/erubi.rb +1 -1
- data/lib/action_view/template/handlers/erb.rb +77 -44
- data/lib/action_view/template/raw_file.rb +4 -0
- data/lib/action_view/template/renderable.rb +7 -1
- data/lib/action_view/template/resolver.rb +0 -3
- data/lib/action_view/template.rb +39 -12
- data/lib/action_view/test_case.rb +57 -62
- data/lib/action_view.rb +4 -0
- metadata +17 -14
- data/lib/action_view/dependency_tracker/ripper_tracker.rb +0 -59
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "cgi"
|
|
4
3
|
require "action_view/helpers/date_helper"
|
|
5
4
|
require "action_view/helpers/url_helper"
|
|
6
5
|
require "action_view/helpers/form_tag_helper"
|
|
7
6
|
require "action_view/helpers/active_model_helper"
|
|
8
7
|
require "action_view/model_naming"
|
|
9
8
|
require "action_view/record_identifier"
|
|
9
|
+
require "active_support/code_generator"
|
|
10
10
|
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"
|
|
@@ -29,20 +29,21 @@ 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
|
|
33
|
-
# a number of related helper methods.
|
|
34
|
-
#
|
|
35
|
-
#
|
|
36
|
-
#
|
|
32
|
+
# In \Rails, this is usually achieved by creating the form using either
|
|
33
|
+
# #form_with or #form_for and a number of related helper methods. These
|
|
34
|
+
# methods generate an appropriate <tt>form</tt> tag and yield a form
|
|
35
|
+
# builder object that knows the model the form is about. Input fields are
|
|
36
|
+
# created by calling methods defined on the form builder, which means they
|
|
37
|
+
# are able to generate the appropriate names and default values
|
|
37
38
|
# corresponding to the model attributes, as well as convenient IDs, etc.
|
|
38
|
-
# Conventions in the generated field names allow controllers to receive form
|
|
39
|
-
# nicely structured in +params+ with no effort on your side.
|
|
39
|
+
# Conventions in the generated field names allow controllers to receive form
|
|
40
|
+
# data nicely structured in +params+ with no effort on your side.
|
|
40
41
|
#
|
|
41
42
|
# For example, to create a new person you typically set up a new instance of
|
|
42
43
|
# +Person+ in the <tt>PeopleController#new</tt> action, <tt>@person</tt>, and
|
|
43
|
-
# in the view template pass that object to
|
|
44
|
+
# in the view template pass that object to #form_with or #form_for:
|
|
44
45
|
#
|
|
45
|
-
# <%=
|
|
46
|
+
# <%= form_with model: @person do |f| %>
|
|
46
47
|
# <%= f.label :first_name %>:
|
|
47
48
|
# <%= f.text_field :first_name %><br />
|
|
48
49
|
#
|
|
@@ -131,8 +132,8 @@ module ActionView
|
|
|
131
132
|
# <%= form_for :person do |f| %>
|
|
132
133
|
# First name: <%= f.text_field :first_name %><br />
|
|
133
134
|
# Last name : <%= f.text_field :last_name %><br />
|
|
134
|
-
# Biography : <%= f.
|
|
135
|
-
# Admin? : <%= f.
|
|
135
|
+
# Biography : <%= f.textarea :biography %><br />
|
|
136
|
+
# Admin? : <%= f.checkbox :admin %><br />
|
|
136
137
|
# <%= f.submit %>
|
|
137
138
|
# <% end %>
|
|
138
139
|
#
|
|
@@ -198,8 +199,8 @@ module ActionView
|
|
|
198
199
|
# <%= form_for :person do |f| %>
|
|
199
200
|
# First name: <%= f.text_field :first_name %>
|
|
200
201
|
# Last name : <%= f.text_field :last_name %>
|
|
201
|
-
# Biography : <%=
|
|
202
|
-
# Admin? : <%=
|
|
202
|
+
# Biography : <%= textarea :person, :biography %>
|
|
203
|
+
# Admin? : <%= checkbox_tag "person[admin]", "1", @person.company.admin? %>
|
|
203
204
|
# <%= f.submit %>
|
|
204
205
|
# <% end %>
|
|
205
206
|
#
|
|
@@ -207,23 +208,23 @@ module ActionView
|
|
|
207
208
|
# are designed to work with an object as base, like
|
|
208
209
|
# FormOptionsHelper#collection_select and DateHelper#datetime_select.
|
|
209
210
|
#
|
|
210
|
-
# ===
|
|
211
|
+
# === +form_for+ with a model object
|
|
211
212
|
#
|
|
212
213
|
# In the examples above, the object to be created or edited was
|
|
213
214
|
# represented by a symbol passed to +form_for+, and we noted that
|
|
214
215
|
# a string can also be used equivalently. It is also possible, however,
|
|
215
|
-
# to pass a model object itself to +form_for+. For example, if <tt>@
|
|
216
|
+
# to pass a model object itself to +form_for+. For example, if <tt>@article</tt>
|
|
216
217
|
# is an existing record you wish to edit, you can create the form using
|
|
217
218
|
#
|
|
218
|
-
# <%= form_for @
|
|
219
|
+
# <%= form_for @article do |f| %>
|
|
219
220
|
# ...
|
|
220
221
|
# <% end %>
|
|
221
222
|
#
|
|
222
223
|
# This behaves in almost the same way as outlined previously, with a
|
|
223
224
|
# couple of small exceptions. First, the prefix used to name the input
|
|
224
225
|
# elements within the form (hence the key that denotes them in the +params+
|
|
225
|
-
# hash) is actually derived from the object's _class_, e.g. <tt>params[:
|
|
226
|
-
# if the object's class is +
|
|
226
|
+
# hash) is actually derived from the object's _class_, e.g. <tt>params[:article]</tt>
|
|
227
|
+
# if the object's class is +Article+. However, this can be overwritten using
|
|
227
228
|
# the <tt>:as</tt> option, e.g. -
|
|
228
229
|
#
|
|
229
230
|
# <%= form_for(@person, as: :client) do |f| %>
|
|
@@ -235,15 +236,15 @@ module ActionView
|
|
|
235
236
|
# Secondly, the field values shown when the form is initially displayed
|
|
236
237
|
# are taken from the attributes of the object passed to +form_for+,
|
|
237
238
|
# regardless of whether the object is an instance
|
|
238
|
-
# variable. So, for example, if we had a _local_ variable +
|
|
239
|
+
# variable. So, for example, if we had a _local_ variable +article+
|
|
239
240
|
# representing an existing record,
|
|
240
241
|
#
|
|
241
|
-
# <%= form_for
|
|
242
|
+
# <%= form_for article do |f| %>
|
|
242
243
|
# ...
|
|
243
244
|
# <% end %>
|
|
244
245
|
#
|
|
245
246
|
# would produce a form with fields whose initial state reflect the current
|
|
246
|
-
# values of the attributes of +
|
|
247
|
+
# values of the attributes of +article+.
|
|
247
248
|
#
|
|
248
249
|
# === Resource-oriented style
|
|
249
250
|
#
|
|
@@ -255,49 +256,49 @@ module ActionView
|
|
|
255
256
|
# in <tt>config/routes.rb</tt>. In this case \Rails will simply infer the
|
|
256
257
|
# appropriate URL from the record itself. For example,
|
|
257
258
|
#
|
|
258
|
-
# <%= form_for @
|
|
259
|
+
# <%= form_for @article do |f| %>
|
|
259
260
|
# ...
|
|
260
261
|
# <% end %>
|
|
261
262
|
#
|
|
262
263
|
# is then equivalent to something like:
|
|
263
264
|
#
|
|
264
|
-
# <%= form_for @
|
|
265
|
+
# <%= form_for @article, as: :article, url: article_path(@article), method: :patch, html: { class: "edit_article", id: "edit_article_45" } do |f| %>
|
|
265
266
|
# ...
|
|
266
267
|
# <% end %>
|
|
267
268
|
#
|
|
268
269
|
# And for a new record
|
|
269
270
|
#
|
|
270
|
-
# <%= form_for(
|
|
271
|
+
# <%= form_for(Article.new) do |f| %>
|
|
271
272
|
# ...
|
|
272
273
|
# <% end %>
|
|
273
274
|
#
|
|
274
275
|
# is equivalent to something like:
|
|
275
276
|
#
|
|
276
|
-
# <%= form_for @
|
|
277
|
+
# <%= form_for @article, as: :article, url: articles_path, html: { class: "new_article", id: "new_article" } do |f| %>
|
|
277
278
|
# ...
|
|
278
279
|
# <% end %>
|
|
279
280
|
#
|
|
280
281
|
# However you can still overwrite individual conventions, such as:
|
|
281
282
|
#
|
|
282
|
-
# <%= form_for(@
|
|
283
|
+
# <%= form_for(@article, url: super_articles_path) do |f| %>
|
|
283
284
|
# ...
|
|
284
285
|
# <% end %>
|
|
285
286
|
#
|
|
286
287
|
# You can omit the <tt>action</tt> attribute by passing <tt>url: false</tt>:
|
|
287
288
|
#
|
|
288
|
-
# <%= form_for(@
|
|
289
|
+
# <%= form_for(@article, url: false) do |f| %>
|
|
289
290
|
# ...
|
|
290
291
|
# <% end %>
|
|
291
292
|
#
|
|
292
293
|
# You can also set the answer format, like this:
|
|
293
294
|
#
|
|
294
|
-
# <%= form_for(@
|
|
295
|
+
# <%= form_for(@article, format: :json) do |f| %>
|
|
295
296
|
# ...
|
|
296
297
|
# <% end %>
|
|
297
298
|
#
|
|
298
|
-
# For namespaced routes, like +
|
|
299
|
+
# For namespaced routes, like +admin_article_url+:
|
|
299
300
|
#
|
|
300
|
-
# <%= form_for([:admin, @
|
|
301
|
+
# <%= form_for([:admin, @article]) do |f| %>
|
|
301
302
|
# ...
|
|
302
303
|
# <% end %>
|
|
303
304
|
#
|
|
@@ -333,7 +334,7 @@ module ActionView
|
|
|
333
334
|
#
|
|
334
335
|
# Example:
|
|
335
336
|
#
|
|
336
|
-
# <%= form_for(@
|
|
337
|
+
# <%= form_for(@article, remote: true) do |f| %>
|
|
337
338
|
# ...
|
|
338
339
|
# <% end %>
|
|
339
340
|
#
|
|
@@ -349,7 +350,7 @@ module ActionView
|
|
|
349
350
|
# You can set data attributes directly by passing in a data hash, but all other HTML options must be wrapped in
|
|
350
351
|
# the HTML key. Example:
|
|
351
352
|
#
|
|
352
|
-
# <%= form_for(@
|
|
353
|
+
# <%= form_for(@article, data: { behavior: "autosave" }, html: { name: "go" }) do |f| %>
|
|
353
354
|
# ...
|
|
354
355
|
# <% end %>
|
|
355
356
|
#
|
|
@@ -362,17 +363,17 @@ module ActionView
|
|
|
362
363
|
#
|
|
363
364
|
# === Removing hidden model id's
|
|
364
365
|
#
|
|
365
|
-
# The form_for method automatically includes the model id as a hidden field in the form.
|
|
366
|
+
# The +form_for+ method automatically includes the model id as a hidden field in the form.
|
|
366
367
|
# This is used to maintain the correlation between the form data and its associated model.
|
|
367
368
|
# Some ORM systems do not use IDs on nested models so in this case you want to be able
|
|
368
369
|
# to disable the hidden id.
|
|
369
370
|
#
|
|
370
|
-
# In the following example the
|
|
371
|
+
# In the following example the Article model has many Comments stored within it in a NoSQL database,
|
|
371
372
|
# thus there is no primary key for comments.
|
|
372
373
|
#
|
|
373
374
|
# Example:
|
|
374
375
|
#
|
|
375
|
-
# <%= form_for(@
|
|
376
|
+
# <%= form_for(@article) do |f| %>
|
|
376
377
|
# <%= f.fields_for(:comments, include_id: false) do |cf| %>
|
|
377
378
|
# ...
|
|
378
379
|
# <% end %>
|
|
@@ -388,8 +389,8 @@ module ActionView
|
|
|
388
389
|
# <%= form_for @person, url: { action: "create" }, builder: LabellingFormBuilder do |f| %>
|
|
389
390
|
# <%= f.text_field :first_name %>
|
|
390
391
|
# <%= f.text_field :last_name %>
|
|
391
|
-
# <%= f.
|
|
392
|
-
# <%= f.
|
|
392
|
+
# <%= f.textarea :biography %>
|
|
393
|
+
# <%= f.checkbox :admin %>
|
|
393
394
|
# <%= f.submit %>
|
|
394
395
|
# <% end %>
|
|
395
396
|
#
|
|
@@ -436,7 +437,7 @@ module ActionView
|
|
|
436
437
|
|
|
437
438
|
case record
|
|
438
439
|
when String, Symbol
|
|
439
|
-
model =
|
|
440
|
+
model = false
|
|
440
441
|
object_name = record
|
|
441
442
|
else
|
|
442
443
|
model = record
|
|
@@ -484,12 +485,12 @@ module ActionView
|
|
|
484
485
|
# Creates a form tag based on mixing URLs, scopes, or models.
|
|
485
486
|
#
|
|
486
487
|
# # Using just a URL:
|
|
487
|
-
# <%= form_with url:
|
|
488
|
+
# <%= form_with url: articles_path do |form| %>
|
|
488
489
|
# <%= form.text_field :title %>
|
|
489
490
|
# <% end %>
|
|
490
491
|
# # =>
|
|
491
|
-
# <form action="/
|
|
492
|
-
# <input type="text" name="title"
|
|
492
|
+
# <form action="/articles" method="post">
|
|
493
|
+
# <input type="text" name="title" />
|
|
493
494
|
# </form>
|
|
494
495
|
#
|
|
495
496
|
# # With an intentionally empty URL:
|
|
@@ -498,37 +499,36 @@ module ActionView
|
|
|
498
499
|
# <% end %>
|
|
499
500
|
# # =>
|
|
500
501
|
# <form method="post">
|
|
501
|
-
# <input type="text" name="title"
|
|
502
|
+
# <input type="text" name="title" />
|
|
502
503
|
# </form>
|
|
503
504
|
#
|
|
504
505
|
# # Adding a scope prefixes the input field names:
|
|
505
|
-
# <%= form_with scope: :
|
|
506
|
+
# <%= form_with scope: :article, url: articles_path do |form| %>
|
|
506
507
|
# <%= form.text_field :title %>
|
|
507
508
|
# <% end %>
|
|
508
509
|
# # =>
|
|
509
|
-
# <form action="/
|
|
510
|
-
# <input type="text" name="
|
|
510
|
+
# <form action="/articles" method="post">
|
|
511
|
+
# <input type="text" name="article[title]" />
|
|
511
512
|
# </form>
|
|
512
513
|
#
|
|
513
514
|
# # Using a model infers both the URL and scope:
|
|
514
|
-
# <%= form_with model:
|
|
515
|
+
# <%= form_with model: Article.new do |form| %>
|
|
515
516
|
# <%= form.text_field :title %>
|
|
516
517
|
# <% end %>
|
|
517
518
|
# # =>
|
|
518
|
-
# <form action="/
|
|
519
|
-
# <input type="text" name="
|
|
519
|
+
# <form action="/articles" method="post">
|
|
520
|
+
# <input type="text" name="article[title]" />
|
|
520
521
|
# </form>
|
|
521
522
|
#
|
|
522
523
|
# # An existing model makes an update form and fills out field values:
|
|
523
|
-
# <%= form_with model:
|
|
524
|
+
# <%= form_with model: Article.first do |form| %>
|
|
524
525
|
# <%= form.text_field :title %>
|
|
525
526
|
# <% end %>
|
|
526
527
|
# # =>
|
|
527
|
-
# <form action="/
|
|
528
|
-
# <input type="hidden" name="_method" value="patch"
|
|
529
|
-
# <input type="text" name="
|
|
528
|
+
# <form action="/articles/1" method="post">
|
|
529
|
+
# <input type="hidden" name="_method" value="patch" />
|
|
530
|
+
# <input type="text" name="article[title]" value="<the title of the article>" />
|
|
530
531
|
# </form>
|
|
531
|
-
#
|
|
532
532
|
# # Though the fields don't have to correspond to model attributes:
|
|
533
533
|
# <%= form_with model: Cat.new do |form| %>
|
|
534
534
|
# <%= form.text_field :cats_dont_have_gills %>
|
|
@@ -536,13 +536,13 @@ module ActionView
|
|
|
536
536
|
# <% end %>
|
|
537
537
|
# # =>
|
|
538
538
|
# <form action="/cats" method="post">
|
|
539
|
-
# <input type="text" name="cat[cats_dont_have_gills]"
|
|
540
|
-
# <input type="text" name="cat[but_in_forms_they_can]"
|
|
539
|
+
# <input type="text" name="cat[cats_dont_have_gills]" />
|
|
540
|
+
# <input type="text" name="cat[but_in_forms_they_can]" />
|
|
541
541
|
# </form>
|
|
542
542
|
#
|
|
543
543
|
# The parameters in the forms are accessible in controllers according to
|
|
544
|
-
# their name nesting. So inputs named +title+ and <tt>
|
|
545
|
-
# accessible as <tt>params[:title]</tt> and <tt>params[:
|
|
544
|
+
# their name nesting. So inputs named +title+ and <tt>article[title]</tt> are
|
|
545
|
+
# accessible as <tt>params[:title]</tt> and <tt>params[:article][:title]</tt>
|
|
546
546
|
# respectively.
|
|
547
547
|
#
|
|
548
548
|
# For ease of comparison the examples above left out the submit button,
|
|
@@ -558,25 +558,25 @@ module ActionView
|
|
|
558
558
|
#
|
|
559
559
|
# So when passing such a model record, \Rails infers the URL and method.
|
|
560
560
|
#
|
|
561
|
-
# <%= form_with model: @
|
|
561
|
+
# <%= form_with model: @article do |form| %>
|
|
562
562
|
# ...
|
|
563
563
|
# <% end %>
|
|
564
564
|
#
|
|
565
565
|
# is then equivalent to something like:
|
|
566
566
|
#
|
|
567
|
-
# <%= form_with scope: :
|
|
567
|
+
# <%= form_with scope: :article, url: article_path(@article), method: :patch do |form| %>
|
|
568
568
|
# ...
|
|
569
569
|
# <% end %>
|
|
570
570
|
#
|
|
571
571
|
# And for a new record
|
|
572
572
|
#
|
|
573
|
-
# <%= form_with model:
|
|
573
|
+
# <%= form_with model: Article.new do |form| %>
|
|
574
574
|
# ...
|
|
575
575
|
# <% end %>
|
|
576
576
|
#
|
|
577
577
|
# is equivalent to something like:
|
|
578
578
|
#
|
|
579
|
-
# <%= form_with scope: :
|
|
579
|
+
# <%= form_with scope: :article, url: articles_path do |form| %>
|
|
580
580
|
# ...
|
|
581
581
|
# <% end %>
|
|
582
582
|
#
|
|
@@ -605,7 +605,7 @@ module ActionView
|
|
|
605
605
|
# If the model is a new record a create form is generated, if an
|
|
606
606
|
# existing record, however, an update form is generated.
|
|
607
607
|
# Pass <tt>:scope</tt> or <tt>:url</tt> to override the defaults.
|
|
608
|
-
# E.g. turn <tt>params[:
|
|
608
|
+
# E.g. turn <tt>params[:article]</tt> into <tt>params[:blog]</tt>.
|
|
609
609
|
# * <tt>:authenticity_token</tt> - Authenticity token to use in the form.
|
|
610
610
|
# Override with a custom authenticity token or pass <tt>false</tt> to
|
|
611
611
|
# skip the authenticity token field altogether.
|
|
@@ -638,14 +638,14 @@ module ActionView
|
|
|
638
638
|
#
|
|
639
639
|
# When not passing a block, +form_with+ just generates an opening form tag.
|
|
640
640
|
#
|
|
641
|
-
# <%= form_with(model: @
|
|
642
|
-
# <%= form_with(model: @
|
|
643
|
-
# <%= form_with(model: @
|
|
644
|
-
# <%= form_with(model: @
|
|
641
|
+
# <%= form_with(model: @article, url: super_articles_path) %>
|
|
642
|
+
# <%= form_with(model: @article, scope: :blog) %>
|
|
643
|
+
# <%= form_with(model: @article, format: :json) %>
|
|
644
|
+
# <%= form_with(model: @article, authenticity_token: false) %> # Disables the token.
|
|
645
645
|
#
|
|
646
|
-
# For namespaced routes, like +
|
|
646
|
+
# For namespaced routes, like +admin_article_url+:
|
|
647
647
|
#
|
|
648
|
-
# <%= form_with(model: [ :admin, @
|
|
648
|
+
# <%= form_with(model: [ :admin, @article ]) do |form| %>
|
|
649
649
|
# ...
|
|
650
650
|
# <% end %>
|
|
651
651
|
#
|
|
@@ -668,8 +668,8 @@ module ActionView
|
|
|
668
668
|
# <%= form.text_field :first_name %>
|
|
669
669
|
# <%= form.text_field :last_name %>
|
|
670
670
|
#
|
|
671
|
-
# <%=
|
|
672
|
-
# <%=
|
|
671
|
+
# <%= textarea :person, :biography %>
|
|
672
|
+
# <%= checkbox_tag "person[admin]", "1", @person.company.admin? %>
|
|
673
673
|
#
|
|
674
674
|
# <%= form.submit %>
|
|
675
675
|
# <% end %>
|
|
@@ -693,13 +693,13 @@ module ActionView
|
|
|
693
693
|
# You can set data attributes directly in a data hash, but HTML options
|
|
694
694
|
# besides id and class must be wrapped in an HTML key:
|
|
695
695
|
#
|
|
696
|
-
# <%= form_with(model: @
|
|
696
|
+
# <%= form_with(model: @article, data: { behavior: "autosave" }, html: { name: "go" }) do |form| %>
|
|
697
697
|
# ...
|
|
698
698
|
# <% end %>
|
|
699
699
|
#
|
|
700
700
|
# generates
|
|
701
701
|
#
|
|
702
|
-
# <form action="/
|
|
702
|
+
# <form action="/articles/123" method="post" data-behavior="autosave" name="go">
|
|
703
703
|
# <input name="_method" type="hidden" value="patch" />
|
|
704
704
|
# ...
|
|
705
705
|
# </form>
|
|
@@ -711,10 +711,10 @@ module ActionView
|
|
|
711
711
|
# Some ORM systems do not use IDs on nested models so in this case you want to be able
|
|
712
712
|
# to disable the hidden id.
|
|
713
713
|
#
|
|
714
|
-
# In the following example the
|
|
714
|
+
# In the following example the Article model has many Comments stored within it in a NoSQL database,
|
|
715
715
|
# thus there is no primary key for comments.
|
|
716
716
|
#
|
|
717
|
-
# <%= form_with(model: @
|
|
717
|
+
# <%= form_with(model: @article) do |form| %>
|
|
718
718
|
# <%= form.fields(:comments, skip_id: true) do |fields| %>
|
|
719
719
|
# ...
|
|
720
720
|
# <% end %>
|
|
@@ -730,8 +730,8 @@ module ActionView
|
|
|
730
730
|
# <%= form_with model: @person, url: { action: "create" }, builder: LabellingFormBuilder do |form| %>
|
|
731
731
|
# <%= form.text_field :first_name %>
|
|
732
732
|
# <%= form.text_field :last_name %>
|
|
733
|
-
# <%= form.
|
|
734
|
-
# <%= form.
|
|
733
|
+
# <%= form.textarea :biography %>
|
|
734
|
+
# <%= form.checkbox :admin %>
|
|
735
735
|
# <%= form.submit %>
|
|
736
736
|
# <% end %>
|
|
737
737
|
#
|
|
@@ -752,7 +752,9 @@ module ActionView
|
|
|
752
752
|
# def labelled_form_with(**options, &block)
|
|
753
753
|
# form_with(**options.merge(builder: LabellingFormBuilder), &block)
|
|
754
754
|
# end
|
|
755
|
-
def form_with(model:
|
|
755
|
+
def form_with(model: false, scope: nil, url: nil, format: nil, **options, &block)
|
|
756
|
+
raise ArgumentError, "Passed nil to the :model argument, expect an object or false" if model.nil?
|
|
757
|
+
|
|
756
758
|
options = { allow_method_names_outside_object: true, skip_default_ids: !form_with_generates_ids }.merge!(options)
|
|
757
759
|
|
|
758
760
|
if model
|
|
@@ -781,28 +783,28 @@ module ActionView
|
|
|
781
783
|
end
|
|
782
784
|
end
|
|
783
785
|
|
|
784
|
-
# Creates a scope around a specific model object like
|
|
785
|
-
# doesn't create the form tags themselves. This makes fields_for
|
|
786
|
-
# for specifying additional model objects in the same form.
|
|
786
|
+
# 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
|
+
# suitable for specifying additional model objects in the same form.
|
|
787
789
|
#
|
|
788
|
-
# Although the usage and purpose of +fields_for+ is similar to
|
|
789
|
-
# its method signature is slightly different. Like
|
|
790
|
+
# Although the usage and purpose of +fields_for+ is similar to #form_with's,
|
|
791
|
+
# its method signature is slightly different. Like #form_with, it yields
|
|
790
792
|
# a FormBuilder object associated with a particular model object to a block,
|
|
791
793
|
# and within the block allows methods to be called on the builder to
|
|
792
794
|
# generate fields associated with the model object. Fields may reflect
|
|
793
795
|
# a model object in two ways - how they are named (hence how submitted
|
|
794
796
|
# values appear within the +params+ hash in the controller) and what
|
|
795
|
-
# default values are shown when the form
|
|
796
|
-
#
|
|
797
|
+
# default values are shown when the form fields are first displayed.
|
|
798
|
+
# In order for both of these features to be specified independently,
|
|
797
799
|
# both an object name (represented by either a symbol or string) and the
|
|
798
800
|
# object itself can be passed to the method separately -
|
|
799
801
|
#
|
|
800
|
-
# <%=
|
|
802
|
+
# <%= form_with model: @person do |person_form| %>
|
|
801
803
|
# First name: <%= person_form.text_field :first_name %>
|
|
802
804
|
# Last name : <%= person_form.text_field :last_name %>
|
|
803
805
|
#
|
|
804
806
|
# <%= fields_for :permission, @person.permission do |permission_fields| %>
|
|
805
|
-
# Admin? : <%= permission_fields.
|
|
807
|
+
# Admin? : <%= permission_fields.checkbox :admin %>
|
|
806
808
|
# <% end %>
|
|
807
809
|
#
|
|
808
810
|
# <%= person_form.submit %>
|
|
@@ -819,7 +821,7 @@ module ActionView
|
|
|
819
821
|
# object to +fields_for+ -
|
|
820
822
|
#
|
|
821
823
|
# <%= fields_for :permission do |permission_fields| %>
|
|
822
|
-
# Admin?: <%= permission_fields.
|
|
824
|
+
# Admin?: <%= permission_fields.checkbox :admin %>
|
|
823
825
|
# <% end %>
|
|
824
826
|
#
|
|
825
827
|
# ...in which case, if <tt>:permission</tt> also happens to be the name of an
|
|
@@ -831,7 +833,7 @@ module ActionView
|
|
|
831
833
|
# name has been omitted) -
|
|
832
834
|
#
|
|
833
835
|
# <%= fields_for @person.permission do |permission_fields| %>
|
|
834
|
-
# Admin?: <%= permission_fields.
|
|
836
|
+
# Admin?: <%= permission_fields.checkbox :admin %>
|
|
835
837
|
# <% end %>
|
|
836
838
|
#
|
|
837
839
|
# and +fields_for+ will derive the required name of the field from the
|
|
@@ -845,7 +847,7 @@ module ActionView
|
|
|
845
847
|
# === Nested Attributes Examples
|
|
846
848
|
#
|
|
847
849
|
# When the object belonging to the current scope has a nested attribute
|
|
848
|
-
# writer for a certain attribute, fields_for will yield a new scope
|
|
850
|
+
# writer for a certain attribute, +fields_for+ will yield a new scope
|
|
849
851
|
# for that attribute. This allows you to create forms that set or change
|
|
850
852
|
# the attributes of a parent object and its associations in one go.
|
|
851
853
|
#
|
|
@@ -878,7 +880,7 @@ module ActionView
|
|
|
878
880
|
#
|
|
879
881
|
# This model can now be used with a nested fields_for, like so:
|
|
880
882
|
#
|
|
881
|
-
# <%=
|
|
883
|
+
# <%= form_with model: @person do |person_form| %>
|
|
882
884
|
# ...
|
|
883
885
|
# <%= person_form.fields_for :address do |address_fields| %>
|
|
884
886
|
# Street : <%= address_fields.text_field :street %>
|
|
@@ -908,11 +910,11 @@ module ActionView
|
|
|
908
910
|
# with a value that evaluates to +true+, you will destroy the associated
|
|
909
911
|
# model (e.g. 1, '1', true, or 'true'):
|
|
910
912
|
#
|
|
911
|
-
# <%=
|
|
913
|
+
# <%= form_with model: @person do |person_form| %>
|
|
912
914
|
# ...
|
|
913
915
|
# <%= person_form.fields_for :address do |address_fields| %>
|
|
914
916
|
# ...
|
|
915
|
-
# Delete: <%= address_fields.
|
|
917
|
+
# Delete: <%= address_fields.checkbox :_destroy %>
|
|
916
918
|
# <% end %>
|
|
917
919
|
# ...
|
|
918
920
|
# <% end %>
|
|
@@ -934,7 +936,7 @@ module ActionView
|
|
|
934
936
|
# end
|
|
935
937
|
#
|
|
936
938
|
# Note that the <tt>projects_attributes=</tt> writer method is in fact
|
|
937
|
-
# required for fields_for to correctly identify <tt>:projects</tt> as a
|
|
939
|
+
# required for +fields_for+ to correctly identify <tt>:projects</tt> as a
|
|
938
940
|
# collection, and the correct indices to be set in the form markup.
|
|
939
941
|
#
|
|
940
942
|
# When projects is already an association on Person you can use
|
|
@@ -946,10 +948,10 @@ module ActionView
|
|
|
946
948
|
# end
|
|
947
949
|
#
|
|
948
950
|
# This model can now be used with a nested fields_for. The block given to
|
|
949
|
-
# the nested fields_for call will be repeated for each instance in the
|
|
951
|
+
# the nested +fields_for+ call will be repeated for each instance in the
|
|
950
952
|
# collection:
|
|
951
953
|
#
|
|
952
|
-
# <%=
|
|
954
|
+
# <%= form_with model: @person do |person_form| %>
|
|
953
955
|
# ...
|
|
954
956
|
# <%= person_form.fields_for :projects do |project_fields| %>
|
|
955
957
|
# <% if project_fields.object.active? %>
|
|
@@ -961,7 +963,7 @@ module ActionView
|
|
|
961
963
|
#
|
|
962
964
|
# It's also possible to specify the instance to be used:
|
|
963
965
|
#
|
|
964
|
-
# <%=
|
|
966
|
+
# <%= form_with model: @person do |person_form| %>
|
|
965
967
|
# ...
|
|
966
968
|
# <% @person.projects.each do |project| %>
|
|
967
969
|
# <% if project.active? %>
|
|
@@ -975,7 +977,7 @@ module ActionView
|
|
|
975
977
|
#
|
|
976
978
|
# Or a collection to be used:
|
|
977
979
|
#
|
|
978
|
-
# <%=
|
|
980
|
+
# <%= form_with model: @person do |person_form| %>
|
|
979
981
|
# ...
|
|
980
982
|
# <%= person_form.fields_for :projects, @active_projects do |project_fields| %>
|
|
981
983
|
# Name: <%= project_fields.text_field :name %>
|
|
@@ -997,10 +999,10 @@ module ActionView
|
|
|
997
999
|
# parameter with a value that evaluates to +true+
|
|
998
1000
|
# (e.g. 1, '1', true, or 'true'):
|
|
999
1001
|
#
|
|
1000
|
-
# <%=
|
|
1002
|
+
# <%= form_with model: @person do |person_form| %>
|
|
1001
1003
|
# ...
|
|
1002
1004
|
# <%= person_form.fields_for :projects do |project_fields| %>
|
|
1003
|
-
# Delete: <%= project_fields.
|
|
1005
|
+
# Delete: <%= project_fields.checkbox :_destroy %>
|
|
1004
1006
|
# <% end %>
|
|
1005
1007
|
# ...
|
|
1006
1008
|
# <% end %>
|
|
@@ -1009,7 +1011,7 @@ module ActionView
|
|
|
1009
1011
|
# object in the array. For this purpose, the <tt>index</tt> method is
|
|
1010
1012
|
# available in the FormBuilder object.
|
|
1011
1013
|
#
|
|
1012
|
-
# <%=
|
|
1014
|
+
# <%= form_with model: @person do |person_form| %>
|
|
1013
1015
|
# ...
|
|
1014
1016
|
# <%= person_form.fields_for :projects do |project_fields| %>
|
|
1015
1017
|
# Project #<%= project_fields.index %>
|
|
@@ -1018,10 +1020,10 @@ module ActionView
|
|
|
1018
1020
|
# ...
|
|
1019
1021
|
# <% end %>
|
|
1020
1022
|
#
|
|
1021
|
-
# Note that fields_for will automatically generate a hidden field
|
|
1023
|
+
# Note that +fields_for+ will automatically generate a hidden field
|
|
1022
1024
|
# to store the ID of the record if it responds to <tt>persisted?</tt>.
|
|
1023
1025
|
# 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
|
|
1026
|
+
# can pass <tt>include_id: false</tt> to prevent +fields_for+ from
|
|
1025
1027
|
# rendering it automatically.
|
|
1026
1028
|
def fields_for(record_name, record_object = nil, options = {}, &block)
|
|
1027
1029
|
options = { model: record_object, allow_method_names_outside_object: false, skip_default_ids: false }.merge!(options)
|
|
@@ -1030,7 +1032,7 @@ module ActionView
|
|
|
1030
1032
|
end
|
|
1031
1033
|
|
|
1032
1034
|
# Scopes input fields with either an explicit scope or model.
|
|
1033
|
-
# Like
|
|
1035
|
+
# Like #form_with does with <tt>:scope</tt> or <tt>:model</tt>,
|
|
1034
1036
|
# except it doesn't output the form tags.
|
|
1035
1037
|
#
|
|
1036
1038
|
# # Using a scope prefixes the input field names:
|
|
@@ -1045,8 +1047,8 @@ module ActionView
|
|
|
1045
1047
|
# <% end %>
|
|
1046
1048
|
# # => <input type="text" name="comment[body]" value="full bodied">
|
|
1047
1049
|
#
|
|
1048
|
-
# # Using
|
|
1049
|
-
# <%= form_with model: @
|
|
1050
|
+
# # Using `fields` with `form_with`:
|
|
1051
|
+
# <%= form_with model: @article do |form| %>
|
|
1050
1052
|
# <%= form.text_field :title %>
|
|
1051
1053
|
#
|
|
1052
1054
|
# <%= form.fields :comment do |fields| %>
|
|
@@ -1054,21 +1056,21 @@ module ActionView
|
|
|
1054
1056
|
# <% end %>
|
|
1055
1057
|
# <% end %>
|
|
1056
1058
|
#
|
|
1057
|
-
# Much like
|
|
1059
|
+
# Much like #form_with a FormBuilder instance associated with the scope
|
|
1058
1060
|
# or model is yielded, so any generated field names are prefixed with
|
|
1059
1061
|
# either the passed scope or the scope inferred from the <tt>:model</tt>.
|
|
1060
1062
|
#
|
|
1061
1063
|
# === Mixing with other form helpers
|
|
1062
1064
|
#
|
|
1063
|
-
# While
|
|
1065
|
+
# While #form_with uses a FormBuilder object it's possible to mix and
|
|
1064
1066
|
# match the stand-alone FormHelper methods and methods
|
|
1065
1067
|
# from FormTagHelper:
|
|
1066
1068
|
#
|
|
1067
1069
|
# <%= fields model: @comment do |fields| %>
|
|
1068
1070
|
# <%= fields.text_field :body %>
|
|
1069
1071
|
#
|
|
1070
|
-
# <%=
|
|
1071
|
-
# <%=
|
|
1072
|
+
# <%= textarea :commenter, :biography %>
|
|
1073
|
+
# <%= checkbox_tag "comment[all_caps]", "1", @comment.commenter.hulk_mode? %>
|
|
1072
1074
|
# <% end %>
|
|
1073
1075
|
#
|
|
1074
1076
|
# Same goes for the methods in FormOptionsHelper and DateHelper designed
|
|
@@ -1094,58 +1096,58 @@ module ActionView
|
|
|
1094
1096
|
# target labels for radio_button tags (where the value is used in the ID of the input tag).
|
|
1095
1097
|
#
|
|
1096
1098
|
# ==== Examples
|
|
1097
|
-
# label(:
|
|
1098
|
-
# # => <label for="
|
|
1099
|
+
# label(:article, :title)
|
|
1100
|
+
# # => <label for="article_title">Title</label>
|
|
1099
1101
|
#
|
|
1100
1102
|
# You can localize your labels based on model and attribute names.
|
|
1101
1103
|
# For example you can define the following in your locale (e.g. en.yml)
|
|
1102
1104
|
#
|
|
1103
1105
|
# helpers:
|
|
1104
1106
|
# label:
|
|
1105
|
-
#
|
|
1107
|
+
# article:
|
|
1106
1108
|
# body: "Write your entire text here"
|
|
1107
1109
|
#
|
|
1108
1110
|
# Which then will result in
|
|
1109
1111
|
#
|
|
1110
|
-
# label(:
|
|
1111
|
-
# # => <label for="
|
|
1112
|
+
# label(:article, :body)
|
|
1113
|
+
# # => <label for="article_body">Write your entire text here</label>
|
|
1112
1114
|
#
|
|
1113
1115
|
# Localization can also be based purely on the translation of the attribute-name
|
|
1114
1116
|
# (if you are using ActiveRecord):
|
|
1115
1117
|
#
|
|
1116
1118
|
# activerecord:
|
|
1117
1119
|
# attributes:
|
|
1118
|
-
#
|
|
1120
|
+
# article:
|
|
1119
1121
|
# cost: "Total cost"
|
|
1120
1122
|
#
|
|
1121
1123
|
# <code></code>
|
|
1122
1124
|
#
|
|
1123
|
-
# label(:
|
|
1124
|
-
# # => <label for="
|
|
1125
|
+
# label(:article, :cost)
|
|
1126
|
+
# # => <label for="article_cost">Total cost</label>
|
|
1125
1127
|
#
|
|
1126
|
-
# label(:
|
|
1127
|
-
# # => <label for="
|
|
1128
|
+
# label(:article, :title, "A short title")
|
|
1129
|
+
# # => <label for="article_title">A short title</label>
|
|
1128
1130
|
#
|
|
1129
|
-
# label(:
|
|
1130
|
-
# # => <label for="
|
|
1131
|
+
# label(:article, :title, "A short title", class: "title_label")
|
|
1132
|
+
# # => <label for="article_title" class="title_label">A short title</label>
|
|
1131
1133
|
#
|
|
1132
|
-
# label(:
|
|
1133
|
-
# # => <label for="
|
|
1134
|
+
# label(:article, :privacy, "Public Article", value: "public")
|
|
1135
|
+
# # => <label for="article_privacy_public">Public Article</label>
|
|
1134
1136
|
#
|
|
1135
|
-
# label(:
|
|
1137
|
+
# label(:article, :cost) do |translation|
|
|
1136
1138
|
# content_tag(:span, translation, class: "cost_label")
|
|
1137
1139
|
# end
|
|
1138
|
-
# # => <label for="
|
|
1140
|
+
# # => <label for="article_cost"><span class="cost_label">Total cost</span></label>
|
|
1139
1141
|
#
|
|
1140
|
-
# label(:
|
|
1142
|
+
# label(:article, :cost) do |builder|
|
|
1141
1143
|
# content_tag(:span, builder.translation, class: "cost_label")
|
|
1142
1144
|
# end
|
|
1143
|
-
# # => <label for="
|
|
1145
|
+
# # => <label for="article_cost"><span class="cost_label">Total cost</span></label>
|
|
1144
1146
|
#
|
|
1145
|
-
# label(:
|
|
1147
|
+
# label(:article, :terms) do
|
|
1146
1148
|
# raw('Accept <a href="/terms">Terms</a>.')
|
|
1147
1149
|
# end
|
|
1148
|
-
# # => <label for="
|
|
1150
|
+
# # => <label for="article_terms">Accept <a href="/terms">Terms</a>.</label>
|
|
1149
1151
|
def label(object_name, method, content_or_options = nil, options = nil, &block)
|
|
1150
1152
|
Tags::Label.new(object_name, method, self, content_or_options, options).render(&block)
|
|
1151
1153
|
end
|
|
@@ -1156,14 +1158,14 @@ module ActionView
|
|
|
1156
1158
|
# shown.
|
|
1157
1159
|
#
|
|
1158
1160
|
# ==== Examples
|
|
1159
|
-
# text_field(:
|
|
1160
|
-
# # => <input type="text" id="
|
|
1161
|
+
# text_field(:article, :title, size: 20)
|
|
1162
|
+
# # => <input type="text" id="article_title" name="article[title]" size="20" value="#{@article.title}" />
|
|
1161
1163
|
#
|
|
1162
|
-
# text_field(:
|
|
1163
|
-
# # => <input type="text" id="
|
|
1164
|
+
# text_field(:article, :title, class: "create_input")
|
|
1165
|
+
# # => <input type="text" id="article_title" name="article[title]" value="#{@article.title}" class="create_input" />
|
|
1164
1166
|
#
|
|
1165
|
-
# text_field(:
|
|
1166
|
-
# # => <input type="text" id="
|
|
1167
|
+
# text_field(:article, :title, maxlength: 30, class: "title_input")
|
|
1168
|
+
# # => <input type="text" id="article_title" name="article[title]" maxlength="30" size="30" value="#{@article.title}" class="title_input" />
|
|
1167
1169
|
#
|
|
1168
1170
|
# text_field(:session, :user, onchange: "if ($('#session_user').val() === 'admin') { alert('Your login cannot be admin!'); }")
|
|
1169
1171
|
# # => <input type="text" id="session_user" name="session[user]" value="#{@session.user}" onchange="if ($('#session_user').val() === 'admin') { alert('Your login cannot be admin!'); }"/>
|
|
@@ -1204,8 +1206,8 @@ module ActionView
|
|
|
1204
1206
|
# hidden_field(:signup, :pass_confirm)
|
|
1205
1207
|
# # => <input type="hidden" id="signup_pass_confirm" name="signup[pass_confirm]" value="#{@signup.pass_confirm}" />
|
|
1206
1208
|
#
|
|
1207
|
-
# hidden_field(:
|
|
1208
|
-
# # => <input type="hidden" id="
|
|
1209
|
+
# hidden_field(:article, :tag_list)
|
|
1210
|
+
# # => <input type="hidden" id="article_tag_list" name="article[tag_list]" value="#{@article.tag_list}" />
|
|
1209
1211
|
#
|
|
1210
1212
|
# hidden_field(:user, :token)
|
|
1211
1213
|
# # => <input type="hidden" id="user_token" name="user[token]" value="#{@user.token}" />
|
|
@@ -1218,7 +1220,7 @@ module ActionView
|
|
|
1218
1220
|
# hash with +options+. These options will be tagged onto the HTML as an HTML element attribute as in the example
|
|
1219
1221
|
# shown.
|
|
1220
1222
|
#
|
|
1221
|
-
# Using this method inside a
|
|
1223
|
+
# Using this method inside a #form_with block will set the enclosing form's encoding to <tt>multipart/form-data</tt>.
|
|
1222
1224
|
#
|
|
1223
1225
|
# ==== Options
|
|
1224
1226
|
# * Creates standard HTML attributes for the tag.
|
|
@@ -1231,14 +1233,14 @@ module ActionView
|
|
|
1231
1233
|
# file_field(:user, :avatar)
|
|
1232
1234
|
# # => <input type="file" id="user_avatar" name="user[avatar]" />
|
|
1233
1235
|
#
|
|
1234
|
-
# file_field(:
|
|
1235
|
-
# # => <input type="file" id="
|
|
1236
|
+
# file_field(:article, :image, multiple: true)
|
|
1237
|
+
# # => <input type="file" id="article_image" name="article[image][]" multiple="multiple" />
|
|
1236
1238
|
#
|
|
1237
|
-
# file_field(:
|
|
1238
|
-
# # => <input accept="text/html" type="file" id="
|
|
1239
|
+
# file_field(:article, :attached, accept: 'text/html')
|
|
1240
|
+
# # => <input accept="text/html" type="file" id="article_attached" name="article[attached]" />
|
|
1239
1241
|
#
|
|
1240
|
-
# file_field(:
|
|
1241
|
-
# # => <input type="file" id="
|
|
1242
|
+
# file_field(:article, :image, accept: 'image/png,image/gif,image/jpeg')
|
|
1243
|
+
# # => <input type="file" id="article_image" name="article[image]" accept="image/png,image/gif,image/jpeg" />
|
|
1242
1244
|
#
|
|
1243
1245
|
# file_field(:attachment, :file, class: 'file_input')
|
|
1244
1246
|
# # => <input type="file" id="attachment_file" name="attachment[file]" class="file_input" />
|
|
@@ -1253,28 +1255,29 @@ module ActionView
|
|
|
1253
1255
|
# hash with +options+.
|
|
1254
1256
|
#
|
|
1255
1257
|
# ==== Examples
|
|
1256
|
-
#
|
|
1257
|
-
# # => <textarea cols="20" rows="40" id="
|
|
1258
|
-
# # #{@
|
|
1258
|
+
# textarea(:article, :body, cols: 20, rows: 40)
|
|
1259
|
+
# # => <textarea cols="20" rows="40" id="article_body" name="article[body]">
|
|
1260
|
+
# # #{@article.body}
|
|
1259
1261
|
# # </textarea>
|
|
1260
1262
|
#
|
|
1261
|
-
#
|
|
1263
|
+
# textarea(:comment, :text, size: "20x30")
|
|
1262
1264
|
# # => <textarea cols="20" rows="30" id="comment_text" name="comment[text]">
|
|
1263
1265
|
# # #{@comment.text}
|
|
1264
1266
|
# # </textarea>
|
|
1265
1267
|
#
|
|
1266
|
-
#
|
|
1268
|
+
# textarea(:application, :notes, cols: 40, rows: 15, class: 'app_input')
|
|
1267
1269
|
# # => <textarea cols="40" rows="15" id="application_notes" name="application[notes]" class="app_input">
|
|
1268
1270
|
# # #{@application.notes}
|
|
1269
1271
|
# # </textarea>
|
|
1270
1272
|
#
|
|
1271
|
-
#
|
|
1273
|
+
# textarea(:entry, :body, size: "20x20", disabled: 'disabled')
|
|
1272
1274
|
# # => <textarea cols="20" rows="20" id="entry_body" name="entry[body]" disabled="disabled">
|
|
1273
1275
|
# # #{@entry.body}
|
|
1274
1276
|
# # </textarea>
|
|
1275
|
-
def
|
|
1277
|
+
def textarea(object_name, method, options = {})
|
|
1276
1278
|
Tags::TextArea.new(object_name, method, self, options).render
|
|
1277
1279
|
end
|
|
1280
|
+
alias_method :text_area, :textarea
|
|
1278
1281
|
|
|
1279
1282
|
# Returns a checkbox tag tailored for accessing a specified attribute (identified by +method+) on an object
|
|
1280
1283
|
# assigned to the template (identified by +object+). This object must be an instance object (@object) and not a local object.
|
|
@@ -1314,7 +1317,7 @@ module ActionView
|
|
|
1314
1317
|
# within an array-like parameter, as in
|
|
1315
1318
|
#
|
|
1316
1319
|
# <%= fields_for "project[invoice_attributes][]", invoice, index: nil do |form| %>
|
|
1317
|
-
# <%= form.
|
|
1320
|
+
# <%= form.checkbox :paid %>
|
|
1318
1321
|
# ...
|
|
1319
1322
|
# <% end %>
|
|
1320
1323
|
#
|
|
@@ -1322,27 +1325,28 @@ module ActionView
|
|
|
1322
1325
|
# the elements of the array. For each item with a checked check box you
|
|
1323
1326
|
# get an extra ghost item with only that attribute, assigned to "0".
|
|
1324
1327
|
#
|
|
1325
|
-
# In that case it is preferable to either use
|
|
1328
|
+
# In that case it is preferable to either use FormTagHelper#checkbox_tag or to use
|
|
1326
1329
|
# hashes instead of arrays.
|
|
1327
1330
|
#
|
|
1328
1331
|
# ==== Examples
|
|
1329
1332
|
#
|
|
1330
|
-
# # Let's say that @
|
|
1331
|
-
#
|
|
1332
|
-
# # => <input name="
|
|
1333
|
-
# # <input checked="checked" type="checkbox" id="
|
|
1333
|
+
# # Let's say that @article.validated? is 1:
|
|
1334
|
+
# checkbox("article", "validated")
|
|
1335
|
+
# # => <input name="article[validated]" type="hidden" value="0" />
|
|
1336
|
+
# # <input checked="checked" type="checkbox" id="article_validated" name="article[validated]" value="1" />
|
|
1334
1337
|
#
|
|
1335
1338
|
# # Let's say that @puppy.gooddog is "no":
|
|
1336
|
-
#
|
|
1339
|
+
# checkbox("puppy", "gooddog", {}, "yes", "no")
|
|
1337
1340
|
# # => <input name="puppy[gooddog]" type="hidden" value="no" />
|
|
1338
1341
|
# # <input type="checkbox" id="puppy_gooddog" name="puppy[gooddog]" value="yes" />
|
|
1339
1342
|
#
|
|
1340
|
-
#
|
|
1343
|
+
# checkbox("eula", "accepted", { class: 'eula_check' }, "yes", "no")
|
|
1341
1344
|
# # => <input name="eula[accepted]" type="hidden" value="no" />
|
|
1342
1345
|
# # <input type="checkbox" class="eula_check" id="eula_accepted" name="eula[accepted]" value="yes" />
|
|
1343
|
-
def
|
|
1346
|
+
def checkbox(object_name, method, options = {}, checked_value = "1", unchecked_value = "0")
|
|
1344
1347
|
Tags::CheckBox.new(object_name, method, self, checked_value, unchecked_value, options).render
|
|
1345
1348
|
end
|
|
1349
|
+
alias_method :check_box, :checkbox
|
|
1346
1350
|
|
|
1347
1351
|
# Returns a radio button tag for accessing a specified attribute (identified by +method+) on an object
|
|
1348
1352
|
# assigned to the template (identified by +object+). If the current value of +method+ is +tag_value+ the
|
|
@@ -1351,11 +1355,11 @@ module ActionView
|
|
|
1351
1355
|
# To force the radio button to be checked pass <tt>checked: true</tt> in the
|
|
1352
1356
|
# +options+ hash. You may pass HTML options there as well.
|
|
1353
1357
|
#
|
|
1354
|
-
# # Let's say that @
|
|
1355
|
-
# radio_button("
|
|
1356
|
-
# radio_button("
|
|
1357
|
-
# # => <input type="radio" id="
|
|
1358
|
-
# # <input type="radio" id="
|
|
1358
|
+
# # Let's say that @article.category returns "rails":
|
|
1359
|
+
# radio_button("article", "category", "rails")
|
|
1360
|
+
# radio_button("article", "category", "java")
|
|
1361
|
+
# # => <input type="radio" id="article_category_rails" name="article[category]" value="rails" checked="checked" />
|
|
1362
|
+
# # <input type="radio" id="article_category_java" name="article[category]" value="java" />
|
|
1359
1363
|
#
|
|
1360
1364
|
# # Let's say that @user.receive_newsletter returns "no":
|
|
1361
1365
|
# radio_button("user", "receive_newsletter", "yes")
|
|
@@ -1627,17 +1631,18 @@ module ActionView
|
|
|
1627
1631
|
#
|
|
1628
1632
|
# A +FormBuilder+ object is associated with a particular model object and
|
|
1629
1633
|
# allows you to generate fields associated with the model object. The
|
|
1630
|
-
# +FormBuilder+ object is yielded when using
|
|
1634
|
+
# +FormBuilder+ object is yielded when using
|
|
1635
|
+
# {form_with}[rdof-ref:ActionView::Helpers::FormHelper#form_with] or #fields_for.
|
|
1631
1636
|
# For example:
|
|
1632
1637
|
#
|
|
1633
|
-
# <%=
|
|
1638
|
+
# <%= form_with model: @person do |person_form| %>
|
|
1634
1639
|
# Name: <%= person_form.text_field :name %>
|
|
1635
|
-
# Admin: <%= person_form.
|
|
1640
|
+
# Admin: <%= person_form.checkbox :admin %>
|
|
1636
1641
|
# <% end %>
|
|
1637
1642
|
#
|
|
1638
1643
|
# In the above block, a +FormBuilder+ object is yielded as the
|
|
1639
1644
|
# +person_form+ variable. This allows you to generate the +text_field+
|
|
1640
|
-
# and +
|
|
1645
|
+
# and +checkbox+ fields by specifying their eponymous methods, which
|
|
1641
1646
|
# modify the underlying template and associates the <tt>@person</tt> model object
|
|
1642
1647
|
# with the form.
|
|
1643
1648
|
#
|
|
@@ -1666,7 +1671,7 @@ module ActionView
|
|
|
1666
1671
|
#
|
|
1667
1672
|
# The +div_radio_button+ code from above can now be used as follows:
|
|
1668
1673
|
#
|
|
1669
|
-
# <%=
|
|
1674
|
+
# <%= form_with model: @person, :builder => MyFormBuilder do |f| %>
|
|
1670
1675
|
# I am a child: <%= f.div_radio_button(:admin, "child") %>
|
|
1671
1676
|
# I am an adult: <%= f.div_radio_button(:admin, "adult") %>
|
|
1672
1677
|
# <% end -%>
|
|
@@ -1679,7 +1684,7 @@ module ActionView
|
|
|
1679
1684
|
# The methods which wrap a form helper call.
|
|
1680
1685
|
class_attribute :field_helpers, default: [
|
|
1681
1686
|
:fields_for, :fields, :label, :text_field, :password_field,
|
|
1682
|
-
:hidden_field, :file_field, :
|
|
1687
|
+
:hidden_field, :file_field, :textarea, :checkbox,
|
|
1683
1688
|
:radio_button, :color_field, :search_field,
|
|
1684
1689
|
:telephone_field, :phone_field, :date_field,
|
|
1685
1690
|
:time_field, :datetime_field, :datetime_local_field,
|
|
@@ -1736,7 +1741,7 @@ module ActionView
|
|
|
1736
1741
|
#
|
|
1737
1742
|
# return the <tt><form></tt> element's <tt>id</tt> attribute.
|
|
1738
1743
|
#
|
|
1739
|
-
# <%=
|
|
1744
|
+
# <%= form_with model: @article do |f| %>
|
|
1740
1745
|
# <%# ... %>
|
|
1741
1746
|
#
|
|
1742
1747
|
# <% content_for :sticky_footer do %>
|
|
@@ -1758,16 +1763,16 @@ module ActionView
|
|
|
1758
1763
|
# Return the value generated by the <tt>FormBuilder</tt> for the given
|
|
1759
1764
|
# attribute name.
|
|
1760
1765
|
#
|
|
1761
|
-
# <%=
|
|
1766
|
+
# <%= form_with model: @article do |f| %>
|
|
1762
1767
|
# <%= f.label :title %>
|
|
1763
1768
|
# <%= f.text_field :title, aria: { describedby: f.field_id(:title, :error) } %>
|
|
1764
1769
|
# <%= tag.span("is blank", id: f.field_id(:title, :error) %>
|
|
1765
1770
|
# <% end %>
|
|
1766
1771
|
#
|
|
1767
1772
|
# In the example above, the <tt><input type="text"></tt> element built by
|
|
1768
|
-
# the call to
|
|
1773
|
+
# the call to #text_field declares an
|
|
1769
1774
|
# <tt>aria-describedby</tt> attribute referencing the <tt><span></tt>
|
|
1770
|
-
# element, sharing a common <tt>id</tt> root (<tt>
|
|
1775
|
+
# element, sharing a common <tt>id</tt> root (<tt>article_title</tt>, in this
|
|
1771
1776
|
# case).
|
|
1772
1777
|
def field_id(method, *suffixes, namespace: @options[:namespace], index: @options[:index])
|
|
1773
1778
|
@template.field_id(@object_name, method, *suffixes, namespace: namespace, index: index)
|
|
@@ -1779,14 +1784,14 @@ module ActionView
|
|
|
1779
1784
|
# Return the value generated by the <tt>FormBuilder</tt> for the given
|
|
1780
1785
|
# attribute name.
|
|
1781
1786
|
#
|
|
1782
|
-
# <%=
|
|
1787
|
+
# <%= form_with model: @article do |f| %>
|
|
1783
1788
|
# <%= f.text_field :title, name: f.field_name(:title, :subtitle) %>
|
|
1784
|
-
# <%# => <input type="text" name="
|
|
1789
|
+
# <%# => <input type="text" name="article[title][subtitle]"> %>
|
|
1785
1790
|
# <% end %>
|
|
1786
1791
|
#
|
|
1787
|
-
# <%=
|
|
1792
|
+
# <%= form_with model: @article do |f| %>
|
|
1788
1793
|
# <%= f.text_field :tag, name: f.field_name(:tag, multiple: true) %>
|
|
1789
|
-
# <%# => <input type="text" name="
|
|
1794
|
+
# <%# => <input type="text" name="article[tag][]"> %>
|
|
1790
1795
|
# <% end %>
|
|
1791
1796
|
#
|
|
1792
1797
|
def field_name(method, *methods, multiple: false, index: @options[:index])
|
|
@@ -1822,14 +1827,14 @@ module ActionView
|
|
|
1822
1827
|
# Please refer to the documentation of the base helper for details.
|
|
1823
1828
|
|
|
1824
1829
|
##
|
|
1825
|
-
# :method:
|
|
1830
|
+
# :method: textarea
|
|
1826
1831
|
#
|
|
1827
|
-
# :call-seq:
|
|
1832
|
+
# :call-seq: textarea(method, options = {})
|
|
1828
1833
|
#
|
|
1829
|
-
# Wraps ActionView::Helpers::FormHelper#
|
|
1834
|
+
# Wraps ActionView::Helpers::FormHelper#textarea for form builders:
|
|
1830
1835
|
#
|
|
1831
1836
|
# <%= form_with model: @user do |f| %>
|
|
1832
|
-
# <%= f.
|
|
1837
|
+
# <%= f.textarea :detail %>
|
|
1833
1838
|
# <% end %>
|
|
1834
1839
|
#
|
|
1835
1840
|
# Please refer to the documentation of the base helper for details.
|
|
@@ -2016,40 +2021,40 @@ module ActionView
|
|
|
2016
2021
|
#
|
|
2017
2022
|
# Please refer to the documentation of the base helper for details.
|
|
2018
2023
|
|
|
2019
|
-
(
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
end
|
|
2028
|
-
RUBY_EVAL
|
|
2024
|
+
ActiveSupport::CodeGenerator.batch(self, __FILE__, __LINE__) do |code_generator|
|
|
2025
|
+
(field_helpers - [:label, :checkbox, :radio_button, :fields_for, :fields, :hidden_field, :file_field]).each do |selector|
|
|
2026
|
+
code_generator.class_eval do |batch|
|
|
2027
|
+
batch <<
|
|
2028
|
+
"def #{selector}(method, options = {})" <<
|
|
2029
|
+
" @template.#{selector}(@object_name, method, objectify_options(options))" <<
|
|
2030
|
+
"end"
|
|
2031
|
+
end
|
|
2032
|
+
end
|
|
2029
2033
|
end
|
|
2034
|
+
alias_method :text_area, :textarea
|
|
2030
2035
|
|
|
2031
|
-
# Creates a scope around a specific model object like
|
|
2032
|
-
# doesn't create the form tags themselves. This makes fields_for
|
|
2033
|
-
# for specifying additional model objects in the same form.
|
|
2036
|
+
# Creates a scope around a specific model object like #form_with, but
|
|
2037
|
+
# doesn't create the form tags themselves. This makes +fields_for+
|
|
2038
|
+
# suitable for specifying additional model objects in the same form.
|
|
2034
2039
|
#
|
|
2035
|
-
# Although the usage and purpose of +fields_for+ is similar to
|
|
2036
|
-
# its method signature is slightly different. Like
|
|
2040
|
+
# Although the usage and purpose of +fields_for+ is similar to #form_with's,
|
|
2041
|
+
# its method signature is slightly different. Like #form_with, it yields
|
|
2037
2042
|
# a FormBuilder object associated with a particular model object to a block,
|
|
2038
2043
|
# and within the block allows methods to be called on the builder to
|
|
2039
2044
|
# generate fields associated with the model object. Fields may reflect
|
|
2040
2045
|
# a model object in two ways - how they are named (hence how submitted
|
|
2041
2046
|
# values appear within the +params+ hash in the controller) and what
|
|
2042
|
-
# default values are shown when the form
|
|
2043
|
-
#
|
|
2047
|
+
# default values are shown when the form fields are first displayed.
|
|
2048
|
+
# In order for both of these features to be specified independently,
|
|
2044
2049
|
# both an object name (represented by either a symbol or string) and the
|
|
2045
2050
|
# object itself can be passed to the method separately -
|
|
2046
2051
|
#
|
|
2047
|
-
# <%=
|
|
2052
|
+
# <%= form_with model: @person do |person_form| %>
|
|
2048
2053
|
# First name: <%= person_form.text_field :first_name %>
|
|
2049
2054
|
# Last name : <%= person_form.text_field :last_name %>
|
|
2050
2055
|
#
|
|
2051
2056
|
# <%= fields_for :permission, @person.permission do |permission_fields| %>
|
|
2052
|
-
# Admin? : <%= permission_fields.
|
|
2057
|
+
# Admin? : <%= permission_fields.checkbox :admin %>
|
|
2053
2058
|
# <% end %>
|
|
2054
2059
|
#
|
|
2055
2060
|
# <%= person_form.submit %>
|
|
@@ -2066,7 +2071,7 @@ module ActionView
|
|
|
2066
2071
|
# object to +fields_for+ -
|
|
2067
2072
|
#
|
|
2068
2073
|
# <%= fields_for :permission do |permission_fields| %>
|
|
2069
|
-
# Admin?: <%= permission_fields.
|
|
2074
|
+
# Admin?: <%= permission_fields.checkbox :admin %>
|
|
2070
2075
|
# <% end %>
|
|
2071
2076
|
#
|
|
2072
2077
|
# ...in which case, if <tt>:permission</tt> also happens to be the name of an
|
|
@@ -2078,7 +2083,7 @@ module ActionView
|
|
|
2078
2083
|
# name has been omitted) -
|
|
2079
2084
|
#
|
|
2080
2085
|
# <%= fields_for @person.permission do |permission_fields| %>
|
|
2081
|
-
# Admin?: <%= permission_fields.
|
|
2086
|
+
# Admin?: <%= permission_fields.checkbox :admin %>
|
|
2082
2087
|
# <% end %>
|
|
2083
2088
|
#
|
|
2084
2089
|
# and +fields_for+ will derive the required name of the field from the
|
|
@@ -2093,10 +2098,10 @@ module ActionView
|
|
|
2093
2098
|
# name and value parameters are provided and the provided value has the shape of an
|
|
2094
2099
|
# option Hash. To remove the ambiguity, explicitly pass an option Hash, even if empty.
|
|
2095
2100
|
#
|
|
2096
|
-
# <%=
|
|
2101
|
+
# <%= form_with model: @person do |person_form| %>
|
|
2097
2102
|
# ...
|
|
2098
2103
|
# <%= fields_for :permission, @person.permission, {} do |permission_fields| %>
|
|
2099
|
-
# Admin?: <%=
|
|
2104
|
+
# Admin?: <%= checkbox_tag permission_fields.field_name(:admin), @person.permission[:admin] %>
|
|
2100
2105
|
# <% end %>
|
|
2101
2106
|
# ...
|
|
2102
2107
|
# <% end %>
|
|
@@ -2104,7 +2109,7 @@ module ActionView
|
|
|
2104
2109
|
# === Nested Attributes Examples
|
|
2105
2110
|
#
|
|
2106
2111
|
# When the object belonging to the current scope has a nested attribute
|
|
2107
|
-
# writer for a certain attribute, fields_for will yield a new scope
|
|
2112
|
+
# writer for a certain attribute, +fields_for+ will yield a new scope
|
|
2108
2113
|
# for that attribute. This allows you to create forms that set or change
|
|
2109
2114
|
# the attributes of a parent object and its associations in one go.
|
|
2110
2115
|
#
|
|
@@ -2135,9 +2140,9 @@ module ActionView
|
|
|
2135
2140
|
# end
|
|
2136
2141
|
# end
|
|
2137
2142
|
#
|
|
2138
|
-
# This model can now be used with a nested fields_for
|
|
2143
|
+
# This model can now be used with a nested +fields_for+, like so:
|
|
2139
2144
|
#
|
|
2140
|
-
# <%=
|
|
2145
|
+
# <%= form_with model: @person do |person_form| %>
|
|
2141
2146
|
# ...
|
|
2142
2147
|
# <%= person_form.fields_for :address do |address_fields| %>
|
|
2143
2148
|
# Street : <%= address_fields.text_field :street %>
|
|
@@ -2167,11 +2172,11 @@ module ActionView
|
|
|
2167
2172
|
# with a value that evaluates to +true+, you will destroy the associated
|
|
2168
2173
|
# model (e.g. 1, '1', true, or 'true'):
|
|
2169
2174
|
#
|
|
2170
|
-
# <%=
|
|
2175
|
+
# <%= form_with model: @person do |person_form| %>
|
|
2171
2176
|
# ...
|
|
2172
2177
|
# <%= person_form.fields_for :address do |address_fields| %>
|
|
2173
2178
|
# ...
|
|
2174
|
-
# Delete: <%= address_fields.
|
|
2179
|
+
# Delete: <%= address_fields.checkbox :_destroy %>
|
|
2175
2180
|
# <% end %>
|
|
2176
2181
|
# ...
|
|
2177
2182
|
# <% end %>
|
|
@@ -2193,7 +2198,7 @@ module ActionView
|
|
|
2193
2198
|
# end
|
|
2194
2199
|
#
|
|
2195
2200
|
# Note that the <tt>projects_attributes=</tt> writer method is in fact
|
|
2196
|
-
# required for fields_for to correctly identify <tt>:projects</tt> as a
|
|
2201
|
+
# required for +fields_for+ to correctly identify <tt>:projects</tt> as a
|
|
2197
2202
|
# collection, and the correct indices to be set in the form markup.
|
|
2198
2203
|
#
|
|
2199
2204
|
# When projects is already an association on Person you can use
|
|
@@ -2204,11 +2209,11 @@ module ActionView
|
|
|
2204
2209
|
# accepts_nested_attributes_for :projects
|
|
2205
2210
|
# end
|
|
2206
2211
|
#
|
|
2207
|
-
# This model can now be used with a nested fields_for
|
|
2208
|
-
# the nested fields_for call will be repeated for each instance in the
|
|
2212
|
+
# This model can now be used with a nested +fields_for+. The block given to
|
|
2213
|
+
# the nested +fields_for+ call will be repeated for each instance in the
|
|
2209
2214
|
# collection:
|
|
2210
2215
|
#
|
|
2211
|
-
# <%=
|
|
2216
|
+
# <%= form_with model: @person do |person_form| %>
|
|
2212
2217
|
# ...
|
|
2213
2218
|
# <%= person_form.fields_for :projects do |project_fields| %>
|
|
2214
2219
|
# <% if project_fields.object.active? %>
|
|
@@ -2220,7 +2225,7 @@ module ActionView
|
|
|
2220
2225
|
#
|
|
2221
2226
|
# It's also possible to specify the instance to be used:
|
|
2222
2227
|
#
|
|
2223
|
-
# <%=
|
|
2228
|
+
# <%= form_with model: @person do |person_form| %>
|
|
2224
2229
|
# ...
|
|
2225
2230
|
# <% @person.projects.each do |project| %>
|
|
2226
2231
|
# <% if project.active? %>
|
|
@@ -2234,7 +2239,7 @@ module ActionView
|
|
|
2234
2239
|
#
|
|
2235
2240
|
# Or a collection to be used:
|
|
2236
2241
|
#
|
|
2237
|
-
# <%=
|
|
2242
|
+
# <%= form_with model: @person do |person_form| %>
|
|
2238
2243
|
# ...
|
|
2239
2244
|
# <%= person_form.fields_for :projects, @active_projects do |project_fields| %>
|
|
2240
2245
|
# Name: <%= project_fields.text_field :name %>
|
|
@@ -2256,10 +2261,10 @@ module ActionView
|
|
|
2256
2261
|
# parameter with a value that evaluates to +true+
|
|
2257
2262
|
# (e.g. 1, '1', true, or 'true'):
|
|
2258
2263
|
#
|
|
2259
|
-
# <%=
|
|
2264
|
+
# <%= form_with model: @person do |person_form| %>
|
|
2260
2265
|
# ...
|
|
2261
2266
|
# <%= person_form.fields_for :projects do |project_fields| %>
|
|
2262
|
-
# Delete: <%= project_fields.
|
|
2267
|
+
# Delete: <%= project_fields.checkbox :_destroy %>
|
|
2263
2268
|
# <% end %>
|
|
2264
2269
|
# ...
|
|
2265
2270
|
# <% end %>
|
|
@@ -2268,7 +2273,7 @@ module ActionView
|
|
|
2268
2273
|
# object in the array. For this purpose, the <tt>index</tt> method
|
|
2269
2274
|
# is available in the FormBuilder object.
|
|
2270
2275
|
#
|
|
2271
|
-
# <%=
|
|
2276
|
+
# <%= form_with model: @person do |person_form| %>
|
|
2272
2277
|
# ...
|
|
2273
2278
|
# <%= person_form.fields_for :projects do |project_fields| %>
|
|
2274
2279
|
# Project #<%= project_fields.index %>
|
|
@@ -2277,10 +2282,10 @@ module ActionView
|
|
|
2277
2282
|
# ...
|
|
2278
2283
|
# <% end %>
|
|
2279
2284
|
#
|
|
2280
|
-
# Note that fields_for will automatically generate a hidden field
|
|
2285
|
+
# Note that +fields_for+ will automatically generate a hidden field
|
|
2281
2286
|
# to store the ID of the record. There are circumstances where this
|
|
2282
2287
|
# hidden field is not needed and you can pass <tt>include_id: false</tt>
|
|
2283
|
-
# to prevent fields_for from rendering it automatically.
|
|
2288
|
+
# to prevent +fields_for+ from rendering it automatically.
|
|
2284
2289
|
def fields_for(record_name, record_object = nil, fields_options = nil, &block)
|
|
2285
2290
|
fields_options, record_object = record_object, nil if fields_options.nil? && record_object.is_a?(Hash) && record_object.extractable_options?
|
|
2286
2291
|
fields_options ||= {}
|
|
@@ -2337,52 +2342,52 @@ module ActionView
|
|
|
2337
2342
|
#
|
|
2338
2343
|
# ==== Examples
|
|
2339
2344
|
# label(:title)
|
|
2340
|
-
# # => <label for="
|
|
2345
|
+
# # => <label for="article_title">Title</label>
|
|
2341
2346
|
#
|
|
2342
2347
|
# You can localize your labels based on model and attribute names.
|
|
2343
2348
|
# For example you can define the following in your locale (e.g. en.yml)
|
|
2344
2349
|
#
|
|
2345
2350
|
# helpers:
|
|
2346
2351
|
# label:
|
|
2347
|
-
#
|
|
2352
|
+
# article:
|
|
2348
2353
|
# body: "Write your entire text here"
|
|
2349
2354
|
#
|
|
2350
2355
|
# Which then will result in
|
|
2351
2356
|
#
|
|
2352
2357
|
# label(:body)
|
|
2353
|
-
# # => <label for="
|
|
2358
|
+
# # => <label for="article_body">Write your entire text here</label>
|
|
2354
2359
|
#
|
|
2355
2360
|
# Localization can also be based purely on the translation of the attribute-name
|
|
2356
2361
|
# (if you are using ActiveRecord):
|
|
2357
2362
|
#
|
|
2358
2363
|
# activerecord:
|
|
2359
2364
|
# attributes:
|
|
2360
|
-
#
|
|
2365
|
+
# article:
|
|
2361
2366
|
# cost: "Total cost"
|
|
2362
2367
|
#
|
|
2363
2368
|
# <code></code>
|
|
2364
2369
|
#
|
|
2365
2370
|
# label(:cost)
|
|
2366
|
-
# # => <label for="
|
|
2371
|
+
# # => <label for="article_cost">Total cost</label>
|
|
2367
2372
|
#
|
|
2368
2373
|
# label(:title, "A short title")
|
|
2369
|
-
# # => <label for="
|
|
2374
|
+
# # => <label for="article_title">A short title</label>
|
|
2370
2375
|
#
|
|
2371
2376
|
# label(:title, "A short title", class: "title_label")
|
|
2372
|
-
# # => <label for="
|
|
2377
|
+
# # => <label for="article_title" class="title_label">A short title</label>
|
|
2373
2378
|
#
|
|
2374
|
-
# label(:privacy, "Public
|
|
2375
|
-
# # => <label for="
|
|
2379
|
+
# label(:privacy, "Public Article", value: "public")
|
|
2380
|
+
# # => <label for="article_privacy_public">Public Article</label>
|
|
2376
2381
|
#
|
|
2377
2382
|
# label(:cost) do |translation|
|
|
2378
2383
|
# content_tag(:span, translation, class: "cost_label")
|
|
2379
2384
|
# end
|
|
2380
|
-
# # => <label for="
|
|
2385
|
+
# # => <label for="article_cost"><span class="cost_label">Total cost</span></label>
|
|
2381
2386
|
#
|
|
2382
2387
|
# label(:cost) do |builder|
|
|
2383
2388
|
# content_tag(:span, builder.translation, class: "cost_label")
|
|
2384
2389
|
# end
|
|
2385
|
-
# # => <label for="
|
|
2390
|
+
# # => <label for="article_cost"><span class="cost_label">Total cost</span></label>
|
|
2386
2391
|
#
|
|
2387
2392
|
# label(:cost) do |builder|
|
|
2388
2393
|
# content_tag(:span, builder.translation, class: [
|
|
@@ -2390,12 +2395,12 @@ module ActionView
|
|
|
2390
2395
|
# ("error_label" if builder.object.errors.include?(:cost))
|
|
2391
2396
|
# ])
|
|
2392
2397
|
# end
|
|
2393
|
-
# # => <label for="
|
|
2398
|
+
# # => <label for="article_cost"><span class="cost_label error_label">Total cost</span></label>
|
|
2394
2399
|
#
|
|
2395
2400
|
# label(:terms) do
|
|
2396
2401
|
# raw('Accept <a href="/terms">Terms</a>.')
|
|
2397
2402
|
# end
|
|
2398
|
-
# # => <label for="
|
|
2403
|
+
# # => <label for="article_terms">Accept <a href="/terms">Terms</a>.</label>
|
|
2399
2404
|
def label(method, text = nil, options = {}, &block)
|
|
2400
2405
|
@template.label(@object_name, method, text, objectify_options(options), &block)
|
|
2401
2406
|
end
|
|
@@ -2438,7 +2443,7 @@ module ActionView
|
|
|
2438
2443
|
# within an array-like parameter, as in
|
|
2439
2444
|
#
|
|
2440
2445
|
# <%= fields_for "project[invoice_attributes][]", invoice, index: nil do |form| %>
|
|
2441
|
-
# <%= form.
|
|
2446
|
+
# <%= form.checkbox :paid %>
|
|
2442
2447
|
# ...
|
|
2443
2448
|
# <% end %>
|
|
2444
2449
|
#
|
|
@@ -2446,28 +2451,29 @@ module ActionView
|
|
|
2446
2451
|
# the elements of the array. For each item with a checked check box you
|
|
2447
2452
|
# get an extra ghost item with only that attribute, assigned to "0".
|
|
2448
2453
|
#
|
|
2449
|
-
# In that case it is preferable to either use
|
|
2454
|
+
# In that case it is preferable to either use FormTagHelper#checkbox_tag or to use
|
|
2450
2455
|
# hashes instead of arrays.
|
|
2451
2456
|
#
|
|
2452
2457
|
# ==== Examples
|
|
2453
2458
|
#
|
|
2454
|
-
# # Let's say that @
|
|
2455
|
-
#
|
|
2456
|
-
# # => <input name="
|
|
2457
|
-
# # <input checked="checked" type="checkbox" id="
|
|
2459
|
+
# # Let's say that @article.validated? is 1:
|
|
2460
|
+
# checkbox("validated")
|
|
2461
|
+
# # => <input name="article[validated]" type="hidden" value="0" />
|
|
2462
|
+
# # <input checked="checked" type="checkbox" id="article_validated" name="article[validated]" value="1" />
|
|
2458
2463
|
#
|
|
2459
2464
|
# # Let's say that @puppy.gooddog is "no":
|
|
2460
|
-
#
|
|
2465
|
+
# checkbox("gooddog", {}, "yes", "no")
|
|
2461
2466
|
# # => <input name="puppy[gooddog]" type="hidden" value="no" />
|
|
2462
2467
|
# # <input type="checkbox" id="puppy_gooddog" name="puppy[gooddog]" value="yes" />
|
|
2463
2468
|
#
|
|
2464
2469
|
# # Let's say that @eula.accepted is "no":
|
|
2465
|
-
#
|
|
2470
|
+
# checkbox("accepted", { class: 'eula_check' }, "yes", "no")
|
|
2466
2471
|
# # => <input name="eula[accepted]" type="hidden" value="no" />
|
|
2467
2472
|
# # <input type="checkbox" class="eula_check" id="eula_accepted" name="eula[accepted]" value="yes" />
|
|
2468
|
-
def
|
|
2469
|
-
@template.
|
|
2473
|
+
def checkbox(method, options = {}, checked_value = "1", unchecked_value = "0")
|
|
2474
|
+
@template.checkbox(@object_name, method, objectify_options(options), checked_value, unchecked_value)
|
|
2470
2475
|
end
|
|
2476
|
+
alias_method :check_box, :checkbox
|
|
2471
2477
|
|
|
2472
2478
|
# Returns a radio button tag for accessing a specified attribute (identified by +method+) on an object
|
|
2473
2479
|
# assigned to the template (identified by +object+). If the current value of +method+ is +tag_value+ the
|
|
@@ -2476,11 +2482,11 @@ module ActionView
|
|
|
2476
2482
|
# To force the radio button to be checked pass <tt>checked: true</tt> in the
|
|
2477
2483
|
# +options+ hash. You may pass HTML options there as well.
|
|
2478
2484
|
#
|
|
2479
|
-
# # Let's say that @
|
|
2485
|
+
# # Let's say that @article.category returns "rails":
|
|
2480
2486
|
# radio_button("category", "rails")
|
|
2481
2487
|
# radio_button("category", "java")
|
|
2482
|
-
# # => <input type="radio" id="
|
|
2483
|
-
# # <input type="radio" id="
|
|
2488
|
+
# # => <input type="radio" id="article_category_rails" name="article[category]" value="rails" checked="checked" />
|
|
2489
|
+
# # <input type="radio" id="article_category_java" name="article[category]" value="java" />
|
|
2484
2490
|
#
|
|
2485
2491
|
# # Let's say that @user.receive_newsletter returns "no":
|
|
2486
2492
|
# radio_button("receive_newsletter", "yes")
|
|
@@ -2501,9 +2507,9 @@ module ActionView
|
|
|
2501
2507
|
# hidden_field(:pass_confirm)
|
|
2502
2508
|
# # => <input type="hidden" id="signup_pass_confirm" name="signup[pass_confirm]" value="true" />
|
|
2503
2509
|
#
|
|
2504
|
-
# # Let's say that @
|
|
2510
|
+
# # Let's say that @article.tag_list returns "blog, ruby":
|
|
2505
2511
|
# hidden_field(:tag_list)
|
|
2506
|
-
# # => <input type="hidden" id="
|
|
2512
|
+
# # => <input type="hidden" id="article_tag_list" name="article[tag_list]" value="blog, ruby" />
|
|
2507
2513
|
#
|
|
2508
2514
|
# # Let's say that @user.token returns "abcde":
|
|
2509
2515
|
# hidden_field(:token)
|
|
@@ -2519,7 +2525,7 @@ module ActionView
|
|
|
2519
2525
|
# hash with +options+. These options will be tagged onto the HTML as an HTML element attribute as in the example
|
|
2520
2526
|
# shown.
|
|
2521
2527
|
#
|
|
2522
|
-
# Using this method inside a
|
|
2528
|
+
# Using this method inside a #form_with block will set the enclosing form's encoding to <tt>multipart/form-data</tt>.
|
|
2523
2529
|
#
|
|
2524
2530
|
# ==== Options
|
|
2525
2531
|
# * Creates standard HTML attributes for the tag.
|
|
@@ -2533,17 +2539,17 @@ module ActionView
|
|
|
2533
2539
|
# file_field(:avatar)
|
|
2534
2540
|
# # => <input type="file" id="user_avatar" name="user[avatar]" />
|
|
2535
2541
|
#
|
|
2536
|
-
# # Let's say that @
|
|
2542
|
+
# # Let's say that @article has image:
|
|
2537
2543
|
# file_field(:image, :multiple => true)
|
|
2538
|
-
# # => <input type="file" id="
|
|
2544
|
+
# # => <input type="file" id="article_image" name="article[image][]" multiple="multiple" />
|
|
2539
2545
|
#
|
|
2540
|
-
# # Let's say that @
|
|
2546
|
+
# # Let's say that @article has attached:
|
|
2541
2547
|
# file_field(:attached, accept: 'text/html')
|
|
2542
|
-
# # => <input accept="text/html" type="file" id="
|
|
2548
|
+
# # => <input accept="text/html" type="file" id="article_attached" name="article[attached]" />
|
|
2543
2549
|
#
|
|
2544
|
-
# # Let's say that @
|
|
2550
|
+
# # Let's say that @article has image:
|
|
2545
2551
|
# file_field(:image, accept: 'image/png,image/gif,image/jpeg')
|
|
2546
|
-
# # => <input type="file" id="
|
|
2552
|
+
# # => <input type="file" id="article_image" name="article[image]" accept="image/png,image/gif,image/jpeg" />
|
|
2547
2553
|
#
|
|
2548
2554
|
# # Let's say that @attachment has file:
|
|
2549
2555
|
# file_field(:file, class: 'file_input')
|
|
@@ -2556,12 +2562,12 @@ module ActionView
|
|
|
2556
2562
|
# Add the submit button for the given form. When no value is given, it checks
|
|
2557
2563
|
# if the object is a new resource or not to create the proper label:
|
|
2558
2564
|
#
|
|
2559
|
-
# <%=
|
|
2565
|
+
# <%= form_with model: @article do |f| %>
|
|
2560
2566
|
# <%= f.submit %>
|
|
2561
2567
|
# <% end %>
|
|
2562
2568
|
#
|
|
2563
|
-
# In the example above, if <tt>@
|
|
2564
|
-
# submit button label; otherwise, it uses "Update
|
|
2569
|
+
# In the example above, if <tt>@article</tt> is a new record, it will use "Create Article" as
|
|
2570
|
+
# submit button label; otherwise, it uses "Update Article".
|
|
2565
2571
|
#
|
|
2566
2572
|
# Those labels can be customized using I18n under the +helpers.submit+ key and using
|
|
2567
2573
|
# <tt>%{model}</tt> for translation interpolation:
|
|
@@ -2577,7 +2583,7 @@ module ActionView
|
|
|
2577
2583
|
# en:
|
|
2578
2584
|
# helpers:
|
|
2579
2585
|
# submit:
|
|
2580
|
-
#
|
|
2586
|
+
# article:
|
|
2581
2587
|
# create: "Add %{model}"
|
|
2582
2588
|
#
|
|
2583
2589
|
def submit(value = nil, options = {})
|
|
@@ -2589,12 +2595,11 @@ module ActionView
|
|
|
2589
2595
|
# Add the submit button for the given form. When no value is given, it checks
|
|
2590
2596
|
# if the object is a new resource or not to create the proper label:
|
|
2591
2597
|
#
|
|
2592
|
-
# <%=
|
|
2598
|
+
# <%= form_with model: @article do |f| %>
|
|
2593
2599
|
# <%= f.button %>
|
|
2594
2600
|
# <% end %>
|
|
2595
|
-
#
|
|
2596
|
-
#
|
|
2597
|
-
# button label; otherwise, it uses "Update Post".
|
|
2601
|
+
# In the example above, if <tt>@article</tt> is a new record, it will use "Create Article" as
|
|
2602
|
+
# button label; otherwise, it uses "Update Article".
|
|
2598
2603
|
#
|
|
2599
2604
|
# Those labels can be customized using I18n under the +helpers.submit+ key
|
|
2600
2605
|
# (the same as submit helper) and using <tt>%{model}</tt> for translation interpolation:
|
|
@@ -2610,15 +2615,15 @@ module ActionView
|
|
|
2610
2615
|
# en:
|
|
2611
2616
|
# helpers:
|
|
2612
2617
|
# submit:
|
|
2613
|
-
#
|
|
2618
|
+
# article:
|
|
2614
2619
|
# create: "Add %{model}"
|
|
2615
2620
|
#
|
|
2616
2621
|
# ==== Examples
|
|
2617
|
-
# button("Create
|
|
2618
|
-
# # => <button name='button' type='submit'>Create
|
|
2622
|
+
# button("Create article")
|
|
2623
|
+
# # => <button name='button' type='submit'>Create article</button>
|
|
2619
2624
|
#
|
|
2620
2625
|
# button(:draft, value: true)
|
|
2621
|
-
# # => <button id="
|
|
2626
|
+
# # => <button id="article_draft" name="article[draft]" value="true" type="submit">Create article</button>
|
|
2622
2627
|
#
|
|
2623
2628
|
# button do
|
|
2624
2629
|
# content_tag(:strong, 'Ask me!')
|
|
@@ -2631,13 +2636,13 @@ module ActionView
|
|
|
2631
2636
|
# content_tag(:strong, text)
|
|
2632
2637
|
# end
|
|
2633
2638
|
# # => <button name='button' type='submit'>
|
|
2634
|
-
# # <strong>Create
|
|
2639
|
+
# # <strong>Create article</strong>
|
|
2635
2640
|
# # </button>
|
|
2636
2641
|
#
|
|
2637
2642
|
# button(:draft, value: true) do
|
|
2638
2643
|
# content_tag(:strong, "Save as draft")
|
|
2639
2644
|
# end
|
|
2640
|
-
# # => <button id="
|
|
2645
|
+
# # => <button id="article_draft" name="article[draft]" value="true" type="submit">
|
|
2641
2646
|
# # <strong>Save as draft</strong>
|
|
2642
2647
|
# # </button>
|
|
2643
2648
|
#
|