rails 4.1.16 → 4.2.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +3 -3
- data/guides/CHANGELOG.md +13 -102
- data/guides/Rakefile +2 -2
- 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 +2 -2
- data/guides/bug_report_templates/action_controller_master.rb +5 -2
- data/guides/bug_report_templates/active_record_master.rb +2 -0
- data/guides/rails_guides.rb +2 -2
- data/guides/rails_guides/helpers.rb +1 -1
- data/guides/rails_guides/levenshtein.rb +29 -21
- data/guides/rails_guides/markdown.rb +6 -7
- data/guides/rails_guides/markdown/renderer.rb +1 -1
- data/guides/source/2_3_release_notes.md +3 -3
- data/guides/source/3_0_release_notes.md +4 -4
- data/guides/source/3_1_release_notes.md +2 -2
- data/guides/source/3_2_release_notes.md +2 -2
- data/guides/source/4_1_release_notes.md +8 -9
- data/guides/source/4_2_release_notes.md +572 -0
- data/guides/source/_license.html.erb +1 -1
- data/guides/source/_welcome.html.erb +2 -8
- data/guides/source/action_controller_overview.md +79 -7
- data/guides/source/action_mailer_basics.md +36 -11
- data/guides/source/action_view_overview.md +138 -119
- data/guides/source/active_job_basics.md +253 -0
- data/guides/source/active_model_basics.md +23 -0
- data/guides/source/active_record_basics.md +16 -15
- data/guides/source/active_record_callbacks.md +12 -9
- data/guides/source/{migrations.md → active_record_migrations.md} +90 -217
- data/guides/source/active_record_postgresql.md +437 -0
- data/guides/source/active_record_querying.md +261 -261
- data/guides/source/active_record_validations.md +7 -7
- data/guides/source/active_support_core_extensions.md +105 -44
- data/guides/source/active_support_instrumentation.md +3 -2
- data/guides/source/api_documentation_guidelines.md +62 -16
- data/guides/source/asset_pipeline.md +58 -46
- data/guides/source/association_basics.md +47 -38
- data/guides/source/caching_with_rails.md +31 -6
- data/guides/source/command_line.md +56 -25
- data/guides/source/configuring.md +98 -19
- data/guides/source/contributing_to_ruby_on_rails.md +174 -111
- data/guides/source/credits.html.erb +1 -1
- data/guides/source/debugging_rails_applications.md +438 -284
- data/guides/source/development_dependencies_install.md +17 -4
- data/guides/source/documents.yaml +11 -7
- data/guides/source/engines.md +192 -203
- data/guides/source/form_helpers.md +54 -45
- data/guides/source/generators.md +20 -11
- data/guides/source/getting_started.md +330 -191
- data/guides/source/i18n.md +92 -62
- data/guides/source/index.html.erb +1 -0
- data/guides/source/initialization.md +108 -59
- data/guides/source/layout.html.erb +1 -4
- data/guides/source/layouts_and_rendering.md +24 -23
- data/guides/source/nested_model_forms.md +3 -3
- data/guides/source/plugins.md +26 -26
- data/guides/source/rails_application_templates.md +21 -3
- data/guides/source/rails_on_rack.md +1 -1
- data/guides/source/routing.md +97 -71
- data/guides/source/ruby_on_rails_guides_guidelines.md +10 -12
- data/guides/source/security.md +39 -33
- data/guides/source/testing.md +111 -108
- data/guides/source/upgrading_ruby_on_rails.md +131 -14
- data/guides/source/working_with_javascript_in_rails.md +18 -16
- data/guides/w3c_validator.rb +2 -0
- metadata +37 -94
- data/guides/bug_report_templates/generic_gem.rb +0 -15
- data/guides/bug_report_templates/generic_master.rb +0 -26
- 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.ru +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/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
|
|
@@ -146,7 +142,7 @@ Output:
|
|
146
142
|
<label for="age_adult">I'm over 21</label>
|
147
143
|
```
|
148
144
|
|
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"
|
145
|
+
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
146
|
|
151
147
|
NOTE: Always use labels for checkbox and radio buttons. They associate text with a specific option and,
|
152
148
|
by expanding the clickable region,
|
@@ -217,7 +213,7 @@ Dealing with Model Objects
|
|
217
213
|
|
218
214
|
### Model Object Helpers
|
219
215
|
|
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`.
|
216
|
+
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
217
|
|
222
218
|
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
219
|
|
@@ -239,7 +235,7 @@ Rails provides helpers for displaying the validation errors associated with a mo
|
|
239
235
|
|
240
236
|
### Binding a Form to an Object
|
241
237
|
|
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.
|
238
|
+
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
239
|
|
244
240
|
Assume we have a controller for dealing with articles `app/controllers/articles_controller.rb`:
|
245
241
|
|
@@ -264,7 +260,7 @@ There are a few things to note here:
|
|
264
260
|
* `@article` is the actual object being edited.
|
265
261
|
* 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
262
|
* 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
|
263
|
+
* Methods to create form controls are called **on** the form builder object `f`.
|
268
264
|
|
269
265
|
The resulting HTML is:
|
270
266
|
|
@@ -280,7 +276,7 @@ The name passed to `form_for` controls the key used in `params` to access the fo
|
|
280
276
|
|
281
277
|
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
278
|
|
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:
|
279
|
+
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
280
|
|
285
281
|
```erb
|
286
282
|
<%= form_for @person, url: {action: "create"} do |person_form| %>
|
@@ -350,7 +346,6 @@ form_for [:admin, :management, @article]
|
|
350
346
|
|
351
347
|
For more information on Rails' routing system and the associated conventions, please see the [routing guide](routing.html).
|
352
348
|
|
353
|
-
|
354
349
|
### How do forms with PATCH, PUT, or DELETE methods work?
|
355
350
|
|
356
351
|
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 +360,11 @@ output:
|
|
365
360
|
|
366
361
|
```html
|
367
362
|
<form accept-charset="UTF-8" action="/search" method="post">
|
368
|
-
<
|
369
|
-
|
370
|
-
|
371
|
-
<input name="authenticity_token" type="hidden" value="f755bb0ed134b76c432144748a6d4b7a7ddf2b71" />
|
372
|
-
</div>
|
363
|
+
<input name="_method" type="hidden" value="patch" />
|
364
|
+
<input name="utf8" type="hidden" value="✓" />
|
365
|
+
<input name="authenticity_token" type="hidden" value="f755bb0ed134b76c432144748a6d4b7a7ddf2b71" />
|
373
366
|
...
|
367
|
+
</form>
|
374
368
|
```
|
375
369
|
|
376
370
|
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 +429,19 @@ output:
|
|
435
429
|
|
436
430
|
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
431
|
|
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
|
432
|
+
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
433
|
|
440
434
|
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
435
|
|
442
436
|
You can add arbitrary attributes to the options using hashes:
|
443
437
|
|
444
438
|
```html+erb
|
445
|
-
<%= options_for_select(
|
439
|
+
<%= options_for_select(
|
440
|
+
[
|
441
|
+
['Lisbon', 1, { 'data-size' => '2.8 million' }],
|
442
|
+
['Madrid', 2, { 'data-size' => '3.2 million' }]
|
443
|
+
], 2
|
444
|
+
) %>
|
446
445
|
|
447
446
|
output:
|
448
447
|
|
@@ -474,11 +473,21 @@ As with other helpers, if you were to use the `select` helper on a form builder
|
|
474
473
|
<%= f.select(:city_id, ...) %>
|
475
474
|
```
|
476
475
|
|
477
|
-
|
476
|
+
You can also pass a block to `select` helper:
|
477
|
+
|
478
|
+
```erb
|
479
|
+
<%= f.select(:city_id) do %>
|
480
|
+
<% [['Lisbon', 1], ['Madrid', 2]].each do |c| -%>
|
481
|
+
<%= content_tag(:option, c.first, value: c.last) %>
|
482
|
+
<% end %>
|
483
|
+
<% end %>
|
484
|
+
```
|
485
|
+
|
486
|
+
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
487
|
|
479
488
|
### Option Tags from a Collection of Arbitrary Objects
|
480
489
|
|
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:
|
490
|
+
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
491
|
|
483
492
|
```erb
|
484
493
|
<% cities_array = City.all.map { |city| [city.name, city.id] } %>
|
@@ -525,7 +534,7 @@ Both of these families of helpers will create a series of select boxes for the d
|
|
525
534
|
|
526
535
|
### Barebones Helpers
|
527
536
|
|
528
|
-
The `select_*` family of helpers take as their first argument an instance of Date
|
537
|
+
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
538
|
|
530
539
|
```erb
|
531
540
|
<%= select_date Date.today, prefix: :start_date %>
|
@@ -539,7 +548,7 @@ outputs (with actual option values omitted for brevity)
|
|
539
548
|
<select id="start_date_day" name="start_date[day]"> ... </select>
|
540
549
|
```
|
541
550
|
|
542
|
-
The above inputs would result in `params[:start_date]` being a hash with keys `:year`, `:month`, `:day`. To get an actual Time or
|
551
|
+
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
552
|
|
544
553
|
```ruby
|
545
554
|
Date.civil(params[:start_date][:year].to_i, params[:start_date][:month].to_i, params[:start_date][:day].to_i)
|
@@ -584,7 +593,7 @@ NOTE: In many cases the built-in date pickers are clumsy as they do not aid the
|
|
584
593
|
|
585
594
|
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
595
|
|
587
|
-
The first parameter specifies which value should be selected and can either be an instance of a Date
|
596
|
+
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
597
|
|
589
598
|
```erb
|
590
599
|
<%= select_year(2009) %>
|
@@ -614,7 +623,7 @@ Rails provides the usual pair of helpers: the barebones `file_field_tag` and the
|
|
614
623
|
|
615
624
|
### What Gets Uploaded
|
616
625
|
|
617
|
-
The object in the `params` hash is an instance of a subclass of IO
|
626
|
+
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
627
|
|
619
628
|
```ruby
|
620
629
|
def upload
|
@@ -625,7 +634,7 @@ def upload
|
|
625
634
|
end
|
626
635
|
```
|
627
636
|
|
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](
|
637
|
+
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
638
|
|
630
639
|
NOTE: If the user has not selected a file the corresponding parameter will be an empty string.
|
631
640
|
|
@@ -636,7 +645,7 @@ Unlike other forms making an asynchronous file upload form is not as simple as p
|
|
636
645
|
Customizing Form Builders
|
637
646
|
-------------------------
|
638
647
|
|
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
|
648
|
+
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
649
|
|
641
650
|
```erb
|
642
651
|
<%= form_for @person do |f| %>
|
@@ -652,7 +661,7 @@ can be replaced with
|
|
652
661
|
<% end %>
|
653
662
|
```
|
654
663
|
|
655
|
-
by defining a LabellingFormBuilder class similar to the following:
|
664
|
+
by defining a `LabellingFormBuilder` class similar to the following:
|
656
665
|
|
657
666
|
```ruby
|
658
667
|
class LabellingFormBuilder < ActionView::Helpers::FormBuilder
|
@@ -670,7 +679,7 @@ The form builder used also determines what happens when you do
|
|
670
679
|
<%= render partial: f %>
|
671
680
|
```
|
672
681
|
|
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.
|
682
|
+
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
683
|
|
675
684
|
Understanding Parameter Naming Conventions
|
676
685
|
------------------------------------------
|
@@ -809,21 +818,21 @@ As a shortcut you can append [] to the name and omit the `:index` option. This i
|
|
809
818
|
|
810
819
|
produces exactly the same output as the previous example.
|
811
820
|
|
812
|
-
Forms to
|
821
|
+
Forms to External Resources
|
813
822
|
---------------------------
|
814
823
|
|
815
|
-
|
824
|
+
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
825
|
|
817
826
|
```erb
|
818
|
-
<%= form_tag 'http://farfar.away/form', authenticity_token: 'external_token'
|
827
|
+
<%= form_tag 'http://farfar.away/form', authenticity_token: 'external_token' do %>
|
819
828
|
Form contents
|
820
829
|
<% end %>
|
821
830
|
```
|
822
831
|
|
823
|
-
Sometimes when
|
832
|
+
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
833
|
|
825
834
|
```erb
|
826
|
-
<%= form_tag 'http://farfar.away/form', authenticity_token: false
|
835
|
+
<%= form_tag 'http://farfar.away/form', authenticity_token: false do %>
|
827
836
|
Form contents
|
828
837
|
<% end %>
|
829
838
|
```
|
@@ -847,7 +856,7 @@ Or if you don't want to render an `authenticity_token` field:
|
|
847
856
|
Building Complex Forms
|
848
857
|
----------------------
|
849
858
|
|
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.
|
859
|
+
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
860
|
|
852
861
|
### Configuring the Model
|
853
862
|
|
@@ -998,4 +1007,4 @@ As a convenience you can instead pass the symbol `:all_blank` which will create
|
|
998
1007
|
|
999
1008
|
### Adding Fields on the Fly
|
1000
1009
|
|
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
|
1010
|
+
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,18 @@ 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
|
+
Many scaffold templates in Rails are written in ERB tags which need to be escaped, so that the output is valid ERB code. For example,
|
345
|
+
|
346
|
+
```ruby
|
347
|
+
<%%= stylesheet_include_tag :application %>
|
348
|
+
```
|
349
|
+
|
350
|
+
when passed through the generator, would generate the following output.
|
351
|
+
|
352
|
+
```ruby
|
353
|
+
<%= stylesheet_include_tag :application %>
|
354
|
+
```
|
355
|
+
|
345
356
|
Adding Generators Fallbacks
|
346
357
|
---------------------------
|
347
358
|
|
@@ -387,8 +398,6 @@ $ bin/rails generate scaffold Comment body:text
|
|
387
398
|
create test/controllers/comments_controller_test.rb
|
388
399
|
invoke my_helper
|
389
400
|
create app/helpers/comments_helper.rb
|
390
|
-
invoke shoulda
|
391
|
-
create test/helpers/comments_helper_test.rb
|
392
401
|
invoke jbuilder
|
393
402
|
create app/views/comments/index.json.jbuilder
|
394
403
|
create app/views/comments/show.json.jbuilder
|
@@ -507,7 +516,7 @@ Replaces text inside a file.
|
|
507
516
|
gsub_file 'name_of_file.rb', 'method.to_be_replaced', 'method.the_replacing_code'
|
508
517
|
```
|
509
518
|
|
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.
|
519
|
+
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
520
|
|
512
521
|
### `application`
|
513
522
|
|
@@ -21,10 +21,10 @@ application from scratch. It does not assume that you have any prior experience
|
|
21
21
|
with Rails. However, to get the most out of it, you need to have some
|
22
22
|
prerequisites installed:
|
23
23
|
|
24
|
-
* The [Ruby](
|
25
|
-
* The [RubyGems](
|
24
|
+
* The [Ruby](https://www.ruby-lang.org/en/downloads) language version 1.9.3 or newer.
|
25
|
+
* The [RubyGems](https://rubygems.org) packaging system, which is installed with Ruby
|
26
26
|
versions 1.9 and later. To learn more about RubyGems, please read the [RubyGems Guides](http://guides.rubygems.org).
|
27
|
-
* A working installation of the [SQLite3 Database](
|
27
|
+
* A working installation of the [SQLite3 Database](https://www.sqlite.org).
|
28
28
|
|
29
29
|
Rails is a web application framework running on the Ruby programming language.
|
30
30
|
If you have no prior experience with Ruby, you will find a very steep learning
|
@@ -73,9 +73,8 @@ step needed to make this example application has been left out, so you can
|
|
73
73
|
literally follow along step by step.
|
74
74
|
|
75
75
|
By following along with this guide, you'll create a Rails project called
|
76
|
-
`blog`, a
|
77
|
-
|
78
|
-
make sure that you have Rails itself installed.
|
76
|
+
`blog`, a (very) simple weblog. Before you can start building the application,
|
77
|
+
you need to make sure that you have Rails itself installed.
|
79
78
|
|
80
79
|
TIP: The examples below use `$` to represent your terminal prompt in a UNIX-like OS,
|
81
80
|
though it may have been customized to appear differently. If you are using Windows,
|
@@ -88,7 +87,7 @@ Open up a command line prompt. On Mac OS X open Terminal.app, on Windows choose
|
|
88
87
|
dollar sign `$` should be run in the command line. Verify that you have a
|
89
88
|
current version of Ruby installed:
|
90
89
|
|
91
|
-
TIP
|
90
|
+
TIP: A number of tools exist to help you quickly install Ruby and Ruby
|
92
91
|
on Rails on your system. Windows users can use [Rails Installer](http://railsinstaller.org),
|
93
92
|
while Mac OS X users can use [Tokaido](https://github.com/tokaido/tokaidoapp).
|
94
93
|
|
@@ -98,11 +97,11 @@ ruby 2.0.0p353
|
|
98
97
|
```
|
99
98
|
|
100
99
|
If you don't have Ruby installed have a look at
|
101
|
-
[ruby-lang.org](https://www.ruby-lang.org/en/
|
100
|
+
[ruby-lang.org](https://www.ruby-lang.org/en/installation/) for possible ways to
|
102
101
|
install Ruby on your platform.
|
103
102
|
|
104
103
|
Many popular UNIX-like OSes ship with an acceptable version of SQLite3. Windows
|
105
|
-
users and others can find installation instructions at [the SQLite3 website](
|
104
|
+
users and others can find installation instructions at [the SQLite3 website](https://www.sqlite.org).
|
106
105
|
Verify that it is correctly installed and in your PATH:
|
107
106
|
|
108
107
|
```bash
|
@@ -121,10 +120,10 @@ To verify that you have everything installed correctly, you should be able to
|
|
121
120
|
run the following:
|
122
121
|
|
123
122
|
```bash
|
124
|
-
$
|
123
|
+
$ rails --version
|
125
124
|
```
|
126
125
|
|
127
|
-
If it says something like "Rails 4.
|
126
|
+
If it says something like "Rails 4.2.0", you are ready to continue.
|
128
127
|
|
129
128
|
### Creating the Blog Application
|
130
129
|
|
@@ -162,11 +161,11 @@ of the files and folders that Rails created by default:
|
|
162
161
|
| File/Folder | Purpose |
|
163
162
|
| ----------- | ------- |
|
164
163
|
|app/|Contains the controllers, models, views, helpers, mailers and assets for your application. You'll focus on this folder for the remainder of this guide.|
|
165
|
-
|bin/|Contains the rails script that starts your app and can contain other scripts you use to deploy or run your application.|
|
164
|
+
|bin/|Contains the rails script that starts your app and can contain other scripts you use to setup, deploy or run your application.|
|
166
165
|
|config/|Configure your application's routes, database, and more. This is covered in more detail in [Configuring Rails Applications](configuring.html).|
|
167
166
|
|config.ru|Rack configuration for Rack based servers used to start the application.|
|
168
167
|
|db/|Contains your current database schema, as well as the database migrations.|
|
169
|
-
|Gemfile<br>Gemfile.lock|These files allow you to specify what gem dependencies are needed for your Rails application. These files are used by the Bundler gem. For more information about Bundler, see [the Bundler website](http://
|
168
|
+
|Gemfile<br>Gemfile.lock|These files allow you to specify what gem dependencies are needed for your Rails application. These files are used by the Bundler gem. For more information about Bundler, see [the Bundler website](http://bundler.io).|
|
170
169
|
|lib/|Extended modules for your application.|
|
171
170
|
|log/|Application log files.|
|
172
171
|
|public/|The only folder seen by the world as-is. Contains static files and compiled assets.|
|
@@ -192,14 +191,15 @@ following in the `blog` directory:
|
|
192
191
|
$ bin/rails server
|
193
192
|
```
|
194
193
|
|
195
|
-
TIP: Compiling CoffeeScript
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
194
|
+
TIP: Compiling CoffeeScript and JavaScript asset compression requires you
|
195
|
+
have a JavaScript runtime available on your system, in the absence
|
196
|
+
of a runtime you will see an `execjs` error during asset compilation.
|
197
|
+
Usually Mac OS X and Windows come with a JavaScript runtime installed.
|
198
|
+
Rails adds the `therubyracer` gem to the generated `Gemfile` in a
|
199
|
+
commented line for new apps and you can uncomment if you need it.
|
200
|
+
`therubyrhino` is the recommended runtime for JRuby users and is added by
|
201
|
+
default to the `Gemfile` in apps generated under JRuby. You can investigate
|
202
|
+
all the supported runtimes at [ExecJS](https://github.com/sstephenson/execjs#readme).
|
203
203
|
|
204
204
|
This will fire up WEBrick, a web server distributed with Ruby by default. To see
|
205
205
|
your application in action, open a browser window and navigate to
|
@@ -257,8 +257,6 @@ invoke test_unit
|
|
257
257
|
create test/controllers/welcome_controller_test.rb
|
258
258
|
invoke helper
|
259
259
|
create app/helpers/welcome_helper.rb
|
260
|
-
invoke test_unit
|
261
|
-
create test/helpers/welcome_helper_test.rb
|
262
260
|
invoke assets
|
263
261
|
invoke coffee
|
264
262
|
create app/assets/javascripts/welcome.js.coffee
|
@@ -266,8 +264,9 @@ invoke scss
|
|
266
264
|
create app/assets/stylesheets/welcome.css.scss
|
267
265
|
```
|
268
266
|
|
269
|
-
Most important of these are of course the controller, located at
|
270
|
-
and the view, located at
|
267
|
+
Most important of these are of course the controller, located at
|
268
|
+
`app/controllers/welcome_controller.rb` and the view, located at
|
269
|
+
`app/views/welcome/index.html.erb`.
|
271
270
|
|
272
271
|
Open the `app/views/welcome/index.html.erb` file in your text editor. Delete all
|
273
272
|
of the existing code in the file, and replace it with the following single line
|
@@ -426,19 +425,22 @@ are generated in Rails they are empty by default, unless you tell it
|
|
426
425
|
your wanted actions during the generation process.
|
427
426
|
|
428
427
|
To manually define an action inside a controller, all you need to do is to
|
429
|
-
define a new method inside the controller.
|
430
|
-
|
431
|
-
class, define a `new` method like this:
|
428
|
+
define a new method inside the controller. Open
|
429
|
+
`app/controllers/articles_controller.rb` and inside the `ArticlesController`
|
430
|
+
class, define a `new` method so that the controller now looks like this:
|
432
431
|
|
433
432
|
```ruby
|
434
|
-
|
433
|
+
class ArticlesController < ApplicationController
|
434
|
+
def new
|
435
|
+
end
|
435
436
|
end
|
436
437
|
```
|
437
438
|
|
438
439
|
With the `new` method defined in `ArticlesController`, if you refresh
|
439
440
|
<http://localhost:3000/articles/new> you'll see another error:
|
440
441
|
|
441
|
-
![Template is missing for articles/new]
|
442
|
+
![Template is missing for articles/new]
|
443
|
+
(images/getting_started/template_is_missing_articles_new.png)
|
442
444
|
|
443
445
|
You're getting this error now because Rails expects plain actions like this one
|
444
446
|
to have views associated with them to display their information. With no view
|
@@ -447,9 +449,7 @@ available, Rails errors out.
|
|
447
449
|
In the above image, the bottom line has been truncated. Let's see what the full
|
448
450
|
thing looks like:
|
449
451
|
|
450
|
-
|
451
|
-
Missing template articles/new, application/new with {locale:[:en], formats:[:html], handlers:[:erb, :builder, :coffee]}. Searched in: * "/path/to/blog/app/views"
|
452
|
-
</blockquote>
|
452
|
+
>Missing template articles/new, application/new with {locale:[:en], formats:[:html], handlers:[:erb, :builder, :coffee]}. Searched in: * "/path/to/blog/app/views"
|
453
453
|
|
454
454
|
That's quite a lot of text! Let's quickly go through and understand what each
|
455
455
|
part of it does.
|
@@ -495,8 +495,8 @@ harmoniously! It's time to create the form for a new article.
|
|
495
495
|
|
496
496
|
### The first form
|
497
497
|
|
498
|
-
To create a form within this template, you will use a
|
499
|
-
builder
|
498
|
+
To create a form within this template, you will use a *form
|
499
|
+
builder*. The primary form builder for Rails is provided by a helper
|
500
500
|
method called `form_for`. To use this method, add this code into
|
501
501
|
`app/views/articles/new.html.erb`:
|
502
502
|
|
@@ -564,18 +564,18 @@ edit_article GET /articles/:id/edit(.:format) articles#edit
|
|
564
564
|
root GET / welcome#index
|
565
565
|
```
|
566
566
|
|
567
|
-
The `articles_path` helper tells Rails to point the form
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
`create` action of the current controller, the `ArticlesController`.
|
567
|
+
The `articles_path` helper tells Rails to point the form to the URI Pattern
|
568
|
+
associated with the `articles` prefix; and the form will (by default) send a
|
569
|
+
`POST` request to that route. This is associated with the `create` action of
|
570
|
+
the current controller, the `ArticlesController`.
|
572
571
|
|
573
572
|
With the form and its associated route defined, you will be able to fill in the
|
574
573
|
form and then click the submit button to begin the process of creating a new
|
575
574
|
article, so go ahead and do that. When you submit the form, you should see a
|
576
575
|
familiar error:
|
577
576
|
|
578
|
-
![Unknown action create for ArticlesController]
|
577
|
+
![Unknown action create for ArticlesController]
|
578
|
+
(images/getting_started/unknown_action_create_for_articles.png)
|
579
579
|
|
580
580
|
You now need to create the `create` action within the `ArticlesController` for
|
581
581
|
this to work.
|
@@ -584,7 +584,7 @@ this to work.
|
|
584
584
|
|
585
585
|
To make the "Unknown action" go away, you can define a `create` action within
|
586
586
|
the `ArticlesController` class in `app/controllers/articles_controller.rb`,
|
587
|
-
underneath the `new` action:
|
587
|
+
underneath the `new` action, as shown:
|
588
588
|
|
589
589
|
```ruby
|
590
590
|
class ArticlesController < ApplicationController
|
@@ -618,6 +618,8 @@ method returns an `ActiveSupport::HashWithIndifferentAccess` object, which
|
|
618
618
|
allows you to access the keys of the hash using either strings or symbols. In
|
619
619
|
this situation, the only parameters that matter are the ones from the form.
|
620
620
|
|
621
|
+
TIP: Ensure you have a firm grasp of the `params` method, as you'll use it fairly regularly. Let's consider an example URL: **http://www.example.com/?username=dhh&email=dhh@email.com**. In this URL, `params[:username]` would equal "dhh" and `params[:email]` would equal "dhh@email.com".
|
622
|
+
|
621
623
|
If you re-submit the form one more time you'll now no longer get the missing
|
622
624
|
template error. Instead, you'll see something that looks like the following:
|
623
625
|
|
@@ -631,10 +633,10 @@ parameters but nothing in particular is being done with them.
|
|
631
633
|
|
632
634
|
### Creating the Article model
|
633
635
|
|
634
|
-
Models in Rails use a singular name, and their corresponding database tables
|
635
|
-
a plural name. Rails provides a generator for creating models, which
|
636
|
-
|
637
|
-
|
636
|
+
Models in Rails use a singular name, and their corresponding database tables
|
637
|
+
use a plural name. Rails provides a generator for creating models, which most
|
638
|
+
Rails developers tend to use when creating new models. To create the new model,
|
639
|
+
run this command in your terminal:
|
638
640
|
|
639
641
|
```bash
|
640
642
|
$ bin/rails generate model Article title:string text:text
|
@@ -645,26 +647,23 @@ with a _title_ attribute of type string, and a _text_ attribute
|
|
645
647
|
of type text. Those attributes are automatically added to the `articles`
|
646
648
|
table in the database and mapped to the `Article` model.
|
647
649
|
|
648
|
-
Rails responded by creating a bunch of files. For
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
for creating the database structure, which is what we'll look at next.
|
650
|
+
Rails responded by creating a bunch of files. For now, we're only interested
|
651
|
+
in `app/models/article.rb` and `db/migrate/20140120191729_create_articles.rb`
|
652
|
+
(your name could be a bit different). The latter is responsible for creating
|
653
|
+
the database structure, which is what we'll look at next.
|
653
654
|
|
654
|
-
TIP: Active Record is smart enough to automatically map column names to
|
655
|
-
|
656
|
-
|
657
|
-
Record.
|
655
|
+
TIP: Active Record is smart enough to automatically map column names to model
|
656
|
+
attributes, which means you don't have to declare attributes inside Rails
|
657
|
+
models, as that will be done automatically by Active Record.
|
658
658
|
|
659
659
|
### Running a Migration
|
660
660
|
|
661
|
-
As we've just seen, `rails generate model` created a _database
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
order that they were created.
|
661
|
+
As we've just seen, `rails generate model` created a _database migration_ file
|
662
|
+
inside the `db/migrate` directory. Migrations are Ruby classes that are
|
663
|
+
designed to make it simple to create and modify database tables. Rails uses
|
664
|
+
rake commands to run migrations, and it's possible to undo a migration after
|
665
|
+
it's been applied to your database. Migration filenames include a timestamp to
|
666
|
+
ensure that they're processed in the order that they were created.
|
668
667
|
|
669
668
|
If you look in the `db/migrate/20140120191729_create_articles.rb` file (remember,
|
670
669
|
yours will have a slightly different name), here's what you'll find:
|
@@ -689,8 +688,8 @@ in case you want to reverse it later. When you run this migration it will create
|
|
689
688
|
an `articles` table with one string column and a text column. It also creates
|
690
689
|
two timestamp fields to allow Rails to track article creation and update times.
|
691
690
|
|
692
|
-
TIP: For more information about migrations, refer to [Rails Database
|
693
|
-
|
691
|
+
TIP: For more information about migrations, refer to [Rails Database Migrations]
|
692
|
+
(migrations.html).
|
694
693
|
|
695
694
|
At this point, you can use a rake command to run the migration:
|
696
695
|
|
@@ -732,26 +731,48 @@ end
|
|
732
731
|
|
733
732
|
Here's what's going on: every Rails model can be initialized with its
|
734
733
|
respective attributes, which are automatically mapped to the respective
|
735
|
-
database columns. In the first line we do just that
|
736
|
-
|
737
|
-
|
738
|
-
|
734
|
+
database columns. In the first line we do just that (remember that
|
735
|
+
`params[:article]` contains the attributes we're interested in). Then,
|
736
|
+
`@article.save` is responsible for saving the model in the database. Finally,
|
737
|
+
we redirect the user to the `show` action, which we'll define later.
|
738
|
+
|
739
|
+
TIP: You might be wondering why the `A` in `Article.new` is capitalized above, whereas most other references to articles in this guide have used lowercase. In this context, we are referring to the class named `Article` that is defined in `\models\article.rb`. Class names in Ruby must begin with a capital letter.
|
739
740
|
|
740
|
-
TIP: As we'll see later, `@article.save` returns a boolean indicating
|
741
|
-
|
741
|
+
TIP: As we'll see later, `@article.save` returns a boolean indicating whether
|
742
|
+
the article was saved or not.
|
742
743
|
|
743
|
-
If you now go to
|
744
|
-
|
745
|
-
article. Try it! You should get an error that looks like this:
|
744
|
+
If you now go to <http://localhost:3000/articles/new> you'll *almost* be able
|
745
|
+
to create an article. Try it! You should get an error that looks like this:
|
746
746
|
|
747
|
-
![Forbidden attributes for new article]
|
747
|
+
![Forbidden attributes for new article]
|
748
|
+
(images/getting_started/forbidden_attributes_for_new_article.png)
|
748
749
|
|
749
750
|
Rails has several security features that help you write secure applications,
|
750
|
-
and you're running into one of them now. This one is called
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
751
|
+
and you're running into one of them now. This one is called [strong parameters](action_controller_overview.html#strong-parameters),
|
752
|
+
which requires us to tell Rails exactly which parameters are allowed into our
|
753
|
+
controller actions.
|
754
|
+
|
755
|
+
Why do you have to bother? The ability to grab and automatically assign all
|
756
|
+
controller parameters to your model in one shot makes the programmer's job
|
757
|
+
easier, but this convenience also allows malicious use. What if a request to
|
758
|
+
the server was crafted to look like a new article form submit but also included
|
759
|
+
extra fields with values that violated your applications integrity? They would
|
760
|
+
be 'mass assigned' into your model and then into the database along with the
|
761
|
+
good stuff - potentially breaking your application or worse.
|
762
|
+
|
763
|
+
We have to whitelist our controller parameters to prevent wrongful mass
|
764
|
+
assignment. In this case, we want to both allow and require the `title` and
|
765
|
+
`text` parameters for valid use of `create`. The syntax for this introduces
|
766
|
+
`require` and `permit`. The change will involve one line in the `create` action:
|
767
|
+
|
768
|
+
```ruby
|
769
|
+
@article = Article.new(params.require(:article).permit(:title, :text))
|
770
|
+
```
|
771
|
+
|
772
|
+
This is often factored out into its own method so it can be reused by multiple
|
773
|
+
actions in the same controller, for example `create` and `update`. Above and
|
774
|
+
beyond mass assignment issues, the method is often made `private` to make sure
|
775
|
+
it can't be called outside its intended context. Here is the result:
|
755
776
|
|
756
777
|
```ruby
|
757
778
|
def create
|
@@ -767,20 +788,15 @@ private
|
|
767
788
|
end
|
768
789
|
```
|
769
790
|
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
TIP: Note that `def article_params` is private. This new approach prevents an
|
774
|
-
attacker from setting the model's attributes by manipulating the hash passed to
|
775
|
-
the model.
|
776
|
-
For more information, refer to
|
777
|
-
[this blog article about Strong Parameters](http://weblog.rubyonrails.org/2012/3/21/strong-parameters/).
|
791
|
+
TIP: For more information, refer to the reference above and
|
792
|
+
[this blog article about Strong Parameters]
|
793
|
+
(http://weblog.rubyonrails.org/2012/3/21/strong-parameters/).
|
778
794
|
|
779
795
|
### Showing Articles
|
780
796
|
|
781
|
-
If you submit the form again now, Rails will complain about not finding
|
782
|
-
|
783
|
-
|
797
|
+
If you submit the form again now, Rails will complain about not finding the
|
798
|
+
`show` action. That's not very useful though, so let's add the `show` action
|
799
|
+
before proceeding.
|
784
800
|
|
785
801
|
As we have seen in the output of `rake routes`, the route for `show` action is
|
786
802
|
as follows:
|
@@ -795,10 +811,24 @@ parameter, which in our case will be the id of the article.
|
|
795
811
|
As we did before, we need to add the `show` action in
|
796
812
|
`app/controllers/articles_controller.rb` and its respective view.
|
797
813
|
|
814
|
+
NOTE: A frequent practice is to place the standard CRUD actions in each
|
815
|
+
controller in the following order: `index`, `show`, `new`, `edit`, `create`, `update`
|
816
|
+
and `destroy`. You may use any order you choose, but keep in mind that these
|
817
|
+
are public methods; as mentioned earlier in this guide, they must be placed
|
818
|
+
before any private or protected method in the controller in order to work.
|
819
|
+
|
820
|
+
Given that, let's add the `show` action, as follows:
|
821
|
+
|
798
822
|
```ruby
|
799
|
-
|
800
|
-
|
801
|
-
|
823
|
+
class ArticlesController < ApplicationController
|
824
|
+
def show
|
825
|
+
@article = Article.find(params[:id])
|
826
|
+
end
|
827
|
+
|
828
|
+
def new
|
829
|
+
end
|
830
|
+
|
831
|
+
# snipped for brevity
|
802
832
|
```
|
803
833
|
|
804
834
|
A couple of things to note. We use `Article.find` to find the article we're
|
@@ -837,15 +867,27 @@ articles GET /articles(.:format) articles#index
|
|
837
867
|
```
|
838
868
|
|
839
869
|
Add the corresponding `index` action for that route inside the
|
840
|
-
`ArticlesController` in the `app/controllers/articles_controller.rb` file
|
870
|
+
`ArticlesController` in the `app/controllers/articles_controller.rb` file.
|
871
|
+
When we write an `index` action, the usual practice is to place it as the
|
872
|
+
first method in the controller. Let's do it:
|
841
873
|
|
842
874
|
```ruby
|
843
|
-
|
844
|
-
|
845
|
-
|
875
|
+
class ArticlesController < ApplicationController
|
876
|
+
def index
|
877
|
+
@articles = Article.all
|
878
|
+
end
|
879
|
+
|
880
|
+
def show
|
881
|
+
@article = Article.find(params[:id])
|
882
|
+
end
|
883
|
+
|
884
|
+
def new
|
885
|
+
end
|
886
|
+
|
887
|
+
# snipped for brevity
|
846
888
|
```
|
847
889
|
|
848
|
-
And then finally, add view for this action, located at
|
890
|
+
And then finally, add the view for this action, located at
|
849
891
|
`app/views/articles/index.html.erb`:
|
850
892
|
|
851
893
|
```html+erb
|
@@ -866,7 +908,7 @@ And then finally, add view for this action, located at
|
|
866
908
|
</table>
|
867
909
|
```
|
868
910
|
|
869
|
-
Now if you go to
|
911
|
+
Now if you go to <http://localhost:3000/articles> you will see a list of all the
|
870
912
|
articles that you have created.
|
871
913
|
|
872
914
|
### Adding links
|
@@ -895,8 +937,8 @@ Let's add links to the other views as well, starting with adding this
|
|
895
937
|
|
896
938
|
This link will allow you to bring up the form that lets you create a new article.
|
897
939
|
|
898
|
-
|
899
|
-
go back to the `index` action:
|
940
|
+
Now, add another link in `app/views/articles/new.html.erb`, underneath the
|
941
|
+
form, to go back to the `index` action:
|
900
942
|
|
901
943
|
```erb
|
902
944
|
<%= form_for :article, url: articles_path do |f| %>
|
@@ -906,7 +948,7 @@ go back to the `index` action:
|
|
906
948
|
<%= link_to 'Back', articles_path %>
|
907
949
|
```
|
908
950
|
|
909
|
-
Finally, add
|
951
|
+
Finally, add a link to the `app/views/articles/show.html.erb` template to
|
910
952
|
go back to the `index` action as well, so that people who are viewing a single
|
911
953
|
article can go back and view the whole list again:
|
912
954
|
|
@@ -924,9 +966,9 @@ article can go back and view the whole list again:
|
|
924
966
|
<%= link_to 'Back', articles_path %>
|
925
967
|
```
|
926
968
|
|
927
|
-
TIP: If you want to link to an action in the same controller, you don't
|
928
|
-
|
929
|
-
|
969
|
+
TIP: If you want to link to an action in the same controller, you don't need to
|
970
|
+
specify the `:controller` option, as Rails will use the current controller by
|
971
|
+
default.
|
930
972
|
|
931
973
|
TIP: In development mode (which is what you're working in by default), Rails
|
932
974
|
reloads your application with every browser request, so there's no need to stop
|
@@ -961,7 +1003,7 @@ These changes will ensure that all articles have a title that is at least five
|
|
961
1003
|
characters long. Rails can validate a variety of conditions in a model,
|
962
1004
|
including the presence or uniqueness of columns, their format, and the
|
963
1005
|
existence of associated objects. Validations are covered in detail in [Active
|
964
|
-
Record Validations](active_record_validations.html)
|
1006
|
+
Record Validations](active_record_validations.html).
|
965
1007
|
|
966
1008
|
With the validation now in place, when you call `@article.save` on an invalid
|
967
1009
|
article, it will return `false`. If you open
|
@@ -1010,17 +1052,21 @@ something went wrong. To do that, you'll modify
|
|
1010
1052
|
|
1011
1053
|
```html+erb
|
1012
1054
|
<%= form_for :article, url: articles_path do |f| %>
|
1055
|
+
|
1013
1056
|
<% if @article.errors.any? %>
|
1014
|
-
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
1018
|
-
|
1019
|
-
<
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1057
|
+
<div id="error_explanation">
|
1058
|
+
<h2>
|
1059
|
+
<%= pluralize(@article.errors.count, "error") %> prohibited
|
1060
|
+
this article from being saved:
|
1061
|
+
</h2>
|
1062
|
+
<ul>
|
1063
|
+
<% @article.errors.full_messages.each do |msg| %>
|
1064
|
+
<li><%= msg %></li>
|
1065
|
+
<% end %>
|
1066
|
+
</ul>
|
1067
|
+
</div>
|
1023
1068
|
<% end %>
|
1069
|
+
|
1024
1070
|
<p>
|
1025
1071
|
<%= f.label :title %><br>
|
1026
1072
|
<%= f.text_field :title %>
|
@@ -1034,6 +1080,7 @@ something went wrong. To do that, you'll modify
|
|
1034
1080
|
<p>
|
1035
1081
|
<%= f.submit %>
|
1036
1082
|
</p>
|
1083
|
+
|
1037
1084
|
<% end %>
|
1038
1085
|
|
1039
1086
|
<%= link_to 'Back', articles_path %>
|
@@ -1057,7 +1104,7 @@ standout.
|
|
1057
1104
|
|
1058
1105
|
Now you'll get a nice error message when saving an article without title when
|
1059
1106
|
you attempt to do just that on the new article form
|
1060
|
-
|
1107
|
+
<http://localhost:3000/articles/new>:
|
1061
1108
|
|
1062
1109
|
![Form With Errors](images/getting_started/form_with_errors.png)
|
1063
1110
|
|
@@ -1066,12 +1113,27 @@ you attempt to do just that on the new article form
|
|
1066
1113
|
We've covered the "CR" part of CRUD. Now let's focus on the "U" part, updating
|
1067
1114
|
articles.
|
1068
1115
|
|
1069
|
-
The first step we'll take is adding an `edit` action to the `ArticlesController
|
1116
|
+
The first step we'll take is adding an `edit` action to the `ArticlesController`,
|
1117
|
+
generally between the `new` and `create` actions, as shown:
|
1070
1118
|
|
1071
1119
|
```ruby
|
1120
|
+
def new
|
1121
|
+
@article = Article.new
|
1122
|
+
end
|
1123
|
+
|
1072
1124
|
def edit
|
1073
1125
|
@article = Article.find(params[:id])
|
1074
1126
|
end
|
1127
|
+
|
1128
|
+
def create
|
1129
|
+
@article = Article.new(article_params)
|
1130
|
+
|
1131
|
+
if @article.save
|
1132
|
+
redirect_to @article
|
1133
|
+
else
|
1134
|
+
render 'new'
|
1135
|
+
end
|
1136
|
+
end
|
1075
1137
|
```
|
1076
1138
|
|
1077
1139
|
The view will contain a form similar to the one we used when creating
|
@@ -1082,17 +1144,21 @@ it look as follows:
|
|
1082
1144
|
<h1>Editing article</h1>
|
1083
1145
|
|
1084
1146
|
<%= form_for :article, url: article_path(@article), method: :patch do |f| %>
|
1147
|
+
|
1085
1148
|
<% if @article.errors.any? %>
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1089
|
-
|
1090
|
-
|
1091
|
-
<
|
1092
|
-
|
1093
|
-
|
1094
|
-
|
1149
|
+
<div id="error_explanation">
|
1150
|
+
<h2>
|
1151
|
+
<%= pluralize(@article.errors.count, "error") %> prohibited
|
1152
|
+
this article from being saved:
|
1153
|
+
</h2>
|
1154
|
+
<ul>
|
1155
|
+
<% @article.errors.full_messages.each do |msg| %>
|
1156
|
+
<li><%= msg %></li>
|
1157
|
+
<% end %>
|
1158
|
+
</ul>
|
1159
|
+
</div>
|
1095
1160
|
<% end %>
|
1161
|
+
|
1096
1162
|
<p>
|
1097
1163
|
<%= f.label :title %><br>
|
1098
1164
|
<%= f.text_field :title %>
|
@@ -1106,6 +1172,7 @@ it look as follows:
|
|
1106
1172
|
<p>
|
1107
1173
|
<%= f.submit %>
|
1108
1174
|
</p>
|
1175
|
+
|
1109
1176
|
<% end %>
|
1110
1177
|
|
1111
1178
|
<%= link_to 'Back', articles_path %>
|
@@ -1120,14 +1187,26 @@ via the `PATCH` HTTP method which is the HTTP method you're expected to use to
|
|
1120
1187
|
|
1121
1188
|
The first parameter of `form_for` can be an object, say, `@article` which would
|
1122
1189
|
cause the helper to fill in the form with the fields of the object. Passing in a
|
1123
|
-
symbol (`:article`) with the same name as the instance variable (`@article`)
|
1124
|
-
automagically leads to the same behavior. This is what is happening here.
|
1125
|
-
can be found in [form_for documentation]
|
1190
|
+
symbol (`:article`) with the same name as the instance variable (`@article`)
|
1191
|
+
also automagically leads to the same behavior. This is what is happening here.
|
1192
|
+
More details can be found in [form_for documentation]
|
1193
|
+
(http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_for).
|
1126
1194
|
|
1127
|
-
Next we need to create the `update` action in
|
1128
|
-
`app/controllers/articles_controller.rb
|
1195
|
+
Next, we need to create the `update` action in
|
1196
|
+
`app/controllers/articles_controller.rb`.
|
1197
|
+
Add it between the `create` action and the `private` method:
|
1129
1198
|
|
1130
1199
|
```ruby
|
1200
|
+
def create
|
1201
|
+
@article = Article.new(article_params)
|
1202
|
+
|
1203
|
+
if @article.save
|
1204
|
+
redirect_to @article
|
1205
|
+
else
|
1206
|
+
render 'new'
|
1207
|
+
end
|
1208
|
+
end
|
1209
|
+
|
1131
1210
|
def update
|
1132
1211
|
@article = Article.find(params[:id])
|
1133
1212
|
|
@@ -1169,14 +1248,14 @@ it appear next to the "Show" link:
|
|
1169
1248
|
<th colspan="2"></th>
|
1170
1249
|
</tr>
|
1171
1250
|
|
1172
|
-
<% @articles.each do |article| %>
|
1173
|
-
|
1174
|
-
|
1175
|
-
|
1176
|
-
|
1177
|
-
|
1178
|
-
|
1179
|
-
<% end %>
|
1251
|
+
<% @articles.each do |article| %>
|
1252
|
+
<tr>
|
1253
|
+
<td><%= article.title %></td>
|
1254
|
+
<td><%= article.text %></td>
|
1255
|
+
<td><%= link_to 'Show', article_path(article) %></td>
|
1256
|
+
<td><%= link_to 'Edit', edit_article_path(article) %></td>
|
1257
|
+
</tr>
|
1258
|
+
<% end %>
|
1180
1259
|
</table>
|
1181
1260
|
```
|
1182
1261
|
|
@@ -1187,8 +1266,8 @@ bottom of the template:
|
|
1187
1266
|
```html+erb
|
1188
1267
|
...
|
1189
1268
|
|
1190
|
-
<%= link_to 'Back', articles_path %>
|
1191
|
-
|
1269
|
+
<%= link_to 'Back', articles_path %> |
|
1270
|
+
<%= link_to 'Edit', edit_article_path(@article) %>
|
1192
1271
|
```
|
1193
1272
|
|
1194
1273
|
And here's how our app looks so far:
|
@@ -1197,10 +1276,10 @@ And here's how our app looks so far:
|
|
1197
1276
|
|
1198
1277
|
### Using partials to clean up duplication in views
|
1199
1278
|
|
1200
|
-
Our `edit` page looks very similar to the `new` page
|
1201
|
-
both share the same code for displaying the form. Let's remove
|
1202
|
-
by using a view partial. By convention, partial files are
|
1203
|
-
underscore.
|
1279
|
+
Our `edit` page looks very similar to the `new` page; in fact, they
|
1280
|
+
both share the same code for displaying the form. Let's remove this
|
1281
|
+
duplication by using a view partial. By convention, partial files are
|
1282
|
+
prefixed by an underscore.
|
1204
1283
|
|
1205
1284
|
TIP: You can read more about partials in the
|
1206
1285
|
[Layouts and Rendering in Rails](layouts_and_rendering.html) guide.
|
@@ -1210,17 +1289,21 @@ content:
|
|
1210
1289
|
|
1211
1290
|
```html+erb
|
1212
1291
|
<%= form_for @article do |f| %>
|
1292
|
+
|
1213
1293
|
<% if @article.errors.any? %>
|
1214
|
-
|
1215
|
-
|
1216
|
-
|
1217
|
-
|
1218
|
-
|
1219
|
-
<
|
1220
|
-
|
1221
|
-
|
1222
|
-
|
1294
|
+
<div id="error_explanation">
|
1295
|
+
<h2>
|
1296
|
+
<%= pluralize(@article.errors.count, "error") %> prohibited
|
1297
|
+
this article from being saved:
|
1298
|
+
</h2>
|
1299
|
+
<ul>
|
1300
|
+
<% @article.errors.full_messages.each do |msg| %>
|
1301
|
+
<li><%= msg %></li>
|
1302
|
+
<% end %>
|
1303
|
+
</ul>
|
1304
|
+
</div>
|
1223
1305
|
<% end %>
|
1306
|
+
|
1224
1307
|
<p>
|
1225
1308
|
<%= f.label :title %><br>
|
1226
1309
|
<%= f.text_field :title %>
|
@@ -1234,6 +1317,7 @@ content:
|
|
1234
1317
|
<p>
|
1235
1318
|
<%= f.submit %>
|
1236
1319
|
</p>
|
1320
|
+
|
1237
1321
|
<% end %>
|
1238
1322
|
```
|
1239
1323
|
|
@@ -1242,8 +1326,8 @@ The reason we can use this shorter, simpler `form_for` declaration
|
|
1242
1326
|
to stand in for either of the other forms is that `@article` is a *resource*
|
1243
1327
|
corresponding to a full set of RESTful routes, and Rails is able to infer
|
1244
1328
|
which URI and method to use.
|
1245
|
-
For more information about this use of `form_for`, see
|
1246
|
-
|
1329
|
+
For more information about this use of `form_for`, see [Resource-oriented style]
|
1330
|
+
(http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_for-label-Resource-oriented+style).
|
1247
1331
|
|
1248
1332
|
Now, let's update the `app/views/articles/new.html.erb` view to use this new
|
1249
1333
|
partial, rewriting it completely:
|
@@ -1284,9 +1368,11 @@ people to craft malicious URLs like this:
|
|
1284
1368
|
<a href='http://example.com/articles/1/destroy'>look at this cat!</a>
|
1285
1369
|
```
|
1286
1370
|
|
1287
|
-
We use the `delete` method for destroying resources, and this route is mapped
|
1288
|
-
the `destroy` action inside `app/controllers/articles_controller.rb`, which
|
1289
|
-
doesn't exist yet
|
1371
|
+
We use the `delete` method for destroying resources, and this route is mapped
|
1372
|
+
to the `destroy` action inside `app/controllers/articles_controller.rb`, which
|
1373
|
+
doesn't exist yet. The `destroy` method is generally the last CRUD action in
|
1374
|
+
the controller, and like the other public CRUD actions, it must be placed
|
1375
|
+
before any `private` or `protected` methods. Let's add it:
|
1290
1376
|
|
1291
1377
|
```ruby
|
1292
1378
|
def destroy
|
@@ -1297,13 +1383,67 @@ def destroy
|
|
1297
1383
|
end
|
1298
1384
|
```
|
1299
1385
|
|
1386
|
+
The complete `ArticlesController` in the
|
1387
|
+
`app/controllers/articles_controller.rb` file should now look like this:
|
1388
|
+
|
1389
|
+
```ruby
|
1390
|
+
class ArticlesController < ApplicationController
|
1391
|
+
def index
|
1392
|
+
@articles = Article.all
|
1393
|
+
end
|
1394
|
+
|
1395
|
+
def show
|
1396
|
+
@article = Article.find(params[:id])
|
1397
|
+
end
|
1398
|
+
|
1399
|
+
def new
|
1400
|
+
@article = Article.new
|
1401
|
+
end
|
1402
|
+
|
1403
|
+
def edit
|
1404
|
+
@article = Article.find(params[:id])
|
1405
|
+
end
|
1406
|
+
|
1407
|
+
def create
|
1408
|
+
@article = Article.new(article_params)
|
1409
|
+
|
1410
|
+
if @article.save
|
1411
|
+
redirect_to @article
|
1412
|
+
else
|
1413
|
+
render 'new'
|
1414
|
+
end
|
1415
|
+
end
|
1416
|
+
|
1417
|
+
def update
|
1418
|
+
@article = Article.find(params[:id])
|
1419
|
+
|
1420
|
+
if @article.update(article_params)
|
1421
|
+
redirect_to @article
|
1422
|
+
else
|
1423
|
+
render 'edit'
|
1424
|
+
end
|
1425
|
+
end
|
1426
|
+
|
1427
|
+
def destroy
|
1428
|
+
@article = Article.find(params[:id])
|
1429
|
+
@article.destroy
|
1430
|
+
|
1431
|
+
redirect_to articles_path
|
1432
|
+
end
|
1433
|
+
|
1434
|
+
private
|
1435
|
+
def article_params
|
1436
|
+
params.require(:article).permit(:title, :text)
|
1437
|
+
end
|
1438
|
+
end
|
1439
|
+
```
|
1440
|
+
|
1300
1441
|
You can call `destroy` on Active Record objects when you want to delete
|
1301
1442
|
them from the database. Note that we don't need to add a view for this
|
1302
1443
|
action since we're redirecting to the `index` action.
|
1303
1444
|
|
1304
1445
|
Finally, add a 'Destroy' link to your `index` action template
|
1305
|
-
(`app/views/articles/index.html.erb`) to wrap everything
|
1306
|
-
together.
|
1446
|
+
(`app/views/articles/index.html.erb`) to wrap everything together.
|
1307
1447
|
|
1308
1448
|
```html+erb
|
1309
1449
|
<h1>Listing Articles</h1>
|
@@ -1315,16 +1455,17 @@ together.
|
|
1315
1455
|
<th colspan="3"></th>
|
1316
1456
|
</tr>
|
1317
1457
|
|
1318
|
-
<% @articles.each do |article| %>
|
1319
|
-
|
1320
|
-
|
1321
|
-
|
1322
|
-
|
1323
|
-
|
1324
|
-
|
1325
|
-
|
1326
|
-
|
1327
|
-
|
1458
|
+
<% @articles.each do |article| %>
|
1459
|
+
<tr>
|
1460
|
+
<td><%= article.title %></td>
|
1461
|
+
<td><%= article.text %></td>
|
1462
|
+
<td><%= link_to 'Show', article_path(article) %></td>
|
1463
|
+
<td><%= link_to 'Edit', edit_article_path(article) %></td>
|
1464
|
+
<td><%= link_to 'Destroy', article_path(article),
|
1465
|
+
method: :delete,
|
1466
|
+
data: { confirm: 'Are you sure?' } %></td>
|
1467
|
+
</tr>
|
1468
|
+
<% end %>
|
1328
1469
|
</table>
|
1329
1470
|
```
|
1330
1471
|
|
@@ -1342,9 +1483,8 @@ Without this file, the confirmation dialog box wouldn't appear.
|
|
1342
1483
|
Congratulations, you can now create, show, list, update and destroy
|
1343
1484
|
articles.
|
1344
1485
|
|
1345
|
-
TIP: In general, Rails encourages
|
1346
|
-
|
1347
|
-
For more information about routing, see
|
1486
|
+
TIP: In general, Rails encourages using resources objects instead of
|
1487
|
+
declaring routes manually. For more information about routing, see
|
1348
1488
|
[Rails Routing from the Outside In](routing.html).
|
1349
1489
|
|
1350
1490
|
Adding a Second Model
|
@@ -1495,7 +1635,6 @@ This creates six files and one empty directory:
|
|
1495
1635
|
| app/views/comments/ | Views of the controller are stored here |
|
1496
1636
|
| test/controllers/comments_controller_test.rb | The test for the controller |
|
1497
1637
|
| app/helpers/comments_helper.rb | A view helper file |
|
1498
|
-
| test/helpers/comments_helper_test.rb | The test for the helper |
|
1499
1638
|
| app/assets/javascripts/comment.js.coffee | CoffeeScript for the controller |
|
1500
1639
|
| app/assets/stylesheets/comment.css.scss | Cascading style sheet for the controller |
|
1501
1640
|
|
@@ -1534,8 +1673,8 @@ So first, we'll wire up the Article show template
|
|
1534
1673
|
</p>
|
1535
1674
|
<% end %>
|
1536
1675
|
|
1537
|
-
<%= link_to 'Back', articles_path %>
|
1538
|
-
|
1676
|
+
<%= link_to 'Back', articles_path %> |
|
1677
|
+
<%= link_to 'Edit', edit_article_path(@article) %>
|
1539
1678
|
```
|
1540
1679
|
|
1541
1680
|
This adds a form on the `Article` show page that creates a new comment by
|
@@ -1729,7 +1868,7 @@ Then you make the `app/views/articles/show.html.erb` look like the following:
|
|
1729
1868
|
<%= render @article.comments %>
|
1730
1869
|
|
1731
1870
|
<h2>Add a comment:</h2>
|
1732
|
-
<%= render
|
1871
|
+
<%= render 'comments/form' %>
|
1733
1872
|
|
1734
1873
|
<%= link_to 'Edit Article', edit_article_path(@article) %> |
|
1735
1874
|
<%= link_to 'Back to Articles', articles_path %>
|
@@ -1805,8 +1944,8 @@ database and send us back to the show action for the article.
|
|
1805
1944
|
|
1806
1945
|
### Deleting Associated Objects
|
1807
1946
|
|
1808
|
-
If you delete an article
|
1809
|
-
deleted
|
1947
|
+
If you delete an article, its associated comments will also need to be
|
1948
|
+
deleted, otherwise they would simply occupy space in the database. Rails allows
|
1810
1949
|
you to use the `dependent` option of an association to achieve this. Modify the
|
1811
1950
|
Article model, `app/models/article.rb`, as follows:
|
1812
1951
|
|
@@ -1823,21 +1962,21 @@ Security
|
|
1823
1962
|
|
1824
1963
|
### Basic Authentication
|
1825
1964
|
|
1826
|
-
If you were to publish your blog online,
|
1965
|
+
If you were to publish your blog online, anyone would be able to add, edit and
|
1827
1966
|
delete articles or delete comments.
|
1828
1967
|
|
1829
1968
|
Rails provides a very simple HTTP authentication system that will work nicely in
|
1830
1969
|
this situation.
|
1831
1970
|
|
1832
|
-
In the `ArticlesController` we need to have a way to block access to the
|
1833
|
-
actions if the person is not authenticated
|
1834
|
-
`http_basic_authenticate_with` method,
|
1971
|
+
In the `ArticlesController` we need to have a way to block access to the
|
1972
|
+
various actions if the person is not authenticated. Here we can use the Rails
|
1973
|
+
`http_basic_authenticate_with` method, which allows access to the requested
|
1835
1974
|
action if that method allows it.
|
1836
1975
|
|
1837
1976
|
To use the authentication system, we specify it at the top of our
|
1838
|
-
`ArticlesController
|
1839
|
-
every action
|
1840
|
-
|
1977
|
+
`ArticlesController` in `app/controllers/articles_controller.rb`. In our case,
|
1978
|
+
we want the user to be authenticated on every action except `index` and `show`,
|
1979
|
+
so we write that:
|
1841
1980
|
|
1842
1981
|
```ruby
|
1843
1982
|
class ArticlesController < ApplicationController
|
@@ -1861,14 +2000,14 @@ class CommentsController < ApplicationController
|
|
1861
2000
|
|
1862
2001
|
def create
|
1863
2002
|
@article = Article.find(params[:article_id])
|
1864
|
-
...
|
2003
|
+
# ...
|
1865
2004
|
end
|
1866
2005
|
|
1867
2006
|
# snipped for brevity
|
1868
2007
|
```
|
1869
2008
|
|
1870
2009
|
Now if you try to create a new article, you will be greeted with a basic HTTP
|
1871
|
-
Authentication challenge
|
2010
|
+
Authentication challenge:
|
1872
2011
|
|
1873
2012
|
![Basic HTTP Authentication Challenge](images/getting_started/challenge.png)
|
1874
2013
|
|
@@ -1883,7 +2022,7 @@ along with a number of others.
|
|
1883
2022
|
|
1884
2023
|
Security, especially in web applications, is a broad and detailed area. Security
|
1885
2024
|
in your Rails application is covered in more depth in
|
1886
|
-
|
2025
|
+
the [Ruby on Rails Security Guide](security.html).
|
1887
2026
|
|
1888
2027
|
|
1889
2028
|
What's Next?
|
@@ -1894,7 +2033,7 @@ update it and experiment on your own. But you don't have to do everything
|
|
1894
2033
|
without help. As you need assistance getting up and running with Rails, feel
|
1895
2034
|
free to consult these support resources:
|
1896
2035
|
|
1897
|
-
* The [Ruby on Rails
|
2036
|
+
* The [Ruby on Rails Guides](index.html)
|
1898
2037
|
* The [Ruby on Rails Tutorial](http://railstutorial.org/book)
|
1899
2038
|
* The [Ruby on Rails mailing list](http://groups.google.com/group/rubyonrails-talk)
|
1900
2039
|
* The [#rubyonrails](irc://irc.freenode.net/#rubyonrails) channel on irc.freenode.net
|