rails 4.1.4 → 4.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +12 -10
- data/guides/CHANGELOG.md +15 -25
- 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_gem.rb +2 -2
- data/guides/bug_report_templates/action_controller_master.rb +3 -2
- 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 +5 -2
- 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 +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 +84 -10
- data/guides/source/action_mailer_basics.md +91 -28
- data/guides/source/action_view_overview.md +140 -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} +135 -226
- data/guides/source/active_record_postgresql.md +433 -0
- data/guides/source/active_record_querying.md +269 -259
- data/guides/source/active_record_validations.md +21 -12
- data/guides/source/active_support_core_extensions.md +113 -73
- data/guides/source/active_support_instrumentation.md +10 -7
- data/guides/source/api_documentation_guidelines.md +62 -16
- data/guides/source/asset_pipeline.md +264 -67
- 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 +448 -294
- data/guides/source/development_dependencies_install.md +47 -36
- data/guides/source/documents.yaml +19 -7
- data/guides/source/engines.md +210 -189
- data/guides/source/form_helpers.md +79 -56
- data/guides/source/generators.md +24 -11
- data/guides/source/getting_started.md +339 -201
- data/guides/source/i18n.md +111 -68
- data/guides/source/index.html.erb +1 -0
- data/guides/source/initialization.md +109 -62
- data/guides/source/layout.html.erb +1 -4
- data/guides/source/layouts_and_rendering.md +18 -17
- 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 -9
- data/guides/source/routing.md +100 -74
- data/guides/source/ruby_on_rails_guides_guidelines.md +11 -12
- data/guides/source/security.md +40 -34
- data/guides/source/testing.md +188 -117
- data/guides/source/upgrading_ruby_on_rails.md +284 -29
- data/guides/source/working_with_javascript_in_rails.md +18 -16
- data/guides/w3c_validator.rb +2 -0
- metadata +40 -94
- 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.0", 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,15 @@ following in the `blog` directory:
|
|
|
193
191
|
$ bin/rails server
|
|
194
192
|
```
|
|
195
193
|
|
|
196
|
-
TIP: Compiling CoffeeScript
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
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).
|
|
204
203
|
|
|
205
204
|
This will fire up WEBrick, a web server distributed with Ruby by default. To see
|
|
206
205
|
your application in action, open a browser window and navigate to
|
|
@@ -258,8 +257,6 @@ invoke test_unit
|
|
|
258
257
|
create test/controllers/welcome_controller_test.rb
|
|
259
258
|
invoke helper
|
|
260
259
|
create app/helpers/welcome_helper.rb
|
|
261
|
-
invoke test_unit
|
|
262
|
-
create test/helpers/welcome_helper_test.rb
|
|
263
260
|
invoke assets
|
|
264
261
|
invoke coffee
|
|
265
262
|
create app/assets/javascripts/welcome.js.coffee
|
|
@@ -267,8 +264,9 @@ invoke scss
|
|
|
267
264
|
create app/assets/stylesheets/welcome.css.scss
|
|
268
265
|
```
|
|
269
266
|
|
|
270
|
-
Most important of these are of course the controller, located at
|
|
271
|
-
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`.
|
|
272
270
|
|
|
273
271
|
Open the `app/views/welcome/index.html.erb` file in your text editor. Delete all
|
|
274
272
|
of the existing code in the file, and replace it with the following single line
|
|
@@ -340,11 +338,11 @@ You can create, read, update and destroy items for a resource and these
|
|
|
340
338
|
operations are referred to as _CRUD_ operations.
|
|
341
339
|
|
|
342
340
|
Rails provides a `resources` method which can be used to declare a standard REST
|
|
343
|
-
resource.
|
|
344
|
-
|
|
341
|
+
resource. You need to add the _article resource_ to the
|
|
342
|
+
`config/routes.rb` as follows:
|
|
345
343
|
|
|
346
344
|
```ruby
|
|
347
|
-
|
|
345
|
+
Rails.application.routes.draw do
|
|
348
346
|
|
|
349
347
|
resources :articles
|
|
350
348
|
|
|
@@ -427,19 +425,22 @@ are generated in Rails they are empty by default, unless you tell it
|
|
|
427
425
|
your wanted actions during the generation process.
|
|
428
426
|
|
|
429
427
|
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:
|
|
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:
|
|
433
431
|
|
|
434
432
|
```ruby
|
|
435
|
-
|
|
433
|
+
class ArticlesController < ApplicationController
|
|
434
|
+
def new
|
|
435
|
+
end
|
|
436
436
|
end
|
|
437
437
|
```
|
|
438
438
|
|
|
439
439
|
With the `new` method defined in `ArticlesController`, if you refresh
|
|
440
440
|
<http://localhost:3000/articles/new> you'll see another error:
|
|
441
441
|
|
|
442
|
-
![Template is missing for articles/new]
|
|
442
|
+
![Template is missing for articles/new]
|
|
443
|
+
(images/getting_started/template_is_missing_articles_new.png)
|
|
443
444
|
|
|
444
445
|
You're getting this error now because Rails expects plain actions like this one
|
|
445
446
|
to have views associated with them to display their information. With no view
|
|
@@ -448,9 +449,7 @@ available, Rails errors out.
|
|
|
448
449
|
In the above image, the bottom line has been truncated. Let's see what the full
|
|
449
450
|
thing looks like:
|
|
450
451
|
|
|
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>
|
|
452
|
+
>Missing template articles/new, application/new with {locale:[:en], formats:[:html], handlers:[:erb, :builder, :coffee]}. Searched in: * "/path/to/blog/app/views"
|
|
454
453
|
|
|
455
454
|
That's quite a lot of text! Let's quickly go through and understand what each
|
|
456
455
|
part of it does.
|
|
@@ -496,8 +495,8 @@ harmoniously! It's time to create the form for a new article.
|
|
|
496
495
|
|
|
497
496
|
### The first form
|
|
498
497
|
|
|
499
|
-
To create a form within this template, you will use a
|
|
500
|
-
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
|
|
501
500
|
method called `form_for`. To use this method, add this code into
|
|
502
501
|
`app/views/articles/new.html.erb`:
|
|
503
502
|
|
|
@@ -565,18 +564,18 @@ edit_article GET /articles/:id/edit(.:format) articles#edit
|
|
|
565
564
|
root GET / welcome#index
|
|
566
565
|
```
|
|
567
566
|
|
|
568
|
-
The `articles_path` helper tells Rails to point the form
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
`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`.
|
|
573
571
|
|
|
574
572
|
With the form and its associated route defined, you will be able to fill in the
|
|
575
573
|
form and then click the submit button to begin the process of creating a new
|
|
576
574
|
article, so go ahead and do that. When you submit the form, you should see a
|
|
577
575
|
familiar error:
|
|
578
576
|
|
|
579
|
-
![Unknown action create for ArticlesController]
|
|
577
|
+
![Unknown action create for ArticlesController]
|
|
578
|
+
(images/getting_started/unknown_action_create_for_articles.png)
|
|
580
579
|
|
|
581
580
|
You now need to create the `create` action within the `ArticlesController` for
|
|
582
581
|
this to work.
|
|
@@ -585,7 +584,7 @@ this to work.
|
|
|
585
584
|
|
|
586
585
|
To make the "Unknown action" go away, you can define a `create` action within
|
|
587
586
|
the `ArticlesController` class in `app/controllers/articles_controller.rb`,
|
|
588
|
-
underneath the `new` action:
|
|
587
|
+
underneath the `new` action, as shown:
|
|
589
588
|
|
|
590
589
|
```ruby
|
|
591
590
|
class ArticlesController < ApplicationController
|
|
@@ -619,6 +618,8 @@ method returns an `ActiveSupport::HashWithIndifferentAccess` object, which
|
|
|
619
618
|
allows you to access the keys of the hash using either strings or symbols. In
|
|
620
619
|
this situation, the only parameters that matter are the ones from the form.
|
|
621
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
|
+
|
|
622
623
|
If you re-submit the form one more time you'll now no longer get the missing
|
|
623
624
|
template error. Instead, you'll see something that looks like the following:
|
|
624
625
|
|
|
@@ -632,10 +633,10 @@ parameters but nothing in particular is being done with them.
|
|
|
632
633
|
|
|
633
634
|
### Creating the Article model
|
|
634
635
|
|
|
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
|
-
|
|
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:
|
|
639
640
|
|
|
640
641
|
```bash
|
|
641
642
|
$ bin/rails generate model Article title:string text:text
|
|
@@ -646,26 +647,23 @@ with a _title_ attribute of type string, and a _text_ attribute
|
|
|
646
647
|
of type text. Those attributes are automatically added to the `articles`
|
|
647
648
|
table in the database and mapped to the `Article` model.
|
|
648
649
|
|
|
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.
|
|
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.
|
|
654
654
|
|
|
655
|
-
TIP: Active Record is smart enough to automatically map column names to
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
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.
|
|
659
658
|
|
|
660
659
|
### Running a Migration
|
|
661
660
|
|
|
662
|
-
As we've just seen, `rails generate model` created a _database
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
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.
|
|
669
667
|
|
|
670
668
|
If you look in the `db/migrate/20140120191729_create_articles.rb` file (remember,
|
|
671
669
|
yours will have a slightly different name), here's what you'll find:
|
|
@@ -677,7 +675,7 @@ class CreateArticles < ActiveRecord::Migration
|
|
|
677
675
|
t.string :title
|
|
678
676
|
t.text :text
|
|
679
677
|
|
|
680
|
-
t.timestamps
|
|
678
|
+
t.timestamps null: false
|
|
681
679
|
end
|
|
682
680
|
end
|
|
683
681
|
end
|
|
@@ -690,8 +688,8 @@ in case you want to reverse it later. When you run this migration it will create
|
|
|
690
688
|
an `articles` table with one string column and a text column. It also creates
|
|
691
689
|
two timestamp fields to allow Rails to track article creation and update times.
|
|
692
690
|
|
|
693
|
-
TIP: For more information about migrations, refer to [Rails Database
|
|
694
|
-
|
|
691
|
+
TIP: For more information about migrations, refer to [Rails Database Migrations]
|
|
692
|
+
(migrations.html).
|
|
695
693
|
|
|
696
694
|
At this point, you can use a rake command to run the migration:
|
|
697
695
|
|
|
@@ -733,26 +731,48 @@ end
|
|
|
733
731
|
|
|
734
732
|
Here's what's going on: every Rails model can be initialized with its
|
|
735
733
|
respective attributes, which are automatically mapped to the respective
|
|
736
|
-
database columns. In the first line we do just that
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
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.
|
|
740
738
|
|
|
741
|
-
TIP:
|
|
742
|
-
whether the article was saved or not.
|
|
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.
|
|
743
740
|
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
article. Try it! You should get an error that looks like this:
|
|
741
|
+
TIP: As we'll see later, `@article.save` returns a boolean indicating whether
|
|
742
|
+
the article was saved or not.
|
|
747
743
|
|
|
748
|
-
|
|
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
|
+
|
|
747
|
+
![Forbidden attributes for new article]
|
|
748
|
+
(images/getting_started/forbidden_attributes_for_new_article.png)
|
|
749
749
|
|
|
750
750
|
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
|
-
|
|
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:
|
|
756
776
|
|
|
757
777
|
```ruby
|
|
758
778
|
def create
|
|
@@ -768,20 +788,15 @@ private
|
|
|
768
788
|
end
|
|
769
789
|
```
|
|
770
790
|
|
|
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/).
|
|
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/).
|
|
779
794
|
|
|
780
795
|
### Showing Articles
|
|
781
796
|
|
|
782
|
-
If you submit the form again now, Rails will complain about not finding
|
|
783
|
-
|
|
784
|
-
|
|
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.
|
|
785
800
|
|
|
786
801
|
As we have seen in the output of `rake routes`, the route for `show` action is
|
|
787
802
|
as follows:
|
|
@@ -796,15 +811,29 @@ parameter, which in our case will be the id of the article.
|
|
|
796
811
|
As we did before, we need to add the `show` action in
|
|
797
812
|
`app/controllers/articles_controller.rb` and its respective view.
|
|
798
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
|
+
|
|
799
822
|
```ruby
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
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
|
|
803
832
|
```
|
|
804
833
|
|
|
805
834
|
A couple of things to note. We use `Article.find` to find the article we're
|
|
806
835
|
interested in, passing in `params[:id]` to get the `:id` parameter from the
|
|
807
|
-
request. We also use an instance variable (prefixed
|
|
836
|
+
request. We also use an instance variable (prefixed with `@`) to hold a
|
|
808
837
|
reference to the article object. We do this because Rails will pass all instance
|
|
809
838
|
variables to the view.
|
|
810
839
|
|
|
@@ -838,15 +867,27 @@ articles GET /articles(.:format) articles#index
|
|
|
838
867
|
```
|
|
839
868
|
|
|
840
869
|
Add the corresponding `index` action for that route inside the
|
|
841
|
-
`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:
|
|
842
873
|
|
|
843
874
|
```ruby
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
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
|
|
847
888
|
```
|
|
848
889
|
|
|
849
|
-
And then finally, add view for this action, located at
|
|
890
|
+
And then finally, add the view for this action, located at
|
|
850
891
|
`app/views/articles/index.html.erb`:
|
|
851
892
|
|
|
852
893
|
```html+erb
|
|
@@ -867,7 +908,7 @@ And then finally, add view for this action, located at
|
|
|
867
908
|
</table>
|
|
868
909
|
```
|
|
869
910
|
|
|
870
|
-
Now if you go to
|
|
911
|
+
Now if you go to <http://localhost:3000/articles> you will see a list of all the
|
|
871
912
|
articles that you have created.
|
|
872
913
|
|
|
873
914
|
### Adding links
|
|
@@ -896,8 +937,8 @@ Let's add links to the other views as well, starting with adding this
|
|
|
896
937
|
|
|
897
938
|
This link will allow you to bring up the form that lets you create a new article.
|
|
898
939
|
|
|
899
|
-
|
|
900
|
-
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:
|
|
901
942
|
|
|
902
943
|
```erb
|
|
903
944
|
<%= form_for :article, url: articles_path do |f| %>
|
|
@@ -907,7 +948,7 @@ go back to the `index` action:
|
|
|
907
948
|
<%= link_to 'Back', articles_path %>
|
|
908
949
|
```
|
|
909
950
|
|
|
910
|
-
Finally, add
|
|
951
|
+
Finally, add a link to the `app/views/articles/show.html.erb` template to
|
|
911
952
|
go back to the `index` action as well, so that people who are viewing a single
|
|
912
953
|
article can go back and view the whole list again:
|
|
913
954
|
|
|
@@ -925,9 +966,9 @@ article can go back and view the whole list again:
|
|
|
925
966
|
<%= link_to 'Back', articles_path %>
|
|
926
967
|
```
|
|
927
968
|
|
|
928
|
-
TIP: If you want to link to an action in the same controller, you don't
|
|
929
|
-
|
|
930
|
-
|
|
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.
|
|
931
972
|
|
|
932
973
|
TIP: In development mode (which is what you're working in by default), Rails
|
|
933
974
|
reloads your application with every browser request, so there's no need to stop
|
|
@@ -962,7 +1003,7 @@ These changes will ensure that all articles have a title that is at least five
|
|
|
962
1003
|
characters long. Rails can validate a variety of conditions in a model,
|
|
963
1004
|
including the presence or uniqueness of columns, their format, and the
|
|
964
1005
|
existence of associated objects. Validations are covered in detail in [Active
|
|
965
|
-
Record Validations](active_record_validations.html)
|
|
1006
|
+
Record Validations](active_record_validations.html).
|
|
966
1007
|
|
|
967
1008
|
With the validation now in place, when you call `@article.save` on an invalid
|
|
968
1009
|
article, it will return `false`. If you open
|
|
@@ -1011,17 +1052,21 @@ something went wrong. To do that, you'll modify
|
|
|
1011
1052
|
|
|
1012
1053
|
```html+erb
|
|
1013
1054
|
<%= form_for :article, url: articles_path do |f| %>
|
|
1055
|
+
|
|
1014
1056
|
<% if @article.errors.any? %>
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
<
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
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>
|
|
1024
1068
|
<% end %>
|
|
1069
|
+
|
|
1025
1070
|
<p>
|
|
1026
1071
|
<%= f.label :title %><br>
|
|
1027
1072
|
<%= f.text_field :title %>
|
|
@@ -1035,6 +1080,7 @@ something went wrong. To do that, you'll modify
|
|
|
1035
1080
|
<p>
|
|
1036
1081
|
<%= f.submit %>
|
|
1037
1082
|
</p>
|
|
1083
|
+
|
|
1038
1084
|
<% end %>
|
|
1039
1085
|
|
|
1040
1086
|
<%= link_to 'Back', articles_path %>
|
|
@@ -1058,7 +1104,7 @@ standout.
|
|
|
1058
1104
|
|
|
1059
1105
|
Now you'll get a nice error message when saving an article without title when
|
|
1060
1106
|
you attempt to do just that on the new article form
|
|
1061
|
-
|
|
1107
|
+
<http://localhost:3000/articles/new>:
|
|
1062
1108
|
|
|
1063
1109
|

|
|
1064
1110
|
|
|
@@ -1067,12 +1113,27 @@ you attempt to do just that on the new article form
|
|
|
1067
1113
|
We've covered the "CR" part of CRUD. Now let's focus on the "U" part, updating
|
|
1068
1114
|
articles.
|
|
1069
1115
|
|
|
1070
|
-
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:
|
|
1071
1118
|
|
|
1072
1119
|
```ruby
|
|
1120
|
+
def new
|
|
1121
|
+
@article = Article.new
|
|
1122
|
+
end
|
|
1123
|
+
|
|
1073
1124
|
def edit
|
|
1074
1125
|
@article = Article.find(params[:id])
|
|
1075
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
|
|
1076
1137
|
```
|
|
1077
1138
|
|
|
1078
1139
|
The view will contain a form similar to the one we used when creating
|
|
@@ -1083,17 +1144,21 @@ it look as follows:
|
|
|
1083
1144
|
<h1>Editing article</h1>
|
|
1084
1145
|
|
|
1085
1146
|
<%= form_for :article, url: article_path(@article), method: :patch do |f| %>
|
|
1147
|
+
|
|
1086
1148
|
<% if @article.errors.any? %>
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
<
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
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>
|
|
1096
1160
|
<% end %>
|
|
1161
|
+
|
|
1097
1162
|
<p>
|
|
1098
1163
|
<%= f.label :title %><br>
|
|
1099
1164
|
<%= f.text_field :title %>
|
|
@@ -1107,6 +1172,7 @@ it look as follows:
|
|
|
1107
1172
|
<p>
|
|
1108
1173
|
<%= f.submit %>
|
|
1109
1174
|
</p>
|
|
1175
|
+
|
|
1110
1176
|
<% end %>
|
|
1111
1177
|
|
|
1112
1178
|
<%= link_to 'Back', articles_path %>
|
|
@@ -1121,14 +1187,26 @@ via the `PATCH` HTTP method which is the HTTP method you're expected to use to
|
|
|
1121
1187
|
|
|
1122
1188
|
The first parameter of `form_for` can be an object, say, `@article` which would
|
|
1123
1189
|
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]
|
|
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).
|
|
1127
1194
|
|
|
1128
|
-
Next we need to create the `update` action in
|
|
1129
|
-
`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:
|
|
1130
1198
|
|
|
1131
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
|
+
|
|
1132
1210
|
def update
|
|
1133
1211
|
@article = Article.find(params[:id])
|
|
1134
1212
|
|
|
@@ -1170,14 +1248,14 @@ it appear next to the "Show" link:
|
|
|
1170
1248
|
<th colspan="2"></th>
|
|
1171
1249
|
</tr>
|
|
1172
1250
|
|
|
1173
|
-
<% @articles.each do |article| %>
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
<% 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 %>
|
|
1181
1259
|
</table>
|
|
1182
1260
|
```
|
|
1183
1261
|
|
|
@@ -1188,8 +1266,8 @@ bottom of the template:
|
|
|
1188
1266
|
```html+erb
|
|
1189
1267
|
...
|
|
1190
1268
|
|
|
1191
|
-
<%= link_to 'Back', articles_path %>
|
|
1192
|
-
|
|
1269
|
+
<%= link_to 'Back', articles_path %> |
|
|
1270
|
+
<%= link_to 'Edit', edit_article_path(@article) %>
|
|
1193
1271
|
```
|
|
1194
1272
|
|
|
1195
1273
|
And here's how our app looks so far:
|
|
@@ -1198,10 +1276,10 @@ And here's how our app looks so far:
|
|
|
1198
1276
|
|
|
1199
1277
|
### Using partials to clean up duplication in views
|
|
1200
1278
|
|
|
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.
|
|
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.
|
|
1205
1283
|
|
|
1206
1284
|
TIP: You can read more about partials in the
|
|
1207
1285
|
[Layouts and Rendering in Rails](layouts_and_rendering.html) guide.
|
|
@@ -1211,17 +1289,21 @@ content:
|
|
|
1211
1289
|
|
|
1212
1290
|
```html+erb
|
|
1213
1291
|
<%= form_for @article do |f| %>
|
|
1292
|
+
|
|
1214
1293
|
<% if @article.errors.any? %>
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
<
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
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>
|
|
1224
1305
|
<% end %>
|
|
1306
|
+
|
|
1225
1307
|
<p>
|
|
1226
1308
|
<%= f.label :title %><br>
|
|
1227
1309
|
<%= f.text_field :title %>
|
|
@@ -1235,6 +1317,7 @@ content:
|
|
|
1235
1317
|
<p>
|
|
1236
1318
|
<%= f.submit %>
|
|
1237
1319
|
</p>
|
|
1320
|
+
|
|
1238
1321
|
<% end %>
|
|
1239
1322
|
```
|
|
1240
1323
|
|
|
@@ -1243,8 +1326,8 @@ The reason we can use this shorter, simpler `form_for` declaration
|
|
|
1243
1326
|
to stand in for either of the other forms is that `@article` is a *resource*
|
|
1244
1327
|
corresponding to a full set of RESTful routes, and Rails is able to infer
|
|
1245
1328
|
which URI and method to use.
|
|
1246
|
-
For more information about this use of `form_for`, see
|
|
1247
|
-
|
|
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).
|
|
1248
1331
|
|
|
1249
1332
|
Now, let's update the `app/views/articles/new.html.erb` view to use this new
|
|
1250
1333
|
partial, rewriting it completely:
|
|
@@ -1285,9 +1368,11 @@ people to craft malicious URLs like this:
|
|
|
1285
1368
|
<a href='http://example.com/articles/1/destroy'>look at this cat!</a>
|
|
1286
1369
|
```
|
|
1287
1370
|
|
|
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
|
|
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:
|
|
1291
1376
|
|
|
1292
1377
|
```ruby
|
|
1293
1378
|
def destroy
|
|
@@ -1298,13 +1383,67 @@ def destroy
|
|
|
1298
1383
|
end
|
|
1299
1384
|
```
|
|
1300
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
|
+
|
|
1301
1441
|
You can call `destroy` on Active Record objects when you want to delete
|
|
1302
1442
|
them from the database. Note that we don't need to add a view for this
|
|
1303
1443
|
action since we're redirecting to the `index` action.
|
|
1304
1444
|
|
|
1305
1445
|
Finally, add a 'Destroy' link to your `index` action template
|
|
1306
|
-
(`app/views/articles/index.html.erb`) to wrap everything
|
|
1307
|
-
together.
|
|
1446
|
+
(`app/views/articles/index.html.erb`) to wrap everything together.
|
|
1308
1447
|
|
|
1309
1448
|
```html+erb
|
|
1310
1449
|
<h1>Listing Articles</h1>
|
|
@@ -1316,16 +1455,17 @@ together.
|
|
|
1316
1455
|
<th colspan="3"></th>
|
|
1317
1456
|
</tr>
|
|
1318
1457
|
|
|
1319
|
-
<% @articles.each do |article| %>
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
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 %>
|
|
1329
1469
|
</table>
|
|
1330
1470
|
```
|
|
1331
1471
|
|
|
@@ -1343,9 +1483,8 @@ Without this file, the confirmation dialog box wouldn't appear.
|
|
|
1343
1483
|
Congratulations, you can now create, show, list, update and destroy
|
|
1344
1484
|
articles.
|
|
1345
1485
|
|
|
1346
|
-
TIP: In general, Rails encourages
|
|
1347
|
-
|
|
1348
|
-
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
|
|
1349
1488
|
[Rails Routing from the Outside In](routing.html).
|
|
1350
1489
|
|
|
1351
1490
|
Adding a Second Model
|
|
@@ -1398,7 +1537,7 @@ class CreateComments < ActiveRecord::Migration
|
|
|
1398
1537
|
# this line adds an integer column called `article_id`.
|
|
1399
1538
|
t.references :article, index: true
|
|
1400
1539
|
|
|
1401
|
-
t.timestamps
|
|
1540
|
+
t.timestamps null: false
|
|
1402
1541
|
end
|
|
1403
1542
|
end
|
|
1404
1543
|
end
|
|
@@ -1488,7 +1627,7 @@ controller. Again, we'll use the same generator we used before:
|
|
|
1488
1627
|
$ bin/rails generate controller Comments
|
|
1489
1628
|
```
|
|
1490
1629
|
|
|
1491
|
-
This creates
|
|
1630
|
+
This creates five files and one empty directory:
|
|
1492
1631
|
|
|
1493
1632
|
| File/Directory | Purpose |
|
|
1494
1633
|
| -------------------------------------------- | ---------------------------------------- |
|
|
@@ -1496,7 +1635,6 @@ This creates six files and one empty directory:
|
|
|
1496
1635
|
| app/views/comments/ | Views of the controller are stored here |
|
|
1497
1636
|
| test/controllers/comments_controller_test.rb | The test for the controller |
|
|
1498
1637
|
| app/helpers/comments_helper.rb | A view helper file |
|
|
1499
|
-
| test/helpers/comments_helper_test.rb | The test for the helper |
|
|
1500
1638
|
| app/assets/javascripts/comment.js.coffee | CoffeeScript for the controller |
|
|
1501
1639
|
| app/assets/stylesheets/comment.css.scss | Cascading style sheet for the controller |
|
|
1502
1640
|
|
|
@@ -1535,8 +1673,8 @@ So first, we'll wire up the Article show template
|
|
|
1535
1673
|
</p>
|
|
1536
1674
|
<% end %>
|
|
1537
1675
|
|
|
1538
|
-
<%= link_to 'Back', articles_path %>
|
|
1539
|
-
|
|
1676
|
+
<%= link_to 'Back', articles_path %> |
|
|
1677
|
+
<%= link_to 'Edit', edit_article_path(@article) %>
|
|
1540
1678
|
```
|
|
1541
1679
|
|
|
1542
1680
|
This adds a form on the `Article` show page that creates a new comment by
|
|
@@ -1730,7 +1868,7 @@ Then you make the `app/views/articles/show.html.erb` look like the following:
|
|
|
1730
1868
|
<%= render @article.comments %>
|
|
1731
1869
|
|
|
1732
1870
|
<h2>Add a comment:</h2>
|
|
1733
|
-
<%= render
|
|
1871
|
+
<%= render 'comments/form' %>
|
|
1734
1872
|
|
|
1735
1873
|
<%= link_to 'Edit Article', edit_article_path(@article) %> |
|
|
1736
1874
|
<%= link_to 'Back to Articles', articles_path %>
|
|
@@ -1806,8 +1944,8 @@ database and send us back to the show action for the article.
|
|
|
1806
1944
|
|
|
1807
1945
|
### Deleting Associated Objects
|
|
1808
1946
|
|
|
1809
|
-
If you delete an article
|
|
1810
|
-
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
|
|
1811
1949
|
you to use the `dependent` option of an association to achieve this. Modify the
|
|
1812
1950
|
Article model, `app/models/article.rb`, as follows:
|
|
1813
1951
|
|
|
@@ -1824,21 +1962,21 @@ Security
|
|
|
1824
1962
|
|
|
1825
1963
|
### Basic Authentication
|
|
1826
1964
|
|
|
1827
|
-
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
|
|
1828
1966
|
delete articles or delete comments.
|
|
1829
1967
|
|
|
1830
1968
|
Rails provides a very simple HTTP authentication system that will work nicely in
|
|
1831
1969
|
this situation.
|
|
1832
1970
|
|
|
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,
|
|
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
|
|
1836
1974
|
action if that method allows it.
|
|
1837
1975
|
|
|
1838
1976
|
To use the authentication system, we specify it at the top of our
|
|
1839
|
-
`ArticlesController
|
|
1840
|
-
every action
|
|
1841
|
-
|
|
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:
|
|
1842
1980
|
|
|
1843
1981
|
```ruby
|
|
1844
1982
|
class ArticlesController < ApplicationController
|
|
@@ -1862,14 +2000,14 @@ class CommentsController < ApplicationController
|
|
|
1862
2000
|
|
|
1863
2001
|
def create
|
|
1864
2002
|
@article = Article.find(params[:article_id])
|
|
1865
|
-
...
|
|
2003
|
+
# ...
|
|
1866
2004
|
end
|
|
1867
2005
|
|
|
1868
2006
|
# snipped for brevity
|
|
1869
2007
|
```
|
|
1870
2008
|
|
|
1871
2009
|
Now if you try to create a new article, you will be greeted with a basic HTTP
|
|
1872
|
-
Authentication challenge
|
|
2010
|
+
Authentication challenge:
|
|
1873
2011
|
|
|
1874
2012
|

|
|
1875
2013
|
|
|
@@ -1884,7 +2022,7 @@ along with a number of others.
|
|
|
1884
2022
|
|
|
1885
2023
|
Security, especially in web applications, is a broad and detailed area. Security
|
|
1886
2024
|
in your Rails application is covered in more depth in
|
|
1887
|
-
|
|
2025
|
+
the [Ruby on Rails Security Guide](security.html).
|
|
1888
2026
|
|
|
1889
2027
|
|
|
1890
2028
|
What's Next?
|
|
@@ -1895,7 +2033,7 @@ update it and experiment on your own. But you don't have to do everything
|
|
|
1895
2033
|
without help. As you need assistance getting up and running with Rails, feel
|
|
1896
2034
|
free to consult these support resources:
|
|
1897
2035
|
|
|
1898
|
-
* The [Ruby on Rails
|
|
2036
|
+
* The [Ruby on Rails Guides](index.html)
|
|
1899
2037
|
* The [Ruby on Rails Tutorial](http://railstutorial.org/book)
|
|
1900
2038
|
* The [Ruby on Rails mailing list](http://groups.google.com/group/rubyonrails-talk)
|
|
1901
2039
|
* The [#rubyonrails](irc://irc.freenode.net/#rubyonrails) channel on irc.freenode.net
|
|
@@ -1911,7 +2049,7 @@ command-line utility:
|
|
|
1911
2049
|
in your web browser to explore the API documentation.
|
|
1912
2050
|
|
|
1913
2051
|
TIP: To be able to generate the Rails Guides locally with the `doc:guides` rake
|
|
1914
|
-
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
|
|
1915
2053
|
`bundle install` and you're ready to go.
|
|
1916
2054
|
|
|
1917
2055
|
Configuration Gotchas
|