rails 4.1.16 → 4.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +12 -10
- data/guides/CHANGELOG.md +15 -100
- data/guides/Rakefile +5 -3
- data/guides/assets/javascripts/guides.js +6 -0
- data/guides/assets/stylesheets/main.css +4 -1
- data/guides/bug_report_templates/action_controller_master.rb +1 -0
- data/guides/rails_guides/helpers.rb +1 -1
- data/guides/rails_guides/levenshtein.rb +29 -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 +5 -6
- data/guides/source/4_2_release_notes.md +850 -0
- data/guides/source/_license.html.erb +1 -1
- data/guides/source/_welcome.html.erb +2 -8
- data/guides/source/action_controller_overview.md +81 -7
- data/guides/source/action_mailer_basics.md +91 -28
- data/guides/source/action_view_overview.md +148 -130
- data/guides/source/active_job_basics.md +318 -0
- data/guides/source/active_model_basics.md +371 -17
- data/guides/source/active_record_basics.md +19 -18
- 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 +263 -265
- data/guides/source/active_record_validations.md +20 -11
- data/guides/source/active_support_core_extensions.md +159 -72
- data/guides/source/active_support_instrumentation.md +10 -7
- data/guides/source/api_documentation_guidelines.md +62 -16
- data/guides/source/asset_pipeline.md +258 -63
- data/guides/source/association_basics.md +81 -74
- data/guides/source/caching_with_rails.md +32 -7
- data/guides/source/command_line.md +52 -30
- data/guides/source/configuring.md +132 -29
- data/guides/source/constant_autoloading_and_reloading.md +1297 -0
- data/guides/source/contributing_to_ruby_on_rails.md +192 -112
- 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 +182 -182
- data/guides/source/form_helpers.md +79 -56
- data/guides/source/generators.md +24 -11
- data/guides/source/getting_started.md +337 -198
- data/guides/source/i18n.md +108 -65
- data/guides/source/index.html.erb +1 -0
- data/guides/source/initialization.md +108 -61
- data/guides/source/layout.html.erb +1 -4
- data/guides/source/layouts_and_rendering.md +27 -25
- 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 -4
- data/guides/source/routing.md +98 -72
- data/guides/source/ruby_on_rails_guides_guidelines.md +11 -12
- data/guides/source/security.md +38 -32
- data/guides/source/testing.md +188 -117
- data/guides/source/upgrading_ruby_on_rails.md +254 -28
- data/guides/source/working_with_javascript_in_rails.md +18 -16
- data/guides/w3c_validator.rb +2 -0
- metadata +40 -96
- 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/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
@@ -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
|
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
|
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
|
@@ -339,8 +338,8 @@ You can create, read, update and destroy items for a resource and these
|
|
339
338
|
operations are referred to as _CRUD_ operations.
|
340
339
|
|
341
340
|
Rails provides a `resources` method which can be used to declare a standard REST
|
342
|
-
resource.
|
343
|
-
|
341
|
+
resource. You need to add the _article resource_ to the
|
342
|
+
`config/routes.rb` as follows:
|
344
343
|
|
345
344
|
```ruby
|
346
345
|
Rails.application.routes.draw do
|
@@ -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:
|
@@ -676,7 +675,7 @@ class CreateArticles < ActiveRecord::Migration
|
|
676
675
|
t.string :title
|
677
676
|
t.text :text
|
678
677
|
|
679
|
-
t.timestamps
|
678
|
+
t.timestamps null: false
|
680
679
|
end
|
681
680
|
end
|
682
681
|
end
|
@@ -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,15 +811,29 @@ 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
|
805
835
|
interested in, passing in `params[:id]` to get the `:id` parameter from the
|
806
|
-
request. We also use an instance variable (prefixed
|
836
|
+
request. We also use an instance variable (prefixed with `@`) to hold a
|
807
837
|
reference to the article object. We do this because Rails will pass all instance
|
808
838
|
variables to the view.
|
809
839
|
|
@@ -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 with 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
|
@@ -1397,7 +1537,7 @@ class CreateComments < ActiveRecord::Migration
|
|
1397
1537
|
# this line adds an integer column called `article_id`.
|
1398
1538
|
t.references :article, index: true
|
1399
1539
|
|
1400
|
-
t.timestamps
|
1540
|
+
t.timestamps null: false
|
1401
1541
|
end
|
1402
1542
|
end
|
1403
1543
|
end
|
@@ -1487,7 +1627,7 @@ controller. Again, we'll use the same generator we used before:
|
|
1487
1627
|
$ bin/rails generate controller Comments
|
1488
1628
|
```
|
1489
1629
|
|
1490
|
-
This creates
|
1630
|
+
This creates five files and one empty directory:
|
1491
1631
|
|
1492
1632
|
| File/Directory | Purpose |
|
1493
1633
|
| -------------------------------------------- | ---------------------------------------- |
|
@@ -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
|
@@ -1910,7 +2049,7 @@ command-line utility:
|
|
1910
2049
|
in your web browser to explore the API documentation.
|
1911
2050
|
|
1912
2051
|
TIP: To be able to generate the Rails Guides locally with the `doc:guides` rake
|
1913
|
-
task you need to install the RedCloth
|
2052
|
+
task you need to install the RedCloth and Nokogiri gems. Add it to your `Gemfile` and run
|
1914
2053
|
`bundle install` and you're ready to go.
|
1915
2054
|
|
1916
2055
|
Configuration Gotchas
|