rails 4.1.6 → 4.2.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +12 -10
- data/guides/CHANGELOG.md +64 -17
- data/guides/Rakefile +21 -6
- data/guides/assets/images/getting_started/article_with_comments.png +0 -0
- data/guides/assets/javascripts/guides.js +6 -0
- data/guides/assets/stylesheets/main.css +4 -1
- data/guides/bug_report_templates/action_controller_gem.rb +3 -3
- data/guides/bug_report_templates/action_controller_master.rb +3 -2
- data/guides/bug_report_templates/active_record_gem.rb +1 -1
- data/guides/bug_report_templates/generic_gem.rb +15 -0
- data/guides/bug_report_templates/generic_master.rb +26 -0
- data/guides/rails_guides/helpers.rb +1 -1
- data/guides/rails_guides/levenshtein.rb +27 -21
- data/guides/rails_guides/markdown/renderer.rb +1 -1
- data/guides/rails_guides/markdown.rb +11 -7
- data/guides/rails_guides.rb +2 -2
- data/guides/source/2_2_release_notes.md +1 -1
- data/guides/source/2_3_release_notes.md +4 -4
- data/guides/source/3_0_release_notes.md +8 -8
- data/guides/source/3_1_release_notes.md +6 -3
- data/guides/source/3_2_release_notes.md +6 -3
- data/guides/source/4_0_release_notes.md +6 -3
- data/guides/source/4_1_release_notes.md +9 -10
- data/guides/source/4_2_release_notes.md +877 -0
- data/guides/source/_license.html.erb +1 -1
- data/guides/source/_welcome.html.erb +6 -8
- data/guides/source/action_controller_overview.md +25 -8
- data/guides/source/action_mailer_basics.md +97 -29
- data/guides/source/action_view_overview.md +142 -191
- data/guides/source/active_job_basics.md +339 -0
- data/guides/source/active_model_basics.md +371 -17
- data/guides/source/active_record_basics.md +25 -24
- data/guides/source/active_record_callbacks.md +12 -9
- data/guides/source/{migrations.md → active_record_migrations.md} +95 -220
- data/guides/source/active_record_postgresql.md +433 -0
- data/guides/source/active_record_querying.md +264 -268
- data/guides/source/active_record_validations.md +23 -13
- data/guides/source/active_support_core_extensions.md +115 -123
- data/guides/source/active_support_instrumentation.md +10 -18
- data/guides/source/api_documentation_guidelines.md +63 -17
- data/guides/source/asset_pipeline.md +259 -120
- data/guides/source/association_basics.md +96 -80
- data/guides/source/autoloading_and_reloading_constants.md +1311 -0
- data/guides/source/caching_with_rails.md +32 -7
- data/guides/source/command_line.md +52 -30
- data/guides/source/configuring.md +161 -33
- data/guides/source/contributing_to_ruby_on_rails.md +198 -114
- data/guides/source/credits.html.erb +2 -2
- data/guides/source/debugging_rails_applications.md +440 -286
- data/guides/source/development_dependencies_install.md +47 -36
- data/guides/source/documents.yaml +19 -7
- data/guides/source/engines.md +217 -196
- data/guides/source/form_helpers.md +79 -56
- data/guides/source/generators.md +24 -11
- data/guides/source/getting_started.md +359 -219
- data/guides/source/i18n.md +110 -66
- data/guides/source/index.html.erb +1 -0
- data/guides/source/initialization.md +109 -62
- data/guides/source/layout.html.erb +5 -11
- data/guides/source/layouts_and_rendering.md +26 -26
- data/guides/source/maintenance_policy.md +6 -3
- data/guides/source/nested_model_forms.md +7 -4
- data/guides/source/plugins.md +27 -27
- data/guides/source/rails_application_templates.md +21 -3
- data/guides/source/rails_on_rack.md +8 -5
- data/guides/source/routing.md +113 -73
- data/guides/source/ruby_on_rails_guides_guidelines.md +11 -12
- data/guides/source/security.md +40 -34
- data/guides/source/testing.md +199 -119
- data/guides/source/upgrading_ruby_on_rails.md +289 -31
- data/guides/source/working_with_javascript_in_rails.md +19 -17
- data/guides/w3c_validator.rb +2 -0
- metadata +42 -95
- data/guides/code/getting_started/Gemfile +0 -40
- data/guides/code/getting_started/Gemfile.lock +0 -125
- data/guides/code/getting_started/README.rdoc +0 -28
- data/guides/code/getting_started/Rakefile +0 -6
- data/guides/code/getting_started/app/assets/javascripts/application.js +0 -15
- data/guides/code/getting_started/app/assets/javascripts/comments.js.coffee +0 -3
- data/guides/code/getting_started/app/assets/javascripts/posts.js.coffee +0 -3
- data/guides/code/getting_started/app/assets/javascripts/welcome.js.coffee +0 -3
- data/guides/code/getting_started/app/assets/stylesheets/application.css +0 -13
- data/guides/code/getting_started/app/assets/stylesheets/comments.css.scss +0 -3
- data/guides/code/getting_started/app/assets/stylesheets/posts.css.scss +0 -3
- data/guides/code/getting_started/app/assets/stylesheets/welcome.css.scss +0 -3
- data/guides/code/getting_started/app/controllers/application_controller.rb +0 -5
- data/guides/code/getting_started/app/controllers/comments_controller.rb +0 -23
- data/guides/code/getting_started/app/controllers/posts_controller.rb +0 -53
- data/guides/code/getting_started/app/controllers/welcome_controller.rb +0 -4
- data/guides/code/getting_started/app/helpers/application_helper.rb +0 -2
- data/guides/code/getting_started/app/helpers/comments_helper.rb +0 -2
- data/guides/code/getting_started/app/helpers/posts_helper.rb +0 -2
- data/guides/code/getting_started/app/helpers/welcome_helper.rb +0 -2
- data/guides/code/getting_started/app/models/comment.rb +0 -3
- data/guides/code/getting_started/app/models/post.rb +0 -7
- data/guides/code/getting_started/app/views/comments/_comment.html.erb +0 -15
- data/guides/code/getting_started/app/views/comments/_form.html.erb +0 -13
- data/guides/code/getting_started/app/views/layouts/application.html.erb +0 -14
- data/guides/code/getting_started/app/views/posts/_form.html.erb +0 -27
- data/guides/code/getting_started/app/views/posts/edit.html.erb +0 -5
- data/guides/code/getting_started/app/views/posts/index.html.erb +0 -21
- data/guides/code/getting_started/app/views/posts/new.html.erb +0 -5
- data/guides/code/getting_started/app/views/posts/show.html.erb +0 -18
- data/guides/code/getting_started/app/views/welcome/index.html.erb +0 -4
- data/guides/code/getting_started/bin/bundle +0 -4
- data/guides/code/getting_started/bin/rails +0 -4
- data/guides/code/getting_started/bin/rake +0 -4
- data/guides/code/getting_started/config/application.rb +0 -18
- data/guides/code/getting_started/config/boot.rb +0 -4
- data/guides/code/getting_started/config/database.yml +0 -25
- data/guides/code/getting_started/config/environment.rb +0 -5
- data/guides/code/getting_started/config/environments/development.rb +0 -30
- data/guides/code/getting_started/config/environments/production.rb +0 -80
- data/guides/code/getting_started/config/environments/test.rb +0 -36
- data/guides/code/getting_started/config/initializers/backtrace_silencers.rb +0 -7
- data/guides/code/getting_started/config/initializers/filter_parameter_logging.rb +0 -4
- data/guides/code/getting_started/config/initializers/inflections.rb +0 -16
- data/guides/code/getting_started/config/initializers/locale.rb +0 -9
- data/guides/code/getting_started/config/initializers/mime_types.rb +0 -5
- data/guides/code/getting_started/config/initializers/secret_token.rb +0 -12
- data/guides/code/getting_started/config/initializers/session_store.rb +0 -3
- data/guides/code/getting_started/config/initializers/wrap_parameters.rb +0 -14
- data/guides/code/getting_started/config/locales/en.yml +0 -23
- data/guides/code/getting_started/config/routes.rb +0 -7
- data/guides/code/getting_started/config.ru +0 -4
- data/guides/code/getting_started/db/migrate/20130122042648_create_posts.rb +0 -10
- data/guides/code/getting_started/db/migrate/20130122045842_create_comments.rb +0 -11
- data/guides/code/getting_started/db/schema.rb +0 -33
- data/guides/code/getting_started/db/seeds.rb +0 -7
- data/guides/code/getting_started/public/404.html +0 -60
- data/guides/code/getting_started/public/422.html +0 -60
- data/guides/code/getting_started/public/500.html +0 -59
- data/guides/code/getting_started/public/favicon.ico +0 -0
- data/guides/code/getting_started/public/robots.txt +0 -5
- data/guides/code/getting_started/test/controllers/comments_controller_test.rb +0 -7
- data/guides/code/getting_started/test/controllers/posts_controller_test.rb +0 -7
- data/guides/code/getting_started/test/controllers/welcome_controller_test.rb +0 -9
- data/guides/code/getting_started/test/fixtures/comments.yml +0 -11
- data/guides/code/getting_started/test/fixtures/posts.yml +0 -9
- data/guides/code/getting_started/test/helpers/comments_helper_test.rb +0 -4
- data/guides/code/getting_started/test/helpers/posts_helper_test.rb +0 -4
- data/guides/code/getting_started/test/helpers/welcome_helper_test.rb +0 -4
- data/guides/code/getting_started/test/models/comment_test.rb +0 -7
- data/guides/code/getting_started/test/models/post_test.rb +0 -7
- data/guides/code/getting_started/test/test_helper.rb +0 -12
@@ -1,23 +1,22 @@
|
|
1
1
|
Form Helpers
|
2
2
|
============
|
3
3
|
|
4
|
-
Forms in web applications are an essential interface for user input. However, form markup can quickly become tedious to write and maintain because of form control naming and
|
4
|
+
Forms in web applications are an essential interface for user input. However, form markup can quickly become tedious to write and maintain because of the need to handle form control naming and its numerous attributes. Rails does away with this complexity by providing view helpers for generating form markup. However, since these helpers have different use cases, developers need to know the differences between the helper methods before putting them to use.
|
5
5
|
|
6
6
|
After reading this guide, you will know:
|
7
7
|
|
8
8
|
* How to create search forms and similar kind of generic forms not representing any specific model in your application.
|
9
|
-
* How to make model-centric forms for
|
9
|
+
* How to make model-centric forms for creating and editing specific database records.
|
10
10
|
* How to generate select boxes from multiple types of data.
|
11
|
-
*
|
11
|
+
* What date and time helpers Rails provides.
|
12
12
|
* What makes a file upload form different.
|
13
|
-
*
|
13
|
+
* How to post forms to external resources and specify setting an `authenticity_token`.
|
14
14
|
* How to build complex forms.
|
15
15
|
|
16
16
|
--------------------------------------------------------------------------------
|
17
17
|
|
18
18
|
NOTE: This guide is not intended to be a complete documentation of available form helpers and their arguments. Please visit [the Rails API documentation](http://api.rubyonrails.org/) for a complete reference.
|
19
19
|
|
20
|
-
|
21
20
|
Dealing with Basic Forms
|
22
21
|
------------------------
|
23
22
|
|
@@ -32,18 +31,14 @@ The most basic form helper is `form_tag`.
|
|
32
31
|
When called without arguments like this, it creates a `<form>` tag which, when submitted, will POST to the current page. For instance, assuming the current page is `/home/index`, the generated HTML will look like this (some line breaks added for readability):
|
33
32
|
|
34
33
|
```html
|
35
|
-
<form accept-charset="UTF-8" action="/
|
36
|
-
<
|
37
|
-
|
38
|
-
<input name="authenticity_token" type="hidden" value="f755bb0ed134b76c432144748a6d4b7a7ddf2b71" />
|
39
|
-
</div>
|
34
|
+
<form accept-charset="UTF-8" action="/" method="post">
|
35
|
+
<input name="utf8" type="hidden" value="✓" />
|
36
|
+
<input name="authenticity_token" type="hidden" value="J7CBxfHalt49OSHp27hblqK20c9PgwJ108nDHX/8Cts=" />
|
40
37
|
Form contents
|
41
38
|
</form>
|
42
39
|
```
|
43
40
|
|
44
|
-
|
45
|
-
|
46
|
-
NOTE: Throughout this guide, the `div` with the hidden input elements will be excluded from code samples for brevity.
|
41
|
+
You'll notice that the HTML contains `input` element with type `hidden`. This `input` is important, because the form cannot be successfully submitted without it. The hidden input element has name attribute of `utf8` enforces browsers to properly respect your form's character encoding and is generated for all forms whether their actions are "GET" or "POST". The second input element with name `authenticity_token` is a security feature of Rails called **cross-site request forgery protection**, and form helpers generate it for every non-GET form (provided that this security feature is enabled). You can read more about this in the [Security Guide](security.html#cross-site-request-forgery-csrf).
|
47
42
|
|
48
43
|
### A Generic Search Form
|
49
44
|
|
@@ -67,14 +62,15 @@ To create this form you will use `form_tag`, `label_tag`, `text_field_tag`, and
|
|
67
62
|
This will generate the following HTML:
|
68
63
|
|
69
64
|
```html
|
70
|
-
<form accept-charset="UTF-8" action="/search" method="get"
|
65
|
+
<form accept-charset="UTF-8" action="/search" method="get">
|
66
|
+
<input name="utf8" type="hidden" value="✓" />
|
71
67
|
<label for="q">Search for:</label>
|
72
68
|
<input id="q" name="q" type="text" />
|
73
69
|
<input name="commit" type="submit" value="Search" />
|
74
70
|
</form>
|
75
71
|
```
|
76
72
|
|
77
|
-
TIP: For every form input, an ID attribute is generated from its name ("q" in
|
73
|
+
TIP: For every form input, an ID attribute is generated from its name (`"q"` in above example). These IDs can be very useful for CSS styling or manipulation of form controls with JavaScript.
|
78
74
|
|
79
75
|
Besides `text_field_tag` and `submit_tag`, there is a similar helper for _every_ form control in HTML.
|
80
76
|
|
@@ -100,7 +96,15 @@ form_tag({controller: "people", action: "search"}, method: "get", class: "nifty_
|
|
100
96
|
|
101
97
|
### Helpers for Generating Form Elements
|
102
98
|
|
103
|
-
Rails provides a series of helpers for generating form elements such as
|
99
|
+
Rails provides a series of helpers for generating form elements such as
|
100
|
+
checkboxes, text fields, and radio buttons. These basic helpers, with names
|
101
|
+
ending in `_tag` (such as `text_field_tag` and `check_box_tag`), generate just a
|
102
|
+
single `<input>` element. The first parameter to these is always the name of the
|
103
|
+
input. When the form is submitted, the name will be passed along with the form
|
104
|
+
data, and will make its way to the `params` hash in the controller with the
|
105
|
+
value entered by the user for that field. For example, if the form contains `<%=
|
106
|
+
text_field_tag(:query) %>`, then you would be able to get the value of this
|
107
|
+
field in the controller with `params[:query]`.
|
104
108
|
|
105
109
|
When naming inputs, Rails uses certain conventions that make it possible to submit parameters with non-scalar values such as arrays or hashes, which will also be accessible in `params`. You can read more about them in [chapter 7 of this guide](#understanding-parameter-naming-conventions). For details on the precise usage of these helpers, please refer to the [API documentation](http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html).
|
106
110
|
|
@@ -146,7 +150,7 @@ Output:
|
|
146
150
|
<label for="age_adult">I'm over 21</label>
|
147
151
|
```
|
148
152
|
|
149
|
-
As with `check_box_tag`, the second parameter to `radio_button_tag` is the value of the input. Because these two radio buttons share the same name (age) the user will only be able to select one, and `params[:age]` will contain either "child" or "adult"
|
153
|
+
As with `check_box_tag`, the second parameter to `radio_button_tag` is the value of the input. Because these two radio buttons share the same name (`age`), the user will only be able to select one of them, and `params[:age]` will contain either `"child"` or `"adult"`.
|
150
154
|
|
151
155
|
NOTE: Always use labels for checkbox and radio buttons. They associate text with a specific option and,
|
152
156
|
by expanding the clickable region,
|
@@ -217,7 +221,7 @@ Dealing with Model Objects
|
|
217
221
|
|
218
222
|
### Model Object Helpers
|
219
223
|
|
220
|
-
A particularly common task for a form is editing or creating a model object. While the `*_tag` helpers can certainly be used for this task they are somewhat verbose as for each tag you would have to ensure the correct parameter name is used and set the default value of the input appropriately. Rails provides helpers tailored to this task. These helpers lack the _tag suffix, for example `text_field`, `text_area`.
|
224
|
+
A particularly common task for a form is editing or creating a model object. While the `*_tag` helpers can certainly be used for this task they are somewhat verbose as for each tag you would have to ensure the correct parameter name is used and set the default value of the input appropriately. Rails provides helpers tailored to this task. These helpers lack the `_tag` suffix, for example `text_field`, `text_area`.
|
221
225
|
|
222
226
|
For these helpers the first argument is the name of an instance variable and the second is the name of a method (usually an attribute) to call on that object. Rails will set the value of the input control to the return value of that method for the object and set an appropriate input name. If your controller has defined `@person` and that person's name is Henry then a form containing:
|
223
227
|
|
@@ -239,7 +243,7 @@ Rails provides helpers for displaying the validation errors associated with a mo
|
|
239
243
|
|
240
244
|
### Binding a Form to an Object
|
241
245
|
|
242
|
-
While this is an increase in comfort it is far from perfect. If Person has many attributes to edit then we would be repeating the name of the edited object many times. What we want to do is somehow bind a form to a model object, which is exactly what `form_for` does.
|
246
|
+
While this is an increase in comfort it is far from perfect. If `Person` has many attributes to edit then we would be repeating the name of the edited object many times. What we want to do is somehow bind a form to a model object, which is exactly what `form_for` does.
|
243
247
|
|
244
248
|
Assume we have a controller for dealing with articles `app/controllers/articles_controller.rb`:
|
245
249
|
|
@@ -264,7 +268,7 @@ There are a few things to note here:
|
|
264
268
|
* `@article` is the actual object being edited.
|
265
269
|
* There is a single hash of options. Routing options are passed in the `:url` hash, HTML options are passed in the `:html` hash. Also you can provide a `:namespace` option for your form to ensure uniqueness of id attributes on form elements. The namespace attribute will be prefixed with underscore on the generated HTML id.
|
266
270
|
* The `form_for` method yields a **form builder** object (the `f` variable).
|
267
|
-
* Methods to create form controls are called **on** the form builder object `f
|
271
|
+
* Methods to create form controls are called **on** the form builder object `f`.
|
268
272
|
|
269
273
|
The resulting HTML is:
|
270
274
|
|
@@ -280,7 +284,7 @@ The name passed to `form_for` controls the key used in `params` to access the fo
|
|
280
284
|
|
281
285
|
The helper methods called on the form builder are identical to the model object helpers except that it is not necessary to specify which object is being edited since this is already managed by the form builder.
|
282
286
|
|
283
|
-
You can create a similar binding without actually creating `<form>` tags with the `fields_for` helper. This is useful for editing additional model objects with the same form. For example if you had a Person model with an associated ContactDetail model you could create a form for creating both like so:
|
287
|
+
You can create a similar binding without actually creating `<form>` tags with the `fields_for` helper. This is useful for editing additional model objects with the same form. For example, if you had a `Person` model with an associated `ContactDetail` model, you could create a form for creating both like so:
|
284
288
|
|
285
289
|
```erb
|
286
290
|
<%= form_for @person, url: {action: "create"} do |person_form| %>
|
@@ -350,7 +354,6 @@ form_for [:admin, :management, @article]
|
|
350
354
|
|
351
355
|
For more information on Rails' routing system and the associated conventions, please see the [routing guide](routing.html).
|
352
356
|
|
353
|
-
|
354
357
|
### How do forms with PATCH, PUT, or DELETE methods work?
|
355
358
|
|
356
359
|
The Rails framework encourages RESTful design of your applications, which means you'll be making a lot of "PATCH" and "DELETE" requests (besides "GET" and "POST"). However, most browsers _don't support_ methods other than "GET" and "POST" when it comes to submitting forms.
|
@@ -365,12 +368,11 @@ output:
|
|
365
368
|
|
366
369
|
```html
|
367
370
|
<form accept-charset="UTF-8" action="/search" method="post">
|
368
|
-
<
|
369
|
-
|
370
|
-
|
371
|
-
<input name="authenticity_token" type="hidden" value="f755bb0ed134b76c432144748a6d4b7a7ddf2b71" />
|
372
|
-
</div>
|
371
|
+
<input name="_method" type="hidden" value="patch" />
|
372
|
+
<input name="utf8" type="hidden" value="✓" />
|
373
|
+
<input name="authenticity_token" type="hidden" value="f755bb0ed134b76c432144748a6d4b7a7ddf2b71" />
|
373
374
|
...
|
375
|
+
</form>
|
374
376
|
```
|
375
377
|
|
376
378
|
When parsing POSTed data, Rails will take into account the special `_method` parameter and acts as if the HTTP method was the one specified inside it ("PATCH" in this example).
|
@@ -435,14 +437,19 @@ output:
|
|
435
437
|
|
436
438
|
Whenever Rails sees that the internal value of an option being generated matches this value, it will add the `selected` attribute to that option.
|
437
439
|
|
438
|
-
TIP: The second argument to `options_for_select` must be exactly equal to the desired internal value. In particular if the value is the integer 2 you cannot pass "2" to `options_for_select` - you must pass 2
|
440
|
+
TIP: The second argument to `options_for_select` must be exactly equal to the desired internal value. In particular if the value is the integer `2` you cannot pass `"2"` to `options_for_select` - you must pass `2`. Be aware of values extracted from the `params` hash as they are all strings.
|
439
441
|
|
440
442
|
WARNING: when `:include_blank` or `:prompt` are not present, `:include_blank` is forced true if the select attribute `required` is true, display `size` is one and `multiple` is not true.
|
441
443
|
|
442
444
|
You can add arbitrary attributes to the options using hashes:
|
443
445
|
|
444
446
|
```html+erb
|
445
|
-
<%= options_for_select(
|
447
|
+
<%= options_for_select(
|
448
|
+
[
|
449
|
+
['Lisbon', 1, { 'data-size' => '2.8 million' }],
|
450
|
+
['Madrid', 2, { 'data-size' => '3.2 million' }]
|
451
|
+
], 2
|
452
|
+
) %>
|
446
453
|
|
447
454
|
output:
|
448
455
|
|
@@ -474,11 +481,21 @@ As with other helpers, if you were to use the `select` helper on a form builder
|
|
474
481
|
<%= f.select(:city_id, ...) %>
|
475
482
|
```
|
476
483
|
|
477
|
-
|
484
|
+
You can also pass a block to `select` helper:
|
485
|
+
|
486
|
+
```erb
|
487
|
+
<%= f.select(:city_id) do %>
|
488
|
+
<% [['Lisbon', 1], ['Madrid', 2]].each do |c| -%>
|
489
|
+
<%= content_tag(:option, c.first, value: c.last) %>
|
490
|
+
<% end %>
|
491
|
+
<% end %>
|
492
|
+
```
|
493
|
+
|
494
|
+
WARNING: If you are using `select` (or similar helpers such as `collection_select`, `select_tag`) to set a `belongs_to` association you must pass the name of the foreign key (in the example above `city_id`), not the name of association itself. If you specify `city` instead of `city_id` Active Record will raise an error along the lines of `ActiveRecord::AssociationTypeMismatch: City(#17815740) expected, got String(#1138750)` when you pass the `params` hash to `Person.new` or `update`. Another way of looking at this is that form helpers only edit attributes. You should also be aware of the potential security ramifications of allowing users to edit foreign keys directly.
|
478
495
|
|
479
496
|
### Option Tags from a Collection of Arbitrary Objects
|
480
497
|
|
481
|
-
Generating options tags with `options_for_select` requires that you create an array containing the text and value for each option. But what if you had a City model (perhaps an Active Record one) and you wanted to generate option tags from a collection of those objects? One solution would be to make a nested array by iterating over them:
|
498
|
+
Generating options tags with `options_for_select` requires that you create an array containing the text and value for each option. But what if you had a `City` model (perhaps an Active Record one) and you wanted to generate option tags from a collection of those objects? One solution would be to make a nested array by iterating over them:
|
482
499
|
|
483
500
|
```erb
|
484
501
|
<% cities_array = City.all.map { |city| [city.name, city.id] } %>
|
@@ -497,6 +514,12 @@ As the name implies, this only generates option tags. To generate a working sele
|
|
497
514
|
<%= collection_select(:person, :city_id, City.all, :id, :name) %>
|
498
515
|
```
|
499
516
|
|
517
|
+
As with other helpers, if you were to use the `collection_select` helper on a form builder scoped to the `@person` object, the syntax would be:
|
518
|
+
|
519
|
+
```erb
|
520
|
+
<%= f.collection_select(:city_id, City.all, :id, :name) %>
|
521
|
+
```
|
522
|
+
|
500
523
|
To recap, `options_from_collection_for_select` is to `collection_select` what `options_for_select` is to `select`.
|
501
524
|
|
502
525
|
NOTE: Pairs passed to `options_for_select` should have the name first and the id second, however with `options_from_collection_for_select` the first argument is the value method and the second the text method.
|
@@ -525,7 +548,7 @@ Both of these families of helpers will create a series of select boxes for the d
|
|
525
548
|
|
526
549
|
### Barebones Helpers
|
527
550
|
|
528
|
-
The `select_*` family of helpers take as their first argument an instance of Date
|
551
|
+
The `select_*` family of helpers take as their first argument an instance of `Date`, `Time` or `DateTime` that is used as the currently selected value. You may omit this parameter, in which case the current date is used. For example:
|
529
552
|
|
530
553
|
```erb
|
531
554
|
<%= select_date Date.today, prefix: :start_date %>
|
@@ -539,7 +562,7 @@ outputs (with actual option values omitted for brevity)
|
|
539
562
|
<select id="start_date_day" name="start_date[day]"> ... </select>
|
540
563
|
```
|
541
564
|
|
542
|
-
The above inputs would result in `params[:start_date]` being a hash with keys `:year`, `:month`, `:day`. To get an actual Time or
|
565
|
+
The above inputs would result in `params[:start_date]` being a hash with keys `:year`, `:month`, `:day`. To get an actual `Date`, `Time` or `DateTime` object you would have to extract these values and pass them to the appropriate constructor, for example:
|
543
566
|
|
544
567
|
```ruby
|
545
568
|
Date.civil(params[:start_date][:year].to_i, params[:start_date][:month].to_i, params[:start_date][:day].to_i)
|
@@ -582,9 +605,9 @@ NOTE: In many cases the built-in date pickers are clumsy as they do not aid the
|
|
582
605
|
|
583
606
|
### Individual Components
|
584
607
|
|
585
|
-
Occasionally you need to display just a single date component such as a year or a month. Rails provides a series of helpers for this, one for each component `select_year`, `select_month`, `select_day`, `select_hour`, `select_minute`, `select_second`. These helpers are fairly straightforward. By default they will generate an input field named after the time component (for example "year" for `select_year`, "month" for `select_month` etc.) although this can be overridden with the `:field_name` option. The `:prefix` option works in the same way that it does for `select_date` and `select_time` and has the same default value.
|
608
|
+
Occasionally you need to display just a single date component such as a year or a month. Rails provides a series of helpers for this, one for each component `select_year`, `select_month`, `select_day`, `select_hour`, `select_minute`, `select_second`. These helpers are fairly straightforward. By default they will generate an input field named after the time component (for example, "year" for `select_year`, "month" for `select_month` etc.) although this can be overridden with the `:field_name` option. The `:prefix` option works in the same way that it does for `select_date` and `select_time` and has the same default value.
|
586
609
|
|
587
|
-
The first parameter specifies which value should be selected and can either be an instance of a Date
|
610
|
+
The first parameter specifies which value should be selected and can either be an instance of a `Date`, `Time` or `DateTime`, in which case the relevant component will be extracted, or a numerical value. For example:
|
588
611
|
|
589
612
|
```erb
|
590
613
|
<%= select_year(2009) %>
|
@@ -614,7 +637,7 @@ Rails provides the usual pair of helpers: the barebones `file_field_tag` and the
|
|
614
637
|
|
615
638
|
### What Gets Uploaded
|
616
639
|
|
617
|
-
The object in the `params` hash is an instance of a subclass of IO
|
640
|
+
The object in the `params` hash is an instance of a subclass of `IO`. Depending on the size of the uploaded file it may in fact be a `StringIO` or an instance of `File` backed by a temporary file. In both cases the object will have an `original_filename` attribute containing the name the file had on the user's computer and a `content_type` attribute containing the MIME type of the uploaded file. The following snippet saves the uploaded content in `#{Rails.root}/public/uploads` under the same name as the original file (assuming the form was the one in the previous example).
|
618
641
|
|
619
642
|
```ruby
|
620
643
|
def upload
|
@@ -625,7 +648,7 @@ def upload
|
|
625
648
|
end
|
626
649
|
```
|
627
650
|
|
628
|
-
Once a file has been uploaded, there are a multitude of potential tasks, ranging from where to store the files (on disk, Amazon S3, etc) and associating them with models to resizing image files and generating thumbnails. The intricacies of this are beyond the scope of this guide, but there are several libraries designed to assist with these. Two of the better known ones are [CarrierWave](https://github.com/jnicklas/carrierwave) and [Paperclip](
|
651
|
+
Once a file has been uploaded, there are a multitude of potential tasks, ranging from where to store the files (on disk, Amazon S3, etc) and associating them with models to resizing image files and generating thumbnails. The intricacies of this are beyond the scope of this guide, but there are several libraries designed to assist with these. Two of the better known ones are [CarrierWave](https://github.com/jnicklas/carrierwave) and [Paperclip](https://github.com/thoughtbot/paperclip).
|
629
652
|
|
630
653
|
NOTE: If the user has not selected a file the corresponding parameter will be an empty string.
|
631
654
|
|
@@ -636,7 +659,7 @@ Unlike other forms making an asynchronous file upload form is not as simple as p
|
|
636
659
|
Customizing Form Builders
|
637
660
|
-------------------------
|
638
661
|
|
639
|
-
As mentioned previously the object yielded by `form_for` and `fields_for` is an instance of FormBuilder (or a subclass thereof). Form builders encapsulate the notion of displaying form elements for a single object. While you can of course write helpers for your forms in the usual way, you can also subclass FormBuilder and add the helpers there. For example
|
662
|
+
As mentioned previously the object yielded by `form_for` and `fields_for` is an instance of `FormBuilder` (or a subclass thereof). Form builders encapsulate the notion of displaying form elements for a single object. While you can of course write helpers for your forms in the usual way, you can also subclass `FormBuilder` and add the helpers there. For example:
|
640
663
|
|
641
664
|
```erb
|
642
665
|
<%= form_for @person do |f| %>
|
@@ -652,7 +675,7 @@ can be replaced with
|
|
652
675
|
<% end %>
|
653
676
|
```
|
654
677
|
|
655
|
-
by defining a LabellingFormBuilder class similar to the following:
|
678
|
+
by defining a `LabellingFormBuilder` class similar to the following:
|
656
679
|
|
657
680
|
```ruby
|
658
681
|
class LabellingFormBuilder < ActionView::Helpers::FormBuilder
|
@@ -670,17 +693,17 @@ The form builder used also determines what happens when you do
|
|
670
693
|
<%= render partial: f %>
|
671
694
|
```
|
672
695
|
|
673
|
-
If `f` is an instance of FormBuilder then this will render the `form` partial, setting the partial's object to the form builder. If the form builder is of class LabellingFormBuilder then the `labelling_form` partial would be rendered instead.
|
696
|
+
If `f` is an instance of `FormBuilder` then this will render the `form` partial, setting the partial's object to the form builder. If the form builder is of class `LabellingFormBuilder` then the `labelling_form` partial would be rendered instead.
|
674
697
|
|
675
698
|
Understanding Parameter Naming Conventions
|
676
699
|
------------------------------------------
|
677
700
|
|
678
|
-
As you've seen in the previous sections, values from forms can be at the top level of the `params` hash or nested in another hash. For example in a standard `create`
|
701
|
+
As you've seen in the previous sections, values from forms can be at the top level of the `params` hash or nested in another hash. For example, in a standard `create`
|
679
702
|
action for a Person model, `params[:person]` would usually be a hash of all the attributes for the person to create. The `params` hash can also contain arrays, arrays of hashes and so on.
|
680
703
|
|
681
704
|
Fundamentally HTML forms don't know about any sort of structured data, all they generate is name-value pairs, where pairs are just plain strings. The arrays and hashes you see in your application are the result of some parameter naming conventions that Rails uses.
|
682
705
|
|
683
|
-
TIP: You may find you can try out examples in this section faster by using the console to directly invoke
|
706
|
+
TIP: You may find you can try out examples in this section faster by using the console to directly invoke Rack's parameter parser. For example,
|
684
707
|
|
685
708
|
```ruby
|
686
709
|
Rack::Utils.parse_query "name=fred&phone=0123456789"
|
@@ -689,7 +712,7 @@ Rack::Utils.parse_query "name=fred&phone=0123456789"
|
|
689
712
|
|
690
713
|
### Basic Structures
|
691
714
|
|
692
|
-
The two basic structures are arrays and hashes. Hashes mirror the syntax used for accessing the value in `params`. For example if a form contains
|
715
|
+
The two basic structures are arrays and hashes. Hashes mirror the syntax used for accessing the value in `params`. For example, if a form contains:
|
693
716
|
|
694
717
|
```html
|
695
718
|
<input id="person_name" name="person[name]" type="text" value="Henry"/>
|
@@ -703,7 +726,7 @@ the `params` hash will contain
|
|
703
726
|
|
704
727
|
and `params[:person][:name]` will retrieve the submitted value in the controller.
|
705
728
|
|
706
|
-
Hashes can be nested as many levels as required, for example
|
729
|
+
Hashes can be nested as many levels as required, for example:
|
707
730
|
|
708
731
|
```html
|
709
732
|
<input id="person_address_city" name="person[address][city]" type="text" value="New York"/>
|
@@ -715,7 +738,7 @@ will result in the `params` hash being
|
|
715
738
|
{'person' => {'address' => {'city' => 'New York'}}}
|
716
739
|
```
|
717
740
|
|
718
|
-
Normally Rails ignores duplicate parameter names. If the parameter name contains an empty set of square brackets [] then they will be accumulated in an array. If you wanted
|
741
|
+
Normally Rails ignores duplicate parameter names. If the parameter name contains an empty set of square brackets `[]` then they will be accumulated in an array. If you wanted users to be able to input multiple phone numbers, you could place this in the form:
|
719
742
|
|
720
743
|
```html
|
721
744
|
<input name="person[phone_number][]" type="text"/>
|
@@ -723,11 +746,11 @@ Normally Rails ignores duplicate parameter names. If the parameter name contains
|
|
723
746
|
<input name="person[phone_number][]" type="text"/>
|
724
747
|
```
|
725
748
|
|
726
|
-
This would result in `params[:person][:phone_number]` being an array.
|
749
|
+
This would result in `params[:person][:phone_number]` being an array containing the inputted phone numbers.
|
727
750
|
|
728
751
|
### Combining Them
|
729
752
|
|
730
|
-
We can mix and match these two concepts.
|
753
|
+
We can mix and match these two concepts. One element of a hash might be an array as in the previous example, or you can have an array of hashes. For example, a form might let you create any number of addresses by repeating the following form fragment
|
731
754
|
|
732
755
|
```html
|
733
756
|
<input name="addresses[][line1]" type="text"/>
|
@@ -737,7 +760,7 @@ We can mix and match these two concepts. For example, one element of a hash migh
|
|
737
760
|
|
738
761
|
This would result in `params[:addresses]` being an array of hashes with keys `line1`, `line2` and `city`. Rails decides to start accumulating values in a new hash whenever it encounters an input name that already exists in the current hash.
|
739
762
|
|
740
|
-
There's a restriction, however, while hashes can be nested arbitrarily, only one level of "arrayness" is allowed. Arrays can be
|
763
|
+
There's a restriction, however, while hashes can be nested arbitrarily, only one level of "arrayness" is allowed. Arrays can usually be replaced by hashes; for example, instead of having an array of model objects, one can have a hash of model objects keyed by their id, an array index or some other parameter.
|
741
764
|
|
742
765
|
WARNING: Array parameters do not play well with the `check_box` helper. According to the HTML specification unchecked checkboxes submit no value. However it is often convenient for a checkbox to always submit a value. The `check_box` helper fakes this by creating an auxiliary hidden input with the same name. If the checkbox is unchecked only the hidden input is submitted and if it is checked then both are submitted but the value submitted by the checkbox takes precedence. When working with array parameters this duplicate submission will confuse Rails since duplicate input names are how it decides when to start a new array element. It is preferable to either use `check_box_tag` or to use hashes instead of arrays.
|
743
766
|
|
@@ -809,21 +832,21 @@ As a shortcut you can append [] to the name and omit the `:index` option. This i
|
|
809
832
|
|
810
833
|
produces exactly the same output as the previous example.
|
811
834
|
|
812
|
-
Forms to
|
835
|
+
Forms to External Resources
|
813
836
|
---------------------------
|
814
837
|
|
815
|
-
|
838
|
+
Rails' form helpers can also be used to build a form for posting data to an external resource. However, at times it can be necessary to set an `authenticity_token` for the resource; this can be done by passing an `authenticity_token: 'your_external_token'` parameter to the `form_tag` options:
|
816
839
|
|
817
840
|
```erb
|
818
|
-
<%= form_tag 'http://farfar.away/form', authenticity_token: 'external_token'
|
841
|
+
<%= form_tag 'http://farfar.away/form', authenticity_token: 'external_token' do %>
|
819
842
|
Form contents
|
820
843
|
<% end %>
|
821
844
|
```
|
822
845
|
|
823
|
-
Sometimes when
|
846
|
+
Sometimes when submitting data to an external resource, like a payment gateway, the fields that can be used in the form are limited by an external API and it may be undesirable to generate an `authenticity_token`. To not send a token, simply pass `false` to the `:authenticity_token` option:
|
824
847
|
|
825
848
|
```erb
|
826
|
-
<%= form_tag 'http://farfar.away/form', authenticity_token: false
|
849
|
+
<%= form_tag 'http://farfar.away/form', authenticity_token: false do %>
|
827
850
|
Form contents
|
828
851
|
<% end %>
|
829
852
|
```
|
@@ -847,7 +870,7 @@ Or if you don't want to render an `authenticity_token` field:
|
|
847
870
|
Building Complex Forms
|
848
871
|
----------------------
|
849
872
|
|
850
|
-
Many apps grow beyond simple forms editing a single object. For example when creating a Person you might want to allow the user to (on the same form) create multiple address records (home, work, etc.). When later editing that person the user should be able to add, remove or amend addresses as necessary.
|
873
|
+
Many apps grow beyond simple forms editing a single object. For example, when creating a `Person` you might want to allow the user to (on the same form) create multiple address records (home, work, etc.). When later editing that person the user should be able to add, remove or amend addresses as necessary.
|
851
874
|
|
852
875
|
### Configuring the Model
|
853
876
|
|
@@ -899,7 +922,7 @@ end
|
|
899
922
|
```
|
900
923
|
|
901
924
|
The `fields_for` yields a form builder. The parameters' name will be what
|
902
|
-
`accepts_nested_attributes_for` expects. For example when creating a user with
|
925
|
+
`accepts_nested_attributes_for` expects. For example, when creating a user with
|
903
926
|
2 addresses, the submitted parameters would look like:
|
904
927
|
|
905
928
|
```ruby
|
@@ -998,4 +1021,4 @@ As a convenience you can instead pass the symbol `:all_blank` which will create
|
|
998
1021
|
|
999
1022
|
### Adding Fields on the Fly
|
1000
1023
|
|
1001
|
-
Rather than rendering multiple sets of fields ahead of time you may wish to add them only when a user clicks on an 'Add new address' button. Rails does not provide any
|
1024
|
+
Rather than rendering multiple sets of fields ahead of time you may wish to add them only when a user clicks on an 'Add new address' button. Rails does not provide any built-in support for this. When generating new sets of fields you must ensure the key of the associated array is unique - the current JavaScript date (milliseconds after the epoch) is a common choice.
|
data/guides/source/generators.md
CHANGED
@@ -8,6 +8,7 @@ After reading this guide, you will know:
|
|
8
8
|
* How to see which generators are available in your application.
|
9
9
|
* How to create a generator using templates.
|
10
10
|
* How Rails searches for generators before invoking them.
|
11
|
+
* How Rails internally generates Rails code from the templates.
|
11
12
|
* How to customize your scaffold by creating new generators.
|
12
13
|
* How to customize your scaffold by changing generator templates.
|
13
14
|
* How to use fallbacks to avoid overwriting a huge set of generators.
|
@@ -35,7 +36,7 @@ $ bin/rails generate helper --help
|
|
35
36
|
Creating Your First Generator
|
36
37
|
-----------------------------
|
37
38
|
|
38
|
-
Since Rails 3.0, generators are built on top of [Thor](https://github.com/erikhuda/thor). Thor provides powerful options parsing and a great API for manipulating files. For instance, let's build a generator that creates an initializer file named `initializer.rb` inside `config/initializers`.
|
39
|
+
Since Rails 3.0, generators are built on top of [Thor](https://github.com/erikhuda/thor). Thor provides powerful options for parsing and a great API for manipulating files. For instance, let's build a generator that creates an initializer file named `initializer.rb` inside `config/initializers`.
|
39
40
|
|
40
41
|
The first step is to create a file at `lib/generators/initializer_generator.rb` with the following content:
|
41
42
|
|
@@ -191,8 +192,6 @@ $ bin/rails generate scaffold User name:string
|
|
191
192
|
create test/controllers/users_controller_test.rb
|
192
193
|
invoke helper
|
193
194
|
create app/helpers/users_helper.rb
|
194
|
-
invoke test_unit
|
195
|
-
create test/helpers/users_helper_test.rb
|
196
195
|
invoke jbuilder
|
197
196
|
create app/views/users/index.json.jbuilder
|
198
197
|
create app/views/users/show.json.jbuilder
|
@@ -207,7 +206,7 @@ $ bin/rails generate scaffold User name:string
|
|
207
206
|
|
208
207
|
Looking at this output, it's easy to understand how generators work in Rails 3.0 and above. The scaffold generator doesn't actually generate anything, it just invokes others to do the work. This allows us to add/replace/remove any of those invocations. For instance, the scaffold generator invokes the scaffold_controller generator, which invokes erb, test_unit and helper generators. Since each generator has a single responsibility, they are easy to reuse, avoiding code duplication.
|
209
208
|
|
210
|
-
Our first customization on the workflow will be to stop generating
|
209
|
+
Our first customization on the workflow will be to stop generating stylesheet, JavaScript and test fixture files for scaffolds. We can achieve that by changing our configuration to the following:
|
211
210
|
|
212
211
|
```ruby
|
213
212
|
config.generators do |g|
|
@@ -219,7 +218,7 @@ config.generators do |g|
|
|
219
218
|
end
|
220
219
|
```
|
221
220
|
|
222
|
-
If we generate another resource with the scaffold generator, we can see that
|
221
|
+
If we generate another resource with the scaffold generator, we can see that stylesheet, JavaScript and fixture files are not created anymore. If you want to customize it further, for example to use DataMapper and RSpec instead of Active Record and TestUnit, it's just a matter of adding their gems to your application and configuring your generators.
|
223
222
|
|
224
223
|
To demonstrate this, we are going to create a new helper generator that simply adds some instance variable readers. First, we create a generator within the rails namespace, as this is where rails searches for generators used as hooks:
|
225
224
|
|
@@ -248,7 +247,7 @@ end
|
|
248
247
|
end
|
249
248
|
```
|
250
249
|
|
251
|
-
We can try out our new generator by creating a helper for
|
250
|
+
We can try out our new generator by creating a helper for products:
|
252
251
|
|
253
252
|
```bash
|
254
253
|
$ bin/rails generate my_helper products
|
@@ -279,10 +278,10 @@ end
|
|
279
278
|
and see it in action when invoking the generator:
|
280
279
|
|
281
280
|
```bash
|
282
|
-
$ bin/rails generate scaffold
|
281
|
+
$ bin/rails generate scaffold Article body:text
|
283
282
|
[...]
|
284
283
|
invoke my_helper
|
285
|
-
create app/helpers/
|
284
|
+
create app/helpers/articles_helper.rb
|
286
285
|
```
|
287
286
|
|
288
287
|
We can notice on the output that our new helper was invoked instead of the Rails default. However one thing is missing, which is tests for our new generator and to do that, we are going to reuse old helpers test generators.
|
@@ -342,6 +341,22 @@ end
|
|
342
341
|
|
343
342
|
If you generate another resource, you can see that we get exactly the same result! This is useful if you want to customize your scaffold templates and/or layout by just creating `edit.html.erb`, `index.html.erb` and so on inside `lib/templates/erb/scaffold`.
|
344
343
|
|
344
|
+
Scaffold templates in Rails frequently use ERB tags; these tags need to be
|
345
|
+
escaped so that the generated output is valid ERB code.
|
346
|
+
|
347
|
+
For example, the following escaped ERB tag would be needed in the template
|
348
|
+
(note the extra `%`)...
|
349
|
+
|
350
|
+
```ruby
|
351
|
+
<%%= stylesheet_include_tag :application %>
|
352
|
+
```
|
353
|
+
|
354
|
+
...to generate the following output:
|
355
|
+
|
356
|
+
```ruby
|
357
|
+
<%= stylesheet_include_tag :application %>
|
358
|
+
```
|
359
|
+
|
345
360
|
Adding Generators Fallbacks
|
346
361
|
---------------------------
|
347
362
|
|
@@ -387,8 +402,6 @@ $ bin/rails generate scaffold Comment body:text
|
|
387
402
|
create test/controllers/comments_controller_test.rb
|
388
403
|
invoke my_helper
|
389
404
|
create app/helpers/comments_helper.rb
|
390
|
-
invoke shoulda
|
391
|
-
create test/helpers/comments_helper_test.rb
|
392
405
|
invoke jbuilder
|
393
406
|
create app/views/comments/index.json.jbuilder
|
394
407
|
create app/views/comments/show.json.jbuilder
|
@@ -507,7 +520,7 @@ Replaces text inside a file.
|
|
507
520
|
gsub_file 'name_of_file.rb', 'method.to_be_replaced', 'method.the_replacing_code'
|
508
521
|
```
|
509
522
|
|
510
|
-
Regular Expressions can be used to make this method more precise. You can also use append_file and prepend_file in the same way to place code at the beginning and end of a file respectively.
|
523
|
+
Regular Expressions can be used to make this method more precise. You can also use `append_file` and `prepend_file` in the same way to place code at the beginning and end of a file respectively.
|
511
524
|
|
512
525
|
### `application`
|
513
526
|
|