rails 4.1.4 → 4.2.11.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +12 -10
- data/guides/CHANGELOG.md +87 -15
- data/guides/Rakefile +21 -6
- data/guides/assets/images/getting_started/article_with_comments.png +0 -0
- data/guides/assets/javascripts/guides.js +6 -0
- data/guides/assets/stylesheets/main.css +4 -1
- data/guides/bug_report_templates/action_controller_gem.rb +3 -3
- data/guides/bug_report_templates/action_controller_master.rb +3 -2
- data/guides/bug_report_templates/active_record_gem.rb +1 -1
- data/guides/bug_report_templates/generic_gem.rb +15 -0
- data/guides/bug_report_templates/generic_master.rb +26 -0
- data/guides/rails_guides/helpers.rb +1 -1
- data/guides/rails_guides/levenshtein.rb +27 -21
- data/guides/rails_guides/markdown/renderer.rb +1 -1
- data/guides/rails_guides/markdown.rb +11 -7
- data/guides/rails_guides.rb +2 -2
- data/guides/source/2_2_release_notes.md +1 -1
- data/guides/source/2_3_release_notes.md +4 -4
- data/guides/source/3_0_release_notes.md +8 -8
- data/guides/source/3_1_release_notes.md +6 -3
- data/guides/source/3_2_release_notes.md +6 -3
- data/guides/source/4_0_release_notes.md +6 -3
- data/guides/source/4_1_release_notes.md +10 -11
- data/guides/source/4_2_release_notes.md +877 -0
- data/guides/source/_license.html.erb +1 -1
- data/guides/source/_welcome.html.erb +6 -8
- data/guides/source/action_controller_overview.md +28 -11
- data/guides/source/action_mailer_basics.md +97 -29
- data/guides/source/action_view_overview.md +142 -191
- data/guides/source/active_job_basics.md +339 -0
- data/guides/source/active_model_basics.md +371 -17
- data/guides/source/active_record_basics.md +25 -24
- data/guides/source/active_record_callbacks.md +12 -9
- data/guides/source/{migrations.md → active_record_migrations.md} +135 -226
- data/guides/source/active_record_postgresql.md +433 -0
- data/guides/source/active_record_querying.md +270 -262
- data/guides/source/active_record_validations.md +24 -14
- data/guides/source/active_support_core_extensions.md +115 -123
- data/guides/source/active_support_instrumentation.md +10 -18
- data/guides/source/api_documentation_guidelines.md +63 -17
- data/guides/source/asset_pipeline.md +266 -125
- data/guides/source/association_basics.md +96 -80
- data/guides/source/autoloading_and_reloading_constants.md +1311 -0
- data/guides/source/caching_with_rails.md +32 -7
- data/guides/source/command_line.md +52 -30
- data/guides/source/configuring.md +161 -33
- data/guides/source/contributing_to_ruby_on_rails.md +198 -114
- data/guides/source/credits.html.erb +2 -2
- data/guides/source/debugging_rails_applications.md +448 -294
- data/guides/source/development_dependencies_install.md +47 -36
- data/guides/source/documents.yaml +19 -7
- data/guides/source/engines.md +217 -196
- data/guides/source/form_helpers.md +79 -56
- data/guides/source/generators.md +24 -11
- data/guides/source/getting_started.md +361 -222
- data/guides/source/i18n.md +113 -69
- data/guides/source/index.html.erb +1 -0
- data/guides/source/initialization.md +110 -63
- data/guides/source/layout.html.erb +5 -11
- data/guides/source/layouts_and_rendering.md +26 -26
- data/guides/source/maintenance_policy.md +26 -4
- 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 +12 -10
- data/guides/source/routing.md +115 -75
- data/guides/source/ruby_on_rails_guides_guidelines.md +11 -12
- data/guides/source/security.md +41 -35
- data/guides/source/testing.md +199 -119
- data/guides/source/upgrading_ruby_on_rails.md +319 -32
- data/guides/source/working_with_javascript_in_rails.md +19 -17
- data/guides/w3c_validator.rb +2 -0
- metadata +42 -95
- data/guides/code/getting_started/Gemfile +0 -40
- data/guides/code/getting_started/Gemfile.lock +0 -125
- data/guides/code/getting_started/README.rdoc +0 -28
- data/guides/code/getting_started/Rakefile +0 -6
- data/guides/code/getting_started/app/assets/javascripts/application.js +0 -15
- data/guides/code/getting_started/app/assets/javascripts/comments.js.coffee +0 -3
- data/guides/code/getting_started/app/assets/javascripts/posts.js.coffee +0 -3
- data/guides/code/getting_started/app/assets/javascripts/welcome.js.coffee +0 -3
- data/guides/code/getting_started/app/assets/stylesheets/application.css +0 -13
- data/guides/code/getting_started/app/assets/stylesheets/comments.css.scss +0 -3
- data/guides/code/getting_started/app/assets/stylesheets/posts.css.scss +0 -3
- data/guides/code/getting_started/app/assets/stylesheets/welcome.css.scss +0 -3
- data/guides/code/getting_started/app/controllers/application_controller.rb +0 -5
- data/guides/code/getting_started/app/controllers/comments_controller.rb +0 -23
- data/guides/code/getting_started/app/controllers/posts_controller.rb +0 -53
- data/guides/code/getting_started/app/controllers/welcome_controller.rb +0 -4
- data/guides/code/getting_started/app/helpers/application_helper.rb +0 -2
- data/guides/code/getting_started/app/helpers/comments_helper.rb +0 -2
- data/guides/code/getting_started/app/helpers/posts_helper.rb +0 -2
- data/guides/code/getting_started/app/helpers/welcome_helper.rb +0 -2
- data/guides/code/getting_started/app/models/comment.rb +0 -3
- data/guides/code/getting_started/app/models/post.rb +0 -7
- data/guides/code/getting_started/app/views/comments/_comment.html.erb +0 -15
- data/guides/code/getting_started/app/views/comments/_form.html.erb +0 -13
- data/guides/code/getting_started/app/views/layouts/application.html.erb +0 -14
- data/guides/code/getting_started/app/views/posts/_form.html.erb +0 -27
- data/guides/code/getting_started/app/views/posts/edit.html.erb +0 -5
- data/guides/code/getting_started/app/views/posts/index.html.erb +0 -21
- data/guides/code/getting_started/app/views/posts/new.html.erb +0 -5
- data/guides/code/getting_started/app/views/posts/show.html.erb +0 -18
- data/guides/code/getting_started/app/views/welcome/index.html.erb +0 -4
- data/guides/code/getting_started/bin/bundle +0 -4
- data/guides/code/getting_started/bin/rails +0 -4
- data/guides/code/getting_started/bin/rake +0 -4
- data/guides/code/getting_started/config/application.rb +0 -18
- data/guides/code/getting_started/config/boot.rb +0 -4
- data/guides/code/getting_started/config/database.yml +0 -25
- data/guides/code/getting_started/config/environment.rb +0 -5
- data/guides/code/getting_started/config/environments/development.rb +0 -30
- data/guides/code/getting_started/config/environments/production.rb +0 -80
- data/guides/code/getting_started/config/environments/test.rb +0 -36
- data/guides/code/getting_started/config/initializers/backtrace_silencers.rb +0 -7
- data/guides/code/getting_started/config/initializers/filter_parameter_logging.rb +0 -4
- data/guides/code/getting_started/config/initializers/inflections.rb +0 -16
- data/guides/code/getting_started/config/initializers/locale.rb +0 -9
- data/guides/code/getting_started/config/initializers/mime_types.rb +0 -5
- data/guides/code/getting_started/config/initializers/secret_token.rb +0 -12
- data/guides/code/getting_started/config/initializers/session_store.rb +0 -3
- data/guides/code/getting_started/config/initializers/wrap_parameters.rb +0 -14
- data/guides/code/getting_started/config/locales/en.yml +0 -23
- data/guides/code/getting_started/config/routes.rb +0 -7
- data/guides/code/getting_started/config.ru +0 -4
- data/guides/code/getting_started/db/migrate/20130122042648_create_posts.rb +0 -10
- data/guides/code/getting_started/db/migrate/20130122045842_create_comments.rb +0 -11
- data/guides/code/getting_started/db/schema.rb +0 -33
- data/guides/code/getting_started/db/seeds.rb +0 -7
- data/guides/code/getting_started/public/404.html +0 -60
- data/guides/code/getting_started/public/422.html +0 -60
- data/guides/code/getting_started/public/500.html +0 -59
- data/guides/code/getting_started/public/favicon.ico +0 -0
- data/guides/code/getting_started/public/robots.txt +0 -5
- data/guides/code/getting_started/test/controllers/comments_controller_test.rb +0 -7
- data/guides/code/getting_started/test/controllers/posts_controller_test.rb +0 -7
- data/guides/code/getting_started/test/controllers/welcome_controller_test.rb +0 -9
- data/guides/code/getting_started/test/fixtures/comments.yml +0 -11
- data/guides/code/getting_started/test/fixtures/posts.yml +0 -9
- data/guides/code/getting_started/test/helpers/comments_helper_test.rb +0 -4
- data/guides/code/getting_started/test/helpers/posts_helper_test.rb +0 -4
- data/guides/code/getting_started/test/helpers/welcome_helper_test.rb +0 -4
- data/guides/code/getting_started/test/models/comment_test.rb +0 -7
- data/guides/code/getting_started/test/models/post_test.rb +0 -7
- data/guides/code/getting_started/test/test_helper.rb +0 -12
@@ -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
|
@@ -70,13 +70,11 @@ Creating a New Rails Project
|
|
70
70
|
|
71
71
|
The best way to use this guide is to follow each step as it happens, no code or
|
72
72
|
step needed to make this example application has been left out, so you can
|
73
|
-
literally follow along step by step.
|
74
|
-
[here](https://github.com/rails/docrails/tree/master/guides/code/getting_started).
|
73
|
+
literally follow along step by step.
|
75
74
|
|
76
75
|
By following along with this guide, you'll create a Rails project called
|
77
|
-
`blog`, a
|
78
|
-
|
79
|
-
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.
|
80
78
|
|
81
79
|
TIP: The examples below use `$` to represent your terminal prompt in a UNIX-like OS,
|
82
80
|
though it may have been customized to appear differently. If you are using Windows,
|
@@ -89,7 +87,7 @@ Open up a command line prompt. On Mac OS X open Terminal.app, on Windows choose
|
|
89
87
|
dollar sign `$` should be run in the command line. Verify that you have a
|
90
88
|
current version of Ruby installed:
|
91
89
|
|
92
|
-
TIP
|
90
|
+
TIP: A number of tools exist to help you quickly install Ruby and Ruby
|
93
91
|
on Rails on your system. Windows users can use [Rails Installer](http://railsinstaller.org),
|
94
92
|
while Mac OS X users can use [Tokaido](https://github.com/tokaido/tokaidoapp).
|
95
93
|
|
@@ -99,11 +97,11 @@ ruby 2.0.0p353
|
|
99
97
|
```
|
100
98
|
|
101
99
|
If you don't have Ruby installed have a look at
|
102
|
-
[ruby-lang.org](https://www.ruby-lang.org/en/
|
100
|
+
[ruby-lang.org](https://www.ruby-lang.org/en/installation/) for possible ways to
|
103
101
|
install Ruby on your platform.
|
104
102
|
|
105
103
|
Many popular UNIX-like OSes ship with an acceptable version of SQLite3. Windows
|
106
|
-
users and others can find installation instructions at
|
104
|
+
users and others can find installation instructions at the [SQLite3 website](https://www.sqlite.org).
|
107
105
|
Verify that it is correctly installed and in your PATH:
|
108
106
|
|
109
107
|
```bash
|
@@ -122,10 +120,10 @@ To verify that you have everything installed correctly, you should be able to
|
|
122
120
|
run the following:
|
123
121
|
|
124
122
|
```bash
|
125
|
-
$
|
123
|
+
$ rails --version
|
126
124
|
```
|
127
125
|
|
128
|
-
If it says something like "Rails 4.
|
126
|
+
If it says something like "Rails 4.2.1", you are ready to continue.
|
129
127
|
|
130
128
|
### Creating the Blog Application
|
131
129
|
|
@@ -163,11 +161,11 @@ of the files and folders that Rails created by default:
|
|
163
161
|
| File/Folder | Purpose |
|
164
162
|
| ----------- | ------- |
|
165
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.|
|
166
|
-
|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.|
|
167
165
|
|config/|Configure your application's routes, database, and more. This is covered in more detail in [Configuring Rails Applications](configuring.html).|
|
168
166
|
|config.ru|Rack configuration for Rack based servers used to start the application.|
|
169
167
|
|db/|Contains your current database schema, as well as the database migrations.|
|
170
|
-
|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).|
|
171
169
|
|lib/|Extended modules for your application.|
|
172
170
|
|log/|Application log files.|
|
173
171
|
|public/|The only folder seen by the world as-is. Contains static files and compiled assets.|
|
@@ -193,14 +191,18 @@ following in the `blog` directory:
|
|
193
191
|
$ bin/rails server
|
194
192
|
```
|
195
193
|
|
196
|
-
TIP:
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
194
|
+
TIP: If you are using Windows, you have to pass the scripts under the `bin`
|
195
|
+
folder directly to the Ruby interpreter e.g. `ruby bin\rails server`.
|
196
|
+
|
197
|
+
TIP: Compiling CoffeeScript and JavaScript asset compression requires you
|
198
|
+
have a JavaScript runtime available on your system, in the absence
|
199
|
+
of a runtime you will see an `execjs` error during asset compilation.
|
200
|
+
Usually Mac OS X and Windows come with a JavaScript runtime installed.
|
201
|
+
Rails adds the `therubyracer` gem to the generated `Gemfile` in a
|
202
|
+
commented line for new apps and you can uncomment if you need it.
|
203
|
+
`therubyrhino` is the recommended runtime for JRuby users and is added by
|
204
|
+
default to the `Gemfile` in apps generated under JRuby. You can investigate
|
205
|
+
all the supported runtimes at [ExecJS](https://github.com/rails/execjs#readme).
|
204
206
|
|
205
207
|
This will fire up WEBrick, a web server distributed with Ruby by default. To see
|
206
208
|
your application in action, open a browser window and navigate to
|
@@ -258,8 +260,6 @@ invoke test_unit
|
|
258
260
|
create test/controllers/welcome_controller_test.rb
|
259
261
|
invoke helper
|
260
262
|
create app/helpers/welcome_helper.rb
|
261
|
-
invoke test_unit
|
262
|
-
create test/helpers/welcome_helper_test.rb
|
263
263
|
invoke assets
|
264
264
|
invoke coffee
|
265
265
|
create app/assets/javascripts/welcome.js.coffee
|
@@ -267,8 +267,9 @@ invoke scss
|
|
267
267
|
create app/assets/stylesheets/welcome.css.scss
|
268
268
|
```
|
269
269
|
|
270
|
-
Most important of these are of course the controller, located at
|
271
|
-
and the view, located at
|
270
|
+
Most important of these are of course the controller, located at
|
271
|
+
`app/controllers/welcome_controller.rb` and the view, located at
|
272
|
+
`app/views/welcome/index.html.erb`.
|
272
273
|
|
273
274
|
Open the `app/views/welcome/index.html.erb` file in your text editor. Delete all
|
274
275
|
of the existing code in the file, and replace it with the following single line
|
@@ -317,9 +318,9 @@ root 'welcome#index'
|
|
317
318
|
application to the welcome controller's index action and `get 'welcome/index'`
|
318
319
|
tells Rails to map requests to <http://localhost:3000/welcome/index> to the
|
319
320
|
welcome controller's index action. This was created earlier when you ran the
|
320
|
-
controller generator (`rails generate controller welcome index`).
|
321
|
+
controller generator (`bin/rails generate controller welcome index`).
|
321
322
|
|
322
|
-
Launch the web server again if you stopped it to generate the controller (`rails
|
323
|
+
Launch the web server again if you stopped it to generate the controller (`bin/rails
|
323
324
|
server`) and navigate to <http://localhost:3000> in your browser. You'll see the
|
324
325
|
"Hello, Rails!" message you put into `app/views/welcome/index.html.erb`,
|
325
326
|
indicating that this new route is indeed going to `WelcomeController`'s `index`
|
@@ -340,11 +341,11 @@ You can create, read, update and destroy items for a resource and these
|
|
340
341
|
operations are referred to as _CRUD_ operations.
|
341
342
|
|
342
343
|
Rails provides a `resources` method which can be used to declare a standard REST
|
343
|
-
resource.
|
344
|
-
|
344
|
+
resource. You need to add the _article resource_ to the
|
345
|
+
`config/routes.rb` as follows:
|
345
346
|
|
346
347
|
```ruby
|
347
|
-
|
348
|
+
Rails.application.routes.draw do
|
348
349
|
|
349
350
|
resources :articles
|
350
351
|
|
@@ -352,7 +353,7 @@ Blog::Application.routes.draw do
|
|
352
353
|
end
|
353
354
|
```
|
354
355
|
|
355
|
-
If you run `rake routes`, you'll see that it has defined routes for all the
|
356
|
+
If you run `bin/rake routes`, you'll see that it has defined routes for all the
|
356
357
|
standard RESTful actions. The meaning of the prefix column (and other columns)
|
357
358
|
will be seen later, but for now notice that Rails has inferred the
|
358
359
|
singular form `article` and makes meaningful use of the distinction.
|
@@ -396,7 +397,7 @@ a controller called `ArticlesController`. You can do this by running this
|
|
396
397
|
command:
|
397
398
|
|
398
399
|
```bash
|
399
|
-
$ bin/rails
|
400
|
+
$ bin/rails generate controller articles
|
400
401
|
```
|
401
402
|
|
402
403
|
If you open up the newly generated `app/controllers/articles_controller.rb`
|
@@ -427,19 +428,22 @@ are generated in Rails they are empty by default, unless you tell it
|
|
427
428
|
your wanted actions during the generation process.
|
428
429
|
|
429
430
|
To manually define an action inside a controller, all you need to do is to
|
430
|
-
define a new method inside the controller.
|
431
|
-
|
432
|
-
class, define a `new` method like this:
|
431
|
+
define a new method inside the controller. Open
|
432
|
+
`app/controllers/articles_controller.rb` and inside the `ArticlesController`
|
433
|
+
class, define a `new` method so that the controller now looks like this:
|
433
434
|
|
434
435
|
```ruby
|
435
|
-
|
436
|
+
class ArticlesController < ApplicationController
|
437
|
+
def new
|
438
|
+
end
|
436
439
|
end
|
437
440
|
```
|
438
441
|
|
439
442
|
With the `new` method defined in `ArticlesController`, if you refresh
|
440
443
|
<http://localhost:3000/articles/new> you'll see another error:
|
441
444
|
|
442
|
-
![Template is missing for articles/new]
|
445
|
+
![Template is missing for articles/new]
|
446
|
+
(images/getting_started/template_is_missing_articles_new.png)
|
443
447
|
|
444
448
|
You're getting this error now because Rails expects plain actions like this one
|
445
449
|
to have views associated with them to display their information. With no view
|
@@ -448,9 +452,7 @@ available, Rails errors out.
|
|
448
452
|
In the above image, the bottom line has been truncated. Let's see what the full
|
449
453
|
thing looks like:
|
450
454
|
|
451
|
-
|
452
|
-
Missing template articles/new, application/new with {locale:[:en], formats:[:html], handlers:[:erb, :builder, :coffee]}. Searched in: * "/path/to/blog/app/views"
|
453
|
-
</blockquote>
|
455
|
+
>Missing template articles/new, application/new with {locale:[:en], formats:[:html], handlers:[:erb, :builder, :coffee]}. Searched in: * "/path/to/blog/app/views"
|
454
456
|
|
455
457
|
That's quite a lot of text! Let's quickly go through and understand what each
|
456
458
|
part of it does.
|
@@ -496,8 +498,8 @@ harmoniously! It's time to create the form for a new article.
|
|
496
498
|
|
497
499
|
### The first form
|
498
500
|
|
499
|
-
To create a form within this template, you will use a
|
500
|
-
builder
|
501
|
+
To create a form within this template, you will use a *form
|
502
|
+
builder*. The primary form builder for Rails is provided by a helper
|
501
503
|
method called `form_for`. To use this method, add this code into
|
502
504
|
`app/views/articles/new.html.erb`:
|
503
505
|
|
@@ -549,7 +551,7 @@ this:
|
|
549
551
|
|
550
552
|
In this example, the `articles_path` helper is passed to the `:url` option.
|
551
553
|
To see what Rails will do with this, we look back at the output of
|
552
|
-
`rake routes`:
|
554
|
+
`bin/rake routes`:
|
553
555
|
|
554
556
|
```bash
|
555
557
|
$ bin/rake routes
|
@@ -565,18 +567,18 @@ edit_article GET /articles/:id/edit(.:format) articles#edit
|
|
565
567
|
root GET / welcome#index
|
566
568
|
```
|
567
569
|
|
568
|
-
The `articles_path` helper tells Rails to point the form
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
`create` action of the current controller, the `ArticlesController`.
|
570
|
+
The `articles_path` helper tells Rails to point the form to the URI Pattern
|
571
|
+
associated with the `articles` prefix; and the form will (by default) send a
|
572
|
+
`POST` request to that route. This is associated with the `create` action of
|
573
|
+
the current controller, the `ArticlesController`.
|
573
574
|
|
574
575
|
With the form and its associated route defined, you will be able to fill in the
|
575
576
|
form and then click the submit button to begin the process of creating a new
|
576
577
|
article, so go ahead and do that. When you submit the form, you should see a
|
577
578
|
familiar error:
|
578
579
|
|
579
|
-
![Unknown action create for ArticlesController]
|
580
|
+
![Unknown action create for ArticlesController]
|
581
|
+
(images/getting_started/unknown_action_create_for_articles.png)
|
580
582
|
|
581
583
|
You now need to create the `create` action within the `ArticlesController` for
|
582
584
|
this to work.
|
@@ -585,7 +587,7 @@ this to work.
|
|
585
587
|
|
586
588
|
To make the "Unknown action" go away, you can define a `create` action within
|
587
589
|
the `ArticlesController` class in `app/controllers/articles_controller.rb`,
|
588
|
-
underneath the `new` action:
|
590
|
+
underneath the `new` action, as shown:
|
589
591
|
|
590
592
|
```ruby
|
591
593
|
class ArticlesController < ApplicationController
|
@@ -619,6 +621,8 @@ method returns an `ActiveSupport::HashWithIndifferentAccess` object, which
|
|
619
621
|
allows you to access the keys of the hash using either strings or symbols. In
|
620
622
|
this situation, the only parameters that matter are the ones from the form.
|
621
623
|
|
624
|
+
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".
|
625
|
+
|
622
626
|
If you re-submit the form one more time you'll now no longer get the missing
|
623
627
|
template error. Instead, you'll see something that looks like the following:
|
624
628
|
|
@@ -632,10 +636,10 @@ parameters but nothing in particular is being done with them.
|
|
632
636
|
|
633
637
|
### Creating the Article model
|
634
638
|
|
635
|
-
Models in Rails use a singular name, and their corresponding database tables
|
636
|
-
a plural name. Rails provides a generator for creating models, which
|
637
|
-
|
638
|
-
|
639
|
+
Models in Rails use a singular name, and their corresponding database tables
|
640
|
+
use a plural name. Rails provides a generator for creating models, which most
|
641
|
+
Rails developers tend to use when creating new models. To create the new model,
|
642
|
+
run this command in your terminal:
|
639
643
|
|
640
644
|
```bash
|
641
645
|
$ bin/rails generate model Article title:string text:text
|
@@ -646,26 +650,23 @@ with a _title_ attribute of type string, and a _text_ attribute
|
|
646
650
|
of type text. Those attributes are automatically added to the `articles`
|
647
651
|
table in the database and mapped to the `Article` model.
|
648
652
|
|
649
|
-
Rails responded by creating a bunch of files. For
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
for creating the database structure, which is what we'll look at next.
|
653
|
+
Rails responded by creating a bunch of files. For now, we're only interested
|
654
|
+
in `app/models/article.rb` and `db/migrate/20140120191729_create_articles.rb`
|
655
|
+
(your name could be a bit different). The latter is responsible for creating
|
656
|
+
the database structure, which is what we'll look at next.
|
654
657
|
|
655
|
-
TIP: Active Record is smart enough to automatically map column names to
|
656
|
-
|
657
|
-
|
658
|
-
Record.
|
658
|
+
TIP: Active Record is smart enough to automatically map column names to model
|
659
|
+
attributes, which means you don't have to declare attributes inside Rails
|
660
|
+
models, as that will be done automatically by Active Record.
|
659
661
|
|
660
662
|
### Running a Migration
|
661
663
|
|
662
|
-
As we've just seen, `rails generate model` created a _database
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
order that they were created.
|
664
|
+
As we've just seen, `bin/rails generate model` created a _database migration_ file
|
665
|
+
inside the `db/migrate` directory. Migrations are Ruby classes that are
|
666
|
+
designed to make it simple to create and modify database tables. Rails uses
|
667
|
+
rake commands to run migrations, and it's possible to undo a migration after
|
668
|
+
it's been applied to your database. Migration filenames include a timestamp to
|
669
|
+
ensure that they're processed in the order that they were created.
|
669
670
|
|
670
671
|
If you look in the `db/migrate/20140120191729_create_articles.rb` file (remember,
|
671
672
|
yours will have a slightly different name), here's what you'll find:
|
@@ -677,7 +678,7 @@ class CreateArticles < ActiveRecord::Migration
|
|
677
678
|
t.string :title
|
678
679
|
t.text :text
|
679
680
|
|
680
|
-
t.timestamps
|
681
|
+
t.timestamps null: false
|
681
682
|
end
|
682
683
|
end
|
683
684
|
end
|
@@ -690,8 +691,8 @@ in case you want to reverse it later. When you run this migration it will create
|
|
690
691
|
an `articles` table with one string column and a text column. It also creates
|
691
692
|
two timestamp fields to allow Rails to track article creation and update times.
|
692
693
|
|
693
|
-
TIP: For more information about migrations, refer to [Rails Database
|
694
|
-
|
694
|
+
TIP: For more information about migrations, refer to [Rails Database Migrations]
|
695
|
+
(migrations.html).
|
695
696
|
|
696
697
|
At this point, you can use a rake command to run the migration:
|
697
698
|
|
@@ -713,7 +714,7 @@ NOTE. Because you're working in the development environment by default, this
|
|
713
714
|
command will apply to the database defined in the `development` section of your
|
714
715
|
`config/database.yml` file. If you would like to execute migrations in another
|
715
716
|
environment, for instance in production, you must explicitly pass it when
|
716
|
-
invoking the command: `rake db:migrate RAILS_ENV=production`.
|
717
|
+
invoking the command: `bin/rake db:migrate RAILS_ENV=production`.
|
717
718
|
|
718
719
|
### Saving data in the controller
|
719
720
|
|
@@ -733,26 +734,48 @@ end
|
|
733
734
|
|
734
735
|
Here's what's going on: every Rails model can be initialized with its
|
735
736
|
respective attributes, which are automatically mapped to the respective
|
736
|
-
database columns. In the first line we do just that
|
737
|
-
|
738
|
-
|
739
|
-
|
737
|
+
database columns. In the first line we do just that (remember that
|
738
|
+
`params[:article]` contains the attributes we're interested in). Then,
|
739
|
+
`@article.save` is responsible for saving the model in the database. Finally,
|
740
|
+
we redirect the user to the `show` action, which we'll define later.
|
741
|
+
|
742
|
+
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.
|
740
743
|
|
741
|
-
TIP: As we'll see later, `@article.save` returns a boolean indicating
|
742
|
-
|
744
|
+
TIP: As we'll see later, `@article.save` returns a boolean indicating whether
|
745
|
+
the article was saved or not.
|
743
746
|
|
744
|
-
If you now go to
|
745
|
-
|
746
|
-
article. Try it! You should get an error that looks like this:
|
747
|
+
If you now go to <http://localhost:3000/articles/new> you'll *almost* be able
|
748
|
+
to create an article. Try it! You should get an error that looks like this:
|
747
749
|
|
748
|
-
![Forbidden attributes for new article]
|
750
|
+
![Forbidden attributes for new article]
|
751
|
+
(images/getting_started/forbidden_attributes_for_new_article.png)
|
749
752
|
|
750
753
|
Rails has several security features that help you write secure applications,
|
751
|
-
and you're running into one of them now. This one is called
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
754
|
+
and you're running into one of them now. This one is called [strong parameters](action_controller_overview.html#strong-parameters),
|
755
|
+
which requires us to tell Rails exactly which parameters are allowed into our
|
756
|
+
controller actions.
|
757
|
+
|
758
|
+
Why do you have to bother? The ability to grab and automatically assign all
|
759
|
+
controller parameters to your model in one shot makes the programmer's job
|
760
|
+
easier, but this convenience also allows malicious use. What if a request to
|
761
|
+
the server was crafted to look like a new article form submit but also included
|
762
|
+
extra fields with values that violated your applications integrity? They would
|
763
|
+
be 'mass assigned' into your model and then into the database along with the
|
764
|
+
good stuff - potentially breaking your application or worse.
|
765
|
+
|
766
|
+
We have to whitelist our controller parameters to prevent wrongful mass
|
767
|
+
assignment. In this case, we want to both allow and require the `title` and
|
768
|
+
`text` parameters for valid use of `create`. The syntax for this introduces
|
769
|
+
`require` and `permit`. The change will involve one line in the `create` action:
|
770
|
+
|
771
|
+
```ruby
|
772
|
+
@article = Article.new(params.require(:article).permit(:title, :text))
|
773
|
+
```
|
774
|
+
|
775
|
+
This is often factored out into its own method so it can be reused by multiple
|
776
|
+
actions in the same controller, for example `create` and `update`. Above and
|
777
|
+
beyond mass assignment issues, the method is often made `private` to make sure
|
778
|
+
it can't be called outside its intended context. Here is the result:
|
756
779
|
|
757
780
|
```ruby
|
758
781
|
def create
|
@@ -768,22 +791,17 @@ private
|
|
768
791
|
end
|
769
792
|
```
|
770
793
|
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
TIP: Note that `def article_params` is private. This new approach prevents an
|
775
|
-
attacker from setting the model's attributes by manipulating the hash passed to
|
776
|
-
the model.
|
777
|
-
For more information, refer to
|
778
|
-
[this blog article about Strong Parameters](http://weblog.rubyonrails.org/2012/3/21/strong-parameters/).
|
794
|
+
TIP: For more information, refer to the reference above and
|
795
|
+
[this blog article about Strong Parameters]
|
796
|
+
(http://weblog.rubyonrails.org/2012/3/21/strong-parameters/).
|
779
797
|
|
780
798
|
### Showing Articles
|
781
799
|
|
782
|
-
If you submit the form again now, Rails will complain about not finding
|
783
|
-
|
784
|
-
|
800
|
+
If you submit the form again now, Rails will complain about not finding the
|
801
|
+
`show` action. That's not very useful though, so let's add the `show` action
|
802
|
+
before proceeding.
|
785
803
|
|
786
|
-
As we have seen in the output of `rake routes`, the route for `show` action is
|
804
|
+
As we have seen in the output of `bin/rake routes`, the route for `show` action is
|
787
805
|
as follows:
|
788
806
|
|
789
807
|
```
|
@@ -796,15 +814,29 @@ parameter, which in our case will be the id of the article.
|
|
796
814
|
As we did before, we need to add the `show` action in
|
797
815
|
`app/controllers/articles_controller.rb` and its respective view.
|
798
816
|
|
817
|
+
NOTE: A frequent practice is to place the standard CRUD actions in each
|
818
|
+
controller in the following order: `index`, `show`, `new`, `edit`, `create`, `update`
|
819
|
+
and `destroy`. You may use any order you choose, but keep in mind that these
|
820
|
+
are public methods; as mentioned earlier in this guide, they must be placed
|
821
|
+
before any private or protected method in the controller in order to work.
|
822
|
+
|
823
|
+
Given that, let's add the `show` action, as follows:
|
824
|
+
|
799
825
|
```ruby
|
800
|
-
|
801
|
-
|
802
|
-
|
826
|
+
class ArticlesController < ApplicationController
|
827
|
+
def show
|
828
|
+
@article = Article.find(params[:id])
|
829
|
+
end
|
830
|
+
|
831
|
+
def new
|
832
|
+
end
|
833
|
+
|
834
|
+
# snippet for brevity
|
803
835
|
```
|
804
836
|
|
805
837
|
A couple of things to note. We use `Article.find` to find the article we're
|
806
838
|
interested in, passing in `params[:id]` to get the `:id` parameter from the
|
807
|
-
request. We also use an instance variable (prefixed
|
839
|
+
request. We also use an instance variable (prefixed with `@`) to hold a
|
808
840
|
reference to the article object. We do this because Rails will pass all instance
|
809
841
|
variables to the view.
|
810
842
|
|
@@ -831,22 +863,34 @@ Visit <http://localhost:3000/articles/new> and give it a try!
|
|
831
863
|
### Listing all articles
|
832
864
|
|
833
865
|
We still need a way to list all our articles, so let's do that.
|
834
|
-
The route for this as per output of `rake routes` is:
|
866
|
+
The route for this as per output of `bin/rake routes` is:
|
835
867
|
|
836
868
|
```
|
837
869
|
articles GET /articles(.:format) articles#index
|
838
870
|
```
|
839
871
|
|
840
872
|
Add the corresponding `index` action for that route inside the
|
841
|
-
`ArticlesController` in the `app/controllers/articles_controller.rb` file
|
873
|
+
`ArticlesController` in the `app/controllers/articles_controller.rb` file.
|
874
|
+
When we write an `index` action, the usual practice is to place it as the
|
875
|
+
first method in the controller. Let's do it:
|
842
876
|
|
843
877
|
```ruby
|
844
|
-
|
845
|
-
|
846
|
-
|
878
|
+
class ArticlesController < ApplicationController
|
879
|
+
def index
|
880
|
+
@articles = Article.all
|
881
|
+
end
|
882
|
+
|
883
|
+
def show
|
884
|
+
@article = Article.find(params[:id])
|
885
|
+
end
|
886
|
+
|
887
|
+
def new
|
888
|
+
end
|
889
|
+
|
890
|
+
# snippet for brevity
|
847
891
|
```
|
848
892
|
|
849
|
-
And then finally, add view for this action, located at
|
893
|
+
And then finally, add the view for this action, located at
|
850
894
|
`app/views/articles/index.html.erb`:
|
851
895
|
|
852
896
|
```html+erb
|
@@ -867,7 +911,7 @@ And then finally, add view for this action, located at
|
|
867
911
|
</table>
|
868
912
|
```
|
869
913
|
|
870
|
-
Now if you go to
|
914
|
+
Now if you go to <http://localhost:3000/articles> you will see a list of all the
|
871
915
|
articles that you have created.
|
872
916
|
|
873
917
|
### Adding links
|
@@ -896,8 +940,8 @@ Let's add links to the other views as well, starting with adding this
|
|
896
940
|
|
897
941
|
This link will allow you to bring up the form that lets you create a new article.
|
898
942
|
|
899
|
-
|
900
|
-
go back to the `index` action:
|
943
|
+
Now, add another link in `app/views/articles/new.html.erb`, underneath the
|
944
|
+
form, to go back to the `index` action:
|
901
945
|
|
902
946
|
```erb
|
903
947
|
<%= form_for :article, url: articles_path do |f| %>
|
@@ -907,7 +951,7 @@ go back to the `index` action:
|
|
907
951
|
<%= link_to 'Back', articles_path %>
|
908
952
|
```
|
909
953
|
|
910
|
-
Finally, add
|
954
|
+
Finally, add a link to the `app/views/articles/show.html.erb` template to
|
911
955
|
go back to the `index` action as well, so that people who are viewing a single
|
912
956
|
article can go back and view the whole list again:
|
913
957
|
|
@@ -925,9 +969,9 @@ article can go back and view the whole list again:
|
|
925
969
|
<%= link_to 'Back', articles_path %>
|
926
970
|
```
|
927
971
|
|
928
|
-
TIP: If you want to link to an action in the same controller, you don't
|
929
|
-
|
930
|
-
|
972
|
+
TIP: If you want to link to an action in the same controller, you don't need to
|
973
|
+
specify the `:controller` option, as Rails will use the current controller by
|
974
|
+
default.
|
931
975
|
|
932
976
|
TIP: In development mode (which is what you're working in by default), Rails
|
933
977
|
reloads your application with every browser request, so there's no need to stop
|
@@ -962,7 +1006,7 @@ These changes will ensure that all articles have a title that is at least five
|
|
962
1006
|
characters long. Rails can validate a variety of conditions in a model,
|
963
1007
|
including the presence or uniqueness of columns, their format, and the
|
964
1008
|
existence of associated objects. Validations are covered in detail in [Active
|
965
|
-
Record Validations](active_record_validations.html)
|
1009
|
+
Record Validations](active_record_validations.html).
|
966
1010
|
|
967
1011
|
With the validation now in place, when you call `@article.save` on an invalid
|
968
1012
|
article, it will return `false`. If you open
|
@@ -1011,17 +1055,21 @@ something went wrong. To do that, you'll modify
|
|
1011
1055
|
|
1012
1056
|
```html+erb
|
1013
1057
|
<%= form_for :article, url: articles_path do |f| %>
|
1058
|
+
|
1014
1059
|
<% if @article.errors.any? %>
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
<
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1060
|
+
<div id="error_explanation">
|
1061
|
+
<h2>
|
1062
|
+
<%= pluralize(@article.errors.count, "error") %> prohibited
|
1063
|
+
this article from being saved:
|
1064
|
+
</h2>
|
1065
|
+
<ul>
|
1066
|
+
<% @article.errors.full_messages.each do |msg| %>
|
1067
|
+
<li><%= msg %></li>
|
1068
|
+
<% end %>
|
1069
|
+
</ul>
|
1070
|
+
</div>
|
1024
1071
|
<% end %>
|
1072
|
+
|
1025
1073
|
<p>
|
1026
1074
|
<%= f.label :title %><br>
|
1027
1075
|
<%= f.text_field :title %>
|
@@ -1035,6 +1083,7 @@ something went wrong. To do that, you'll modify
|
|
1035
1083
|
<p>
|
1036
1084
|
<%= f.submit %>
|
1037
1085
|
</p>
|
1086
|
+
|
1038
1087
|
<% end %>
|
1039
1088
|
|
1040
1089
|
<%= link_to 'Back', articles_path %>
|
@@ -1058,7 +1107,7 @@ standout.
|
|
1058
1107
|
|
1059
1108
|
Now you'll get a nice error message when saving an article without title when
|
1060
1109
|
you attempt to do just that on the new article form
|
1061
|
-
|
1110
|
+
<http://localhost:3000/articles/new>:
|
1062
1111
|
|
1063
1112
|
![Form With Errors](images/getting_started/form_with_errors.png)
|
1064
1113
|
|
@@ -1067,12 +1116,27 @@ you attempt to do just that on the new article form
|
|
1067
1116
|
We've covered the "CR" part of CRUD. Now let's focus on the "U" part, updating
|
1068
1117
|
articles.
|
1069
1118
|
|
1070
|
-
The first step we'll take is adding an `edit` action to the `ArticlesController
|
1119
|
+
The first step we'll take is adding an `edit` action to the `ArticlesController`,
|
1120
|
+
generally between the `new` and `create` actions, as shown:
|
1071
1121
|
|
1072
1122
|
```ruby
|
1123
|
+
def new
|
1124
|
+
@article = Article.new
|
1125
|
+
end
|
1126
|
+
|
1073
1127
|
def edit
|
1074
1128
|
@article = Article.find(params[:id])
|
1075
1129
|
end
|
1130
|
+
|
1131
|
+
def create
|
1132
|
+
@article = Article.new(article_params)
|
1133
|
+
|
1134
|
+
if @article.save
|
1135
|
+
redirect_to @article
|
1136
|
+
else
|
1137
|
+
render 'new'
|
1138
|
+
end
|
1139
|
+
end
|
1076
1140
|
```
|
1077
1141
|
|
1078
1142
|
The view will contain a form similar to the one we used when creating
|
@@ -1083,17 +1147,21 @@ it look as follows:
|
|
1083
1147
|
<h1>Editing article</h1>
|
1084
1148
|
|
1085
1149
|
<%= form_for :article, url: article_path(@article), method: :patch do |f| %>
|
1150
|
+
|
1086
1151
|
<% if @article.errors.any? %>
|
1087
|
-
|
1088
|
-
|
1089
|
-
|
1090
|
-
|
1091
|
-
|
1092
|
-
<
|
1093
|
-
|
1094
|
-
|
1095
|
-
|
1152
|
+
<div id="error_explanation">
|
1153
|
+
<h2>
|
1154
|
+
<%= pluralize(@article.errors.count, "error") %> prohibited
|
1155
|
+
this article from being saved:
|
1156
|
+
</h2>
|
1157
|
+
<ul>
|
1158
|
+
<% @article.errors.full_messages.each do |msg| %>
|
1159
|
+
<li><%= msg %></li>
|
1160
|
+
<% end %>
|
1161
|
+
</ul>
|
1162
|
+
</div>
|
1096
1163
|
<% end %>
|
1164
|
+
|
1097
1165
|
<p>
|
1098
1166
|
<%= f.label :title %><br>
|
1099
1167
|
<%= f.text_field :title %>
|
@@ -1107,6 +1175,7 @@ it look as follows:
|
|
1107
1175
|
<p>
|
1108
1176
|
<%= f.submit %>
|
1109
1177
|
</p>
|
1178
|
+
|
1110
1179
|
<% end %>
|
1111
1180
|
|
1112
1181
|
<%= link_to 'Back', articles_path %>
|
@@ -1121,14 +1190,26 @@ via the `PATCH` HTTP method which is the HTTP method you're expected to use to
|
|
1121
1190
|
|
1122
1191
|
The first parameter of `form_for` can be an object, say, `@article` which would
|
1123
1192
|
cause the helper to fill in the form with the fields of the object. Passing in a
|
1124
|
-
symbol (`:article`) with the same name as the instance variable (`@article`)
|
1125
|
-
automagically leads to the same behavior. This is what is happening here.
|
1126
|
-
can be found in [form_for documentation]
|
1193
|
+
symbol (`:article`) with the same name as the instance variable (`@article`)
|
1194
|
+
also automagically leads to the same behavior. This is what is happening here.
|
1195
|
+
More details can be found in [form_for documentation]
|
1196
|
+
(http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_for).
|
1127
1197
|
|
1128
|
-
Next we need to create the `update` action in
|
1129
|
-
`app/controllers/articles_controller.rb
|
1198
|
+
Next, we need to create the `update` action in
|
1199
|
+
`app/controllers/articles_controller.rb`.
|
1200
|
+
Add it between the `create` action and the `private` method:
|
1130
1201
|
|
1131
1202
|
```ruby
|
1203
|
+
def create
|
1204
|
+
@article = Article.new(article_params)
|
1205
|
+
|
1206
|
+
if @article.save
|
1207
|
+
redirect_to @article
|
1208
|
+
else
|
1209
|
+
render 'new'
|
1210
|
+
end
|
1211
|
+
end
|
1212
|
+
|
1132
1213
|
def update
|
1133
1214
|
@article = Article.find(params[:id])
|
1134
1215
|
|
@@ -1170,14 +1251,14 @@ it appear next to the "Show" link:
|
|
1170
1251
|
<th colspan="2"></th>
|
1171
1252
|
</tr>
|
1172
1253
|
|
1173
|
-
<% @articles.each do |article| %>
|
1174
|
-
|
1175
|
-
|
1176
|
-
|
1177
|
-
|
1178
|
-
|
1179
|
-
|
1180
|
-
<% end %>
|
1254
|
+
<% @articles.each do |article| %>
|
1255
|
+
<tr>
|
1256
|
+
<td><%= article.title %></td>
|
1257
|
+
<td><%= article.text %></td>
|
1258
|
+
<td><%= link_to 'Show', article_path(article) %></td>
|
1259
|
+
<td><%= link_to 'Edit', edit_article_path(article) %></td>
|
1260
|
+
</tr>
|
1261
|
+
<% end %>
|
1181
1262
|
</table>
|
1182
1263
|
```
|
1183
1264
|
|
@@ -1188,8 +1269,8 @@ bottom of the template:
|
|
1188
1269
|
```html+erb
|
1189
1270
|
...
|
1190
1271
|
|
1272
|
+
<%= link_to 'Edit', edit_article_path(@article) %> |
|
1191
1273
|
<%= link_to 'Back', articles_path %>
|
1192
|
-
| <%= link_to 'Edit', edit_article_path(@article) %>
|
1193
1274
|
```
|
1194
1275
|
|
1195
1276
|
And here's how our app looks so far:
|
@@ -1198,10 +1279,10 @@ And here's how our app looks so far:
|
|
1198
1279
|
|
1199
1280
|
### Using partials to clean up duplication in views
|
1200
1281
|
|
1201
|
-
Our `edit` page looks very similar to the `new` page
|
1202
|
-
both share the same code for displaying the form. Let's remove
|
1203
|
-
by using a view partial. By convention, partial files are
|
1204
|
-
underscore.
|
1282
|
+
Our `edit` page looks very similar to the `new` page; in fact, they
|
1283
|
+
both share the same code for displaying the form. Let's remove this
|
1284
|
+
duplication by using a view partial. By convention, partial files are
|
1285
|
+
prefixed with an underscore.
|
1205
1286
|
|
1206
1287
|
TIP: You can read more about partials in the
|
1207
1288
|
[Layouts and Rendering in Rails](layouts_and_rendering.html) guide.
|
@@ -1211,17 +1292,21 @@ content:
|
|
1211
1292
|
|
1212
1293
|
```html+erb
|
1213
1294
|
<%= form_for @article do |f| %>
|
1295
|
+
|
1214
1296
|
<% if @article.errors.any? %>
|
1215
|
-
|
1216
|
-
|
1217
|
-
|
1218
|
-
|
1219
|
-
|
1220
|
-
<
|
1221
|
-
|
1222
|
-
|
1223
|
-
|
1297
|
+
<div id="error_explanation">
|
1298
|
+
<h2>
|
1299
|
+
<%= pluralize(@article.errors.count, "error") %> prohibited
|
1300
|
+
this article from being saved:
|
1301
|
+
</h2>
|
1302
|
+
<ul>
|
1303
|
+
<% @article.errors.full_messages.each do |msg| %>
|
1304
|
+
<li><%= msg %></li>
|
1305
|
+
<% end %>
|
1306
|
+
</ul>
|
1307
|
+
</div>
|
1224
1308
|
<% end %>
|
1309
|
+
|
1225
1310
|
<p>
|
1226
1311
|
<%= f.label :title %><br>
|
1227
1312
|
<%= f.text_field :title %>
|
@@ -1235,6 +1320,7 @@ content:
|
|
1235
1320
|
<p>
|
1236
1321
|
<%= f.submit %>
|
1237
1322
|
</p>
|
1323
|
+
|
1238
1324
|
<% end %>
|
1239
1325
|
```
|
1240
1326
|
|
@@ -1243,8 +1329,8 @@ The reason we can use this shorter, simpler `form_for` declaration
|
|
1243
1329
|
to stand in for either of the other forms is that `@article` is a *resource*
|
1244
1330
|
corresponding to a full set of RESTful routes, and Rails is able to infer
|
1245
1331
|
which URI and method to use.
|
1246
|
-
For more information about this use of `form_for`, see
|
1247
|
-
|
1332
|
+
For more information about this use of `form_for`, see [Resource-oriented style]
|
1333
|
+
(http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_for-label-Resource-oriented+style).
|
1248
1334
|
|
1249
1335
|
Now, let's update the `app/views/articles/new.html.erb` view to use this new
|
1250
1336
|
partial, rewriting it completely:
|
@@ -1271,7 +1357,7 @@ Then do the same for the `app/views/articles/edit.html.erb` view:
|
|
1271
1357
|
|
1272
1358
|
We're now ready to cover the "D" part of CRUD, deleting articles from the
|
1273
1359
|
database. Following the REST convention, the route for
|
1274
|
-
deleting articles as per output of `rake routes` is:
|
1360
|
+
deleting articles as per output of `bin/rake routes` is:
|
1275
1361
|
|
1276
1362
|
```ruby
|
1277
1363
|
DELETE /articles/:id(.:format) articles#destroy
|
@@ -1285,9 +1371,11 @@ people to craft malicious URLs like this:
|
|
1285
1371
|
<a href='http://example.com/articles/1/destroy'>look at this cat!</a>
|
1286
1372
|
```
|
1287
1373
|
|
1288
|
-
We use the `delete` method for destroying resources, and this route is mapped
|
1289
|
-
the `destroy` action inside `app/controllers/articles_controller.rb`, which
|
1290
|
-
doesn't exist yet
|
1374
|
+
We use the `delete` method for destroying resources, and this route is mapped
|
1375
|
+
to the `destroy` action inside `app/controllers/articles_controller.rb`, which
|
1376
|
+
doesn't exist yet. The `destroy` method is generally the last CRUD action in
|
1377
|
+
the controller, and like the other public CRUD actions, it must be placed
|
1378
|
+
before any `private` or `protected` methods. Let's add it:
|
1291
1379
|
|
1292
1380
|
```ruby
|
1293
1381
|
def destroy
|
@@ -1298,13 +1386,67 @@ def destroy
|
|
1298
1386
|
end
|
1299
1387
|
```
|
1300
1388
|
|
1389
|
+
The complete `ArticlesController` in the
|
1390
|
+
`app/controllers/articles_controller.rb` file should now look like this:
|
1391
|
+
|
1392
|
+
```ruby
|
1393
|
+
class ArticlesController < ApplicationController
|
1394
|
+
def index
|
1395
|
+
@articles = Article.all
|
1396
|
+
end
|
1397
|
+
|
1398
|
+
def show
|
1399
|
+
@article = Article.find(params[:id])
|
1400
|
+
end
|
1401
|
+
|
1402
|
+
def new
|
1403
|
+
@article = Article.new
|
1404
|
+
end
|
1405
|
+
|
1406
|
+
def edit
|
1407
|
+
@article = Article.find(params[:id])
|
1408
|
+
end
|
1409
|
+
|
1410
|
+
def create
|
1411
|
+
@article = Article.new(article_params)
|
1412
|
+
|
1413
|
+
if @article.save
|
1414
|
+
redirect_to @article
|
1415
|
+
else
|
1416
|
+
render 'new'
|
1417
|
+
end
|
1418
|
+
end
|
1419
|
+
|
1420
|
+
def update
|
1421
|
+
@article = Article.find(params[:id])
|
1422
|
+
|
1423
|
+
if @article.update(article_params)
|
1424
|
+
redirect_to @article
|
1425
|
+
else
|
1426
|
+
render 'edit'
|
1427
|
+
end
|
1428
|
+
end
|
1429
|
+
|
1430
|
+
def destroy
|
1431
|
+
@article = Article.find(params[:id])
|
1432
|
+
@article.destroy
|
1433
|
+
|
1434
|
+
redirect_to articles_path
|
1435
|
+
end
|
1436
|
+
|
1437
|
+
private
|
1438
|
+
def article_params
|
1439
|
+
params.require(:article).permit(:title, :text)
|
1440
|
+
end
|
1441
|
+
end
|
1442
|
+
```
|
1443
|
+
|
1301
1444
|
You can call `destroy` on Active Record objects when you want to delete
|
1302
1445
|
them from the database. Note that we don't need to add a view for this
|
1303
1446
|
action since we're redirecting to the `index` action.
|
1304
1447
|
|
1305
1448
|
Finally, add a 'Destroy' link to your `index` action template
|
1306
|
-
(`app/views/articles/index.html.erb`) to wrap everything
|
1307
|
-
together.
|
1449
|
+
(`app/views/articles/index.html.erb`) to wrap everything together.
|
1308
1450
|
|
1309
1451
|
```html+erb
|
1310
1452
|
<h1>Listing Articles</h1>
|
@@ -1316,16 +1458,17 @@ together.
|
|
1316
1458
|
<th colspan="3"></th>
|
1317
1459
|
</tr>
|
1318
1460
|
|
1319
|
-
<% @articles.each do |article| %>
|
1320
|
-
|
1321
|
-
|
1322
|
-
|
1323
|
-
|
1324
|
-
|
1325
|
-
|
1326
|
-
|
1327
|
-
|
1328
|
-
|
1461
|
+
<% @articles.each do |article| %>
|
1462
|
+
<tr>
|
1463
|
+
<td><%= article.title %></td>
|
1464
|
+
<td><%= article.text %></td>
|
1465
|
+
<td><%= link_to 'Show', article_path(article) %></td>
|
1466
|
+
<td><%= link_to 'Edit', edit_article_path(article) %></td>
|
1467
|
+
<td><%= link_to 'Destroy', article_path(article),
|
1468
|
+
method: :delete,
|
1469
|
+
data: { confirm: 'Are you sure?' } %></td>
|
1470
|
+
</tr>
|
1471
|
+
<% end %>
|
1329
1472
|
</table>
|
1330
1473
|
```
|
1331
1474
|
|
@@ -1343,9 +1486,8 @@ Without this file, the confirmation dialog box wouldn't appear.
|
|
1343
1486
|
Congratulations, you can now create, show, list, update and destroy
|
1344
1487
|
articles.
|
1345
1488
|
|
1346
|
-
TIP: In general, Rails encourages
|
1347
|
-
|
1348
|
-
For more information about routing, see
|
1489
|
+
TIP: In general, Rails encourages using resources objects instead of
|
1490
|
+
declaring routes manually. For more information about routing, see
|
1349
1491
|
[Rails Routing from the Outside In](routing.html).
|
1350
1492
|
|
1351
1493
|
Adding a Second Model
|
@@ -1394,19 +1536,17 @@ class CreateComments < ActiveRecord::Migration
|
|
1394
1536
|
create_table :comments do |t|
|
1395
1537
|
t.string :commenter
|
1396
1538
|
t.text :body
|
1539
|
+
t.references :article, index: true, foreign_key: true
|
1397
1540
|
|
1398
|
-
|
1399
|
-
t.references :article, index: true
|
1400
|
-
|
1401
|
-
t.timestamps
|
1541
|
+
t.timestamps null: false
|
1402
1542
|
end
|
1403
1543
|
end
|
1404
1544
|
end
|
1405
1545
|
```
|
1406
1546
|
|
1407
|
-
The `t.references` line
|
1408
|
-
|
1409
|
-
|
1547
|
+
The `t.references` line creates an integer column called `article_id`, an index
|
1548
|
+
for it, and a foreign key constraint that points to the `articles` table. Go
|
1549
|
+
ahead and run the migration:
|
1410
1550
|
|
1411
1551
|
```bash
|
1412
1552
|
$ bin/rake db:migrate
|
@@ -1488,7 +1628,7 @@ controller. Again, we'll use the same generator we used before:
|
|
1488
1628
|
$ bin/rails generate controller Comments
|
1489
1629
|
```
|
1490
1630
|
|
1491
|
-
This creates
|
1631
|
+
This creates five files and one empty directory:
|
1492
1632
|
|
1493
1633
|
| File/Directory | Purpose |
|
1494
1634
|
| -------------------------------------------- | ---------------------------------------- |
|
@@ -1496,7 +1636,6 @@ This creates six files and one empty directory:
|
|
1496
1636
|
| app/views/comments/ | Views of the controller are stored here |
|
1497
1637
|
| test/controllers/comments_controller_test.rb | The test for the controller |
|
1498
1638
|
| app/helpers/comments_helper.rb | A view helper file |
|
1499
|
-
| test/helpers/comments_helper_test.rb | The test for the helper |
|
1500
1639
|
| app/assets/javascripts/comment.js.coffee | CoffeeScript for the controller |
|
1501
1640
|
| app/assets/stylesheets/comment.css.scss | Cascading style sheet for the controller |
|
1502
1641
|
|
@@ -1535,8 +1674,8 @@ So first, we'll wire up the Article show template
|
|
1535
1674
|
</p>
|
1536
1675
|
<% end %>
|
1537
1676
|
|
1677
|
+
<%= link_to 'Edit', edit_article_path(@article) %> |
|
1538
1678
|
<%= link_to 'Back', articles_path %>
|
1539
|
-
| <%= link_to 'Edit', edit_article_path(@article) %>
|
1540
1679
|
```
|
1541
1680
|
|
1542
1681
|
This adds a form on the `Article` show page that creates a new comment by
|
@@ -1616,8 +1755,8 @@ add that to the `app/views/articles/show.html.erb`.
|
|
1616
1755
|
</p>
|
1617
1756
|
<% end %>
|
1618
1757
|
|
1619
|
-
<%= link_to 'Edit
|
1620
|
-
<%= link_to 'Back
|
1758
|
+
<%= link_to 'Edit', edit_article_path(@article) %> |
|
1759
|
+
<%= link_to 'Back', articles_path %>
|
1621
1760
|
```
|
1622
1761
|
|
1623
1762
|
Now you can add articles and comments to your blog and have them show up in the
|
@@ -1682,8 +1821,8 @@ following:
|
|
1682
1821
|
</p>
|
1683
1822
|
<% end %>
|
1684
1823
|
|
1685
|
-
<%= link_to 'Edit
|
1686
|
-
<%= link_to 'Back
|
1824
|
+
<%= link_to 'Edit', edit_article_path(@article) %> |
|
1825
|
+
<%= link_to 'Back', articles_path %>
|
1687
1826
|
```
|
1688
1827
|
|
1689
1828
|
This will now render the partial in `app/views/comments/_comment.html.erb` once
|
@@ -1730,10 +1869,10 @@ Then you make the `app/views/articles/show.html.erb` look like the following:
|
|
1730
1869
|
<%= render @article.comments %>
|
1731
1870
|
|
1732
1871
|
<h2>Add a comment:</h2>
|
1733
|
-
<%= render
|
1872
|
+
<%= render 'comments/form' %>
|
1734
1873
|
|
1735
|
-
<%= link_to 'Edit
|
1736
|
-
<%= link_to 'Back
|
1874
|
+
<%= link_to 'Edit', edit_article_path(@article) %> |
|
1875
|
+
<%= link_to 'Back', articles_path %>
|
1737
1876
|
```
|
1738
1877
|
|
1739
1878
|
The second render just defines the partial template we want to render,
|
@@ -1806,8 +1945,8 @@ database and send us back to the show action for the article.
|
|
1806
1945
|
|
1807
1946
|
### Deleting Associated Objects
|
1808
1947
|
|
1809
|
-
If you delete an article
|
1810
|
-
deleted
|
1948
|
+
If you delete an article, its associated comments will also need to be
|
1949
|
+
deleted, otherwise they would simply occupy space in the database. Rails allows
|
1811
1950
|
you to use the `dependent` option of an association to achieve this. Modify the
|
1812
1951
|
Article model, `app/models/article.rb`, as follows:
|
1813
1952
|
|
@@ -1824,21 +1963,21 @@ Security
|
|
1824
1963
|
|
1825
1964
|
### Basic Authentication
|
1826
1965
|
|
1827
|
-
If you were to publish your blog online,
|
1966
|
+
If you were to publish your blog online, anyone would be able to add, edit and
|
1828
1967
|
delete articles or delete comments.
|
1829
1968
|
|
1830
1969
|
Rails provides a very simple HTTP authentication system that will work nicely in
|
1831
1970
|
this situation.
|
1832
1971
|
|
1833
|
-
In the `ArticlesController` we need to have a way to block access to the
|
1834
|
-
actions if the person is not authenticated
|
1835
|
-
`http_basic_authenticate_with` method,
|
1972
|
+
In the `ArticlesController` we need to have a way to block access to the
|
1973
|
+
various actions if the person is not authenticated. Here we can use the Rails
|
1974
|
+
`http_basic_authenticate_with` method, which allows access to the requested
|
1836
1975
|
action if that method allows it.
|
1837
1976
|
|
1838
1977
|
To use the authentication system, we specify it at the top of our
|
1839
|
-
`ArticlesController
|
1840
|
-
every action
|
1841
|
-
|
1978
|
+
`ArticlesController` in `app/controllers/articles_controller.rb`. In our case,
|
1979
|
+
we want the user to be authenticated on every action except `index` and `show`,
|
1980
|
+
so we write that:
|
1842
1981
|
|
1843
1982
|
```ruby
|
1844
1983
|
class ArticlesController < ApplicationController
|
@@ -1849,7 +1988,7 @@ class ArticlesController < ApplicationController
|
|
1849
1988
|
@articles = Article.all
|
1850
1989
|
end
|
1851
1990
|
|
1852
|
-
#
|
1991
|
+
# snippet for brevity
|
1853
1992
|
```
|
1854
1993
|
|
1855
1994
|
We also want to allow only authenticated users to delete comments, so in the
|
@@ -1862,14 +2001,14 @@ class CommentsController < ApplicationController
|
|
1862
2001
|
|
1863
2002
|
def create
|
1864
2003
|
@article = Article.find(params[:article_id])
|
1865
|
-
...
|
2004
|
+
# ...
|
1866
2005
|
end
|
1867
2006
|
|
1868
|
-
#
|
2007
|
+
# snippet for brevity
|
1869
2008
|
```
|
1870
2009
|
|
1871
2010
|
Now if you try to create a new article, you will be greeted with a basic HTTP
|
1872
|
-
Authentication challenge
|
2011
|
+
Authentication challenge:
|
1873
2012
|
|
1874
2013
|
![Basic HTTP Authentication Challenge](images/getting_started/challenge.png)
|
1875
2014
|
|
@@ -1884,7 +2023,7 @@ along with a number of others.
|
|
1884
2023
|
|
1885
2024
|
Security, especially in web applications, is a broad and detailed area. Security
|
1886
2025
|
in your Rails application is covered in more depth in
|
1887
|
-
|
2026
|
+
the [Ruby on Rails Security Guide](security.html).
|
1888
2027
|
|
1889
2028
|
|
1890
2029
|
What's Next?
|
@@ -1895,7 +2034,7 @@ update it and experiment on your own. But you don't have to do everything
|
|
1895
2034
|
without help. As you need assistance getting up and running with Rails, feel
|
1896
2035
|
free to consult these support resources:
|
1897
2036
|
|
1898
|
-
* The [Ruby on Rails
|
2037
|
+
* The [Ruby on Rails Guides](index.html)
|
1899
2038
|
* The [Ruby on Rails Tutorial](http://railstutorial.org/book)
|
1900
2039
|
* The [Ruby on Rails mailing list](http://groups.google.com/group/rubyonrails-talk)
|
1901
2040
|
* The [#rubyonrails](irc://irc.freenode.net/#rubyonrails) channel on irc.freenode.net
|
@@ -1911,7 +2050,7 @@ command-line utility:
|
|
1911
2050
|
in your web browser to explore the API documentation.
|
1912
2051
|
|
1913
2052
|
TIP: To be able to generate the Rails Guides locally with the `doc:guides` rake
|
1914
|
-
task you need to install the RedCloth
|
2053
|
+
task you need to install the RedCloth and Nokogiri gems. Add it to your `Gemfile` and run
|
1915
2054
|
`bundle install` and you're ready to go.
|
1916
2055
|
|
1917
2056
|
Configuration Gotchas
|