rails 4.1.14.2 → 4.2.11.1
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 +5 -5
- data/README.md +12 -10
- data/guides/CHANGELOG.md +34 -37
- 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 +1 -1
- data/guides/bug_report_templates/action_controller_master.rb +1 -0
- data/guides/bug_report_templates/active_record_gem.rb +1 -1
- data/guides/bug_report_templates/generic_gem.rb +1 -1
- 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 +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 +5 -6
- data/guides/source/4_2_release_notes.md +877 -0
- data/guides/source/_license.html.erb +1 -1
- data/guides/source/_welcome.html.erb +6 -8
- data/guides/source/action_controller_overview.md +25 -8
- data/guides/source/action_mailer_basics.md +97 -29
- data/guides/source/action_view_overview.md +142 -183
- data/guides/source/active_job_basics.md +339 -0
- data/guides/source/active_model_basics.md +371 -17
- data/guides/source/active_record_basics.md +25 -24
- data/guides/source/active_record_callbacks.md +12 -9
- data/guides/source/{migrations.md → active_record_migrations.md} +95 -220
- data/guides/source/active_record_postgresql.md +433 -0
- data/guides/source/active_record_querying.md +264 -268
- data/guides/source/active_record_validations.md +23 -13
- data/guides/source/active_support_core_extensions.md +114 -75
- data/guides/source/active_support_instrumentation.md +10 -18
- data/guides/source/api_documentation_guidelines.md +63 -17
- data/guides/source/asset_pipeline.md +258 -119
- data/guides/source/association_basics.md +96 -80
- data/guides/source/autoloading_and_reloading_constants.md +1311 -0
- data/guides/source/caching_with_rails.md +32 -7
- data/guides/source/command_line.md +52 -30
- data/guides/source/configuring.md +161 -33
- data/guides/source/contributing_to_ruby_on_rails.md +198 -114
- data/guides/source/credits.html.erb +2 -2
- data/guides/source/debugging_rails_applications.md +440 -286
- data/guides/source/development_dependencies_install.md +47 -36
- data/guides/source/documents.yaml +19 -7
- data/guides/source/engines.md +189 -189
- data/guides/source/form_helpers.md +79 -56
- data/guides/source/generators.md +24 -11
- data/guides/source/getting_started.md +359 -219
- data/guides/source/i18n.md +110 -66
- data/guides/source/index.html.erb +1 -0
- data/guides/source/initialization.md +109 -62
- data/guides/source/layout.html.erb +5 -11
- data/guides/source/layouts_and_rendering.md +26 -26
- data/guides/source/maintenance_policy.md +6 -3
- data/guides/source/nested_model_forms.md +7 -4
- data/guides/source/plugins.md +27 -27
- data/guides/source/rails_application_templates.md +21 -3
- data/guides/source/rails_on_rack.md +8 -5
- data/guides/source/routing.md +113 -73
- data/guides/source/ruby_on_rails_guides_guidelines.md +11 -12
- data/guides/source/security.md +39 -33
- data/guides/source/testing.md +199 -119
- data/guides/source/upgrading_ruby_on_rails.md +287 -29
- data/guides/source/working_with_javascript_in_rails.md +19 -17
- data/guides/w3c_validator.rb +2 -0
- metadata +40 -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
|
|
@@ -73,9 +73,8 @@ step needed to make this example application has been left out, so you can
|
|
|
73
73
|
literally follow along step by step.
|
|
74
74
|
|
|
75
75
|
By following along with this guide, you'll create a Rails project called
|
|
76
|
-
`blog`, a
|
|
77
|
-
|
|
78
|
-
make sure that you have Rails itself installed.
|
|
76
|
+
`blog`, a (very) simple weblog. Before you can start building the application,
|
|
77
|
+
you need to make sure that you have Rails itself installed.
|
|
79
78
|
|
|
80
79
|
TIP: The examples below use `$` to represent your terminal prompt in a UNIX-like OS,
|
|
81
80
|
though it may have been customized to appear differently. If you are using Windows,
|
|
@@ -88,7 +87,7 @@ Open up a command line prompt. On Mac OS X open Terminal.app, on Windows choose
|
|
|
88
87
|
dollar sign `$` should be run in the command line. Verify that you have a
|
|
89
88
|
current version of Ruby installed:
|
|
90
89
|
|
|
91
|
-
TIP
|
|
90
|
+
TIP: A number of tools exist to help you quickly install Ruby and Ruby
|
|
92
91
|
on Rails on your system. Windows users can use [Rails Installer](http://railsinstaller.org),
|
|
93
92
|
while Mac OS X users can use [Tokaido](https://github.com/tokaido/tokaidoapp).
|
|
94
93
|
|
|
@@ -98,11 +97,11 @@ ruby 2.0.0p353
|
|
|
98
97
|
```
|
|
99
98
|
|
|
100
99
|
If you don't have Ruby installed have a look at
|
|
101
|
-
[ruby-lang.org](https://www.ruby-lang.org/en/
|
|
100
|
+
[ruby-lang.org](https://www.ruby-lang.org/en/installation/) for possible ways to
|
|
102
101
|
install Ruby on your platform.
|
|
103
102
|
|
|
104
103
|
Many popular UNIX-like OSes ship with an acceptable version of SQLite3. Windows
|
|
105
|
-
users and others can find installation instructions at
|
|
104
|
+
users and others can find installation instructions at the [SQLite3 website](https://www.sqlite.org).
|
|
106
105
|
Verify that it is correctly installed and in your PATH:
|
|
107
106
|
|
|
108
107
|
```bash
|
|
@@ -121,10 +120,10 @@ To verify that you have everything installed correctly, you should be able to
|
|
|
121
120
|
run the following:
|
|
122
121
|
|
|
123
122
|
```bash
|
|
124
|
-
$
|
|
123
|
+
$ rails --version
|
|
125
124
|
```
|
|
126
125
|
|
|
127
|
-
If it says something like "Rails 4.
|
|
126
|
+
If it says something like "Rails 4.2.1", you are ready to continue.
|
|
128
127
|
|
|
129
128
|
### Creating the Blog Application
|
|
130
129
|
|
|
@@ -162,11 +161,11 @@ of the files and folders that Rails created by default:
|
|
|
162
161
|
| File/Folder | Purpose |
|
|
163
162
|
| ----------- | ------- |
|
|
164
163
|
|app/|Contains the controllers, models, views, helpers, mailers and assets for your application. You'll focus on this folder for the remainder of this guide.|
|
|
165
|
-
|bin/|Contains the rails script that starts your app and can contain other scripts you use to deploy or run your application.|
|
|
164
|
+
|bin/|Contains the rails script that starts your app and can contain other scripts you use to setup, deploy or run your application.|
|
|
166
165
|
|config/|Configure your application's routes, database, and more. This is covered in more detail in [Configuring Rails Applications](configuring.html).|
|
|
167
166
|
|config.ru|Rack configuration for Rack based servers used to start the application.|
|
|
168
167
|
|db/|Contains your current database schema, as well as the database migrations.|
|
|
169
|
-
|Gemfile<br>Gemfile.lock|These files allow you to specify what gem dependencies are needed for your Rails application. These files are used by the Bundler gem. For more information about Bundler, see
|
|
168
|
+
|Gemfile<br>Gemfile.lock|These files allow you to specify what gem dependencies are needed for your Rails application. These files are used by the Bundler gem. For more information about Bundler, see the [Bundler website](http://bundler.io).|
|
|
170
169
|
|lib/|Extended modules for your application.|
|
|
171
170
|
|log/|Application log files.|
|
|
172
171
|
|public/|The only folder seen by the world as-is. Contains static files and compiled assets.|
|
|
@@ -192,14 +191,18 @@ following in the `blog` directory:
|
|
|
192
191
|
$ bin/rails server
|
|
193
192
|
```
|
|
194
193
|
|
|
195
|
-
TIP:
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
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).
|
|
203
206
|
|
|
204
207
|
This will fire up WEBrick, a web server distributed with Ruby by default. To see
|
|
205
208
|
your application in action, open a browser window and navigate to
|
|
@@ -257,8 +260,6 @@ invoke test_unit
|
|
|
257
260
|
create test/controllers/welcome_controller_test.rb
|
|
258
261
|
invoke helper
|
|
259
262
|
create app/helpers/welcome_helper.rb
|
|
260
|
-
invoke test_unit
|
|
261
|
-
create test/helpers/welcome_helper_test.rb
|
|
262
263
|
invoke assets
|
|
263
264
|
invoke coffee
|
|
264
265
|
create app/assets/javascripts/welcome.js.coffee
|
|
@@ -266,8 +267,9 @@ invoke scss
|
|
|
266
267
|
create app/assets/stylesheets/welcome.css.scss
|
|
267
268
|
```
|
|
268
269
|
|
|
269
|
-
Most important of these are of course the controller, located at
|
|
270
|
-
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`.
|
|
271
273
|
|
|
272
274
|
Open the `app/views/welcome/index.html.erb` file in your text editor. Delete all
|
|
273
275
|
of the existing code in the file, and replace it with the following single line
|
|
@@ -316,9 +318,9 @@ root 'welcome#index'
|
|
|
316
318
|
application to the welcome controller's index action and `get 'welcome/index'`
|
|
317
319
|
tells Rails to map requests to <http://localhost:3000/welcome/index> to the
|
|
318
320
|
welcome controller's index action. This was created earlier when you ran the
|
|
319
|
-
controller generator (`rails generate controller welcome index`).
|
|
321
|
+
controller generator (`bin/rails generate controller welcome index`).
|
|
320
322
|
|
|
321
|
-
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
|
|
322
324
|
server`) and navigate to <http://localhost:3000> in your browser. You'll see the
|
|
323
325
|
"Hello, Rails!" message you put into `app/views/welcome/index.html.erb`,
|
|
324
326
|
indicating that this new route is indeed going to `WelcomeController`'s `index`
|
|
@@ -339,8 +341,8 @@ You can create, read, update and destroy items for a resource and these
|
|
|
339
341
|
operations are referred to as _CRUD_ operations.
|
|
340
342
|
|
|
341
343
|
Rails provides a `resources` method which can be used to declare a standard REST
|
|
342
|
-
resource.
|
|
343
|
-
|
|
344
|
+
resource. You need to add the _article resource_ to the
|
|
345
|
+
`config/routes.rb` as follows:
|
|
344
346
|
|
|
345
347
|
```ruby
|
|
346
348
|
Rails.application.routes.draw do
|
|
@@ -351,7 +353,7 @@ Rails.application.routes.draw do
|
|
|
351
353
|
end
|
|
352
354
|
```
|
|
353
355
|
|
|
354
|
-
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
|
|
355
357
|
standard RESTful actions. The meaning of the prefix column (and other columns)
|
|
356
358
|
will be seen later, but for now notice that Rails has inferred the
|
|
357
359
|
singular form `article` and makes meaningful use of the distinction.
|
|
@@ -395,7 +397,7 @@ a controller called `ArticlesController`. You can do this by running this
|
|
|
395
397
|
command:
|
|
396
398
|
|
|
397
399
|
```bash
|
|
398
|
-
$ bin/rails
|
|
400
|
+
$ bin/rails generate controller articles
|
|
399
401
|
```
|
|
400
402
|
|
|
401
403
|
If you open up the newly generated `app/controllers/articles_controller.rb`
|
|
@@ -426,19 +428,22 @@ are generated in Rails they are empty by default, unless you tell it
|
|
|
426
428
|
your wanted actions during the generation process.
|
|
427
429
|
|
|
428
430
|
To manually define an action inside a controller, all you need to do is to
|
|
429
|
-
define a new method inside the controller.
|
|
430
|
-
|
|
431
|
-
class, define a `new` method like this:
|
|
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:
|
|
432
434
|
|
|
433
435
|
```ruby
|
|
434
|
-
|
|
436
|
+
class ArticlesController < ApplicationController
|
|
437
|
+
def new
|
|
438
|
+
end
|
|
435
439
|
end
|
|
436
440
|
```
|
|
437
441
|
|
|
438
442
|
With the `new` method defined in `ArticlesController`, if you refresh
|
|
439
443
|
<http://localhost:3000/articles/new> you'll see another error:
|
|
440
444
|
|
|
441
|
-
![Template is missing for articles/new]
|
|
445
|
+
![Template is missing for articles/new]
|
|
446
|
+
(images/getting_started/template_is_missing_articles_new.png)
|
|
442
447
|
|
|
443
448
|
You're getting this error now because Rails expects plain actions like this one
|
|
444
449
|
to have views associated with them to display their information. With no view
|
|
@@ -447,9 +452,7 @@ available, Rails errors out.
|
|
|
447
452
|
In the above image, the bottom line has been truncated. Let's see what the full
|
|
448
453
|
thing looks like:
|
|
449
454
|
|
|
450
|
-
|
|
451
|
-
Missing template articles/new, application/new with {locale:[:en], formats:[:html], handlers:[:erb, :builder, :coffee]}. Searched in: * "/path/to/blog/app/views"
|
|
452
|
-
</blockquote>
|
|
455
|
+
>Missing template articles/new, application/new with {locale:[:en], formats:[:html], handlers:[:erb, :builder, :coffee]}. Searched in: * "/path/to/blog/app/views"
|
|
453
456
|
|
|
454
457
|
That's quite a lot of text! Let's quickly go through and understand what each
|
|
455
458
|
part of it does.
|
|
@@ -495,8 +498,8 @@ harmoniously! It's time to create the form for a new article.
|
|
|
495
498
|
|
|
496
499
|
### The first form
|
|
497
500
|
|
|
498
|
-
To create a form within this template, you will use a
|
|
499
|
-
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
|
|
500
503
|
method called `form_for`. To use this method, add this code into
|
|
501
504
|
`app/views/articles/new.html.erb`:
|
|
502
505
|
|
|
@@ -548,7 +551,7 @@ this:
|
|
|
548
551
|
|
|
549
552
|
In this example, the `articles_path` helper is passed to the `:url` option.
|
|
550
553
|
To see what Rails will do with this, we look back at the output of
|
|
551
|
-
`rake routes`:
|
|
554
|
+
`bin/rake routes`:
|
|
552
555
|
|
|
553
556
|
```bash
|
|
554
557
|
$ bin/rake routes
|
|
@@ -564,18 +567,18 @@ edit_article GET /articles/:id/edit(.:format) articles#edit
|
|
|
564
567
|
root GET / welcome#index
|
|
565
568
|
```
|
|
566
569
|
|
|
567
|
-
The `articles_path` helper tells Rails to point the form
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
`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`.
|
|
572
574
|
|
|
573
575
|
With the form and its associated route defined, you will be able to fill in the
|
|
574
576
|
form and then click the submit button to begin the process of creating a new
|
|
575
577
|
article, so go ahead and do that. When you submit the form, you should see a
|
|
576
578
|
familiar error:
|
|
577
579
|
|
|
578
|
-
![Unknown action create for ArticlesController]
|
|
580
|
+
![Unknown action create for ArticlesController]
|
|
581
|
+
(images/getting_started/unknown_action_create_for_articles.png)
|
|
579
582
|
|
|
580
583
|
You now need to create the `create` action within the `ArticlesController` for
|
|
581
584
|
this to work.
|
|
@@ -584,7 +587,7 @@ this to work.
|
|
|
584
587
|
|
|
585
588
|
To make the "Unknown action" go away, you can define a `create` action within
|
|
586
589
|
the `ArticlesController` class in `app/controllers/articles_controller.rb`,
|
|
587
|
-
underneath the `new` action:
|
|
590
|
+
underneath the `new` action, as shown:
|
|
588
591
|
|
|
589
592
|
```ruby
|
|
590
593
|
class ArticlesController < ApplicationController
|
|
@@ -618,6 +621,8 @@ method returns an `ActiveSupport::HashWithIndifferentAccess` object, which
|
|
|
618
621
|
allows you to access the keys of the hash using either strings or symbols. In
|
|
619
622
|
this situation, the only parameters that matter are the ones from the form.
|
|
620
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
|
+
|
|
621
626
|
If you re-submit the form one more time you'll now no longer get the missing
|
|
622
627
|
template error. Instead, you'll see something that looks like the following:
|
|
623
628
|
|
|
@@ -631,10 +636,10 @@ parameters but nothing in particular is being done with them.
|
|
|
631
636
|
|
|
632
637
|
### Creating the Article model
|
|
633
638
|
|
|
634
|
-
Models in Rails use a singular name, and their corresponding database tables
|
|
635
|
-
a plural name. Rails provides a generator for creating models, which
|
|
636
|
-
|
|
637
|
-
|
|
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:
|
|
638
643
|
|
|
639
644
|
```bash
|
|
640
645
|
$ bin/rails generate model Article title:string text:text
|
|
@@ -645,26 +650,23 @@ with a _title_ attribute of type string, and a _text_ attribute
|
|
|
645
650
|
of type text. Those attributes are automatically added to the `articles`
|
|
646
651
|
table in the database and mapped to the `Article` model.
|
|
647
652
|
|
|
648
|
-
Rails responded by creating a bunch of files. For
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
for creating the database structure, which is what we'll look at next.
|
|
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.
|
|
653
657
|
|
|
654
|
-
TIP: Active Record is smart enough to automatically map column names to
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
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.
|
|
658
661
|
|
|
659
662
|
### Running a Migration
|
|
660
663
|
|
|
661
|
-
As we've just seen, `rails generate model` created a _database
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
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.
|
|
668
670
|
|
|
669
671
|
If you look in the `db/migrate/20140120191729_create_articles.rb` file (remember,
|
|
670
672
|
yours will have a slightly different name), here's what you'll find:
|
|
@@ -676,7 +678,7 @@ class CreateArticles < ActiveRecord::Migration
|
|
|
676
678
|
t.string :title
|
|
677
679
|
t.text :text
|
|
678
680
|
|
|
679
|
-
t.timestamps
|
|
681
|
+
t.timestamps null: false
|
|
680
682
|
end
|
|
681
683
|
end
|
|
682
684
|
end
|
|
@@ -689,8 +691,8 @@ in case you want to reverse it later. When you run this migration it will create
|
|
|
689
691
|
an `articles` table with one string column and a text column. It also creates
|
|
690
692
|
two timestamp fields to allow Rails to track article creation and update times.
|
|
691
693
|
|
|
692
|
-
TIP: For more information about migrations, refer to [Rails Database
|
|
693
|
-
|
|
694
|
+
TIP: For more information about migrations, refer to [Rails Database Migrations]
|
|
695
|
+
(migrations.html).
|
|
694
696
|
|
|
695
697
|
At this point, you can use a rake command to run the migration:
|
|
696
698
|
|
|
@@ -712,7 +714,7 @@ NOTE. Because you're working in the development environment by default, this
|
|
|
712
714
|
command will apply to the database defined in the `development` section of your
|
|
713
715
|
`config/database.yml` file. If you would like to execute migrations in another
|
|
714
716
|
environment, for instance in production, you must explicitly pass it when
|
|
715
|
-
invoking the command: `rake db:migrate RAILS_ENV=production`.
|
|
717
|
+
invoking the command: `bin/rake db:migrate RAILS_ENV=production`.
|
|
716
718
|
|
|
717
719
|
### Saving data in the controller
|
|
718
720
|
|
|
@@ -732,26 +734,48 @@ end
|
|
|
732
734
|
|
|
733
735
|
Here's what's going on: every Rails model can be initialized with its
|
|
734
736
|
respective attributes, which are automatically mapped to the respective
|
|
735
|
-
database columns. In the first line we do just that
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
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.
|
|
739
741
|
|
|
740
|
-
TIP:
|
|
741
|
-
whether the article was saved or not.
|
|
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.
|
|
742
743
|
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
article. Try it! You should get an error that looks like this:
|
|
744
|
+
TIP: As we'll see later, `@article.save` returns a boolean indicating whether
|
|
745
|
+
the article was saved or not.
|
|
746
746
|
|
|
747
|
-
|
|
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:
|
|
749
|
+
|
|
750
|
+
![Forbidden attributes for new article]
|
|
751
|
+
(images/getting_started/forbidden_attributes_for_new_article.png)
|
|
748
752
|
|
|
749
753
|
Rails has several security features that help you write secure applications,
|
|
750
|
-
and you're running into one of them now. This one is called
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
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:
|
|
755
779
|
|
|
756
780
|
```ruby
|
|
757
781
|
def create
|
|
@@ -767,22 +791,17 @@ private
|
|
|
767
791
|
end
|
|
768
792
|
```
|
|
769
793
|
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
TIP: Note that `def article_params` is private. This new approach prevents an
|
|
774
|
-
attacker from setting the model's attributes by manipulating the hash passed to
|
|
775
|
-
the model.
|
|
776
|
-
For more information, refer to
|
|
777
|
-
[this blog article about Strong Parameters](http://weblog.rubyonrails.org/2012/3/21/strong-parameters/).
|
|
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/).
|
|
778
797
|
|
|
779
798
|
### Showing Articles
|
|
780
799
|
|
|
781
|
-
If you submit the form again now, Rails will complain about not finding
|
|
782
|
-
|
|
783
|
-
|
|
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.
|
|
784
803
|
|
|
785
|
-
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
|
|
786
805
|
as follows:
|
|
787
806
|
|
|
788
807
|
```
|
|
@@ -795,15 +814,29 @@ parameter, which in our case will be the id of the article.
|
|
|
795
814
|
As we did before, we need to add the `show` action in
|
|
796
815
|
`app/controllers/articles_controller.rb` and its respective view.
|
|
797
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
|
+
|
|
798
825
|
```ruby
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
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
|
|
802
835
|
```
|
|
803
836
|
|
|
804
837
|
A couple of things to note. We use `Article.find` to find the article we're
|
|
805
838
|
interested in, passing in `params[:id]` to get the `:id` parameter from the
|
|
806
|
-
request. We also use an instance variable (prefixed
|
|
839
|
+
request. We also use an instance variable (prefixed with `@`) to hold a
|
|
807
840
|
reference to the article object. We do this because Rails will pass all instance
|
|
808
841
|
variables to the view.
|
|
809
842
|
|
|
@@ -830,22 +863,34 @@ Visit <http://localhost:3000/articles/new> and give it a try!
|
|
|
830
863
|
### Listing all articles
|
|
831
864
|
|
|
832
865
|
We still need a way to list all our articles, so let's do that.
|
|
833
|
-
The route for this as per output of `rake routes` is:
|
|
866
|
+
The route for this as per output of `bin/rake routes` is:
|
|
834
867
|
|
|
835
868
|
```
|
|
836
869
|
articles GET /articles(.:format) articles#index
|
|
837
870
|
```
|
|
838
871
|
|
|
839
872
|
Add the corresponding `index` action for that route inside the
|
|
840
|
-
`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:
|
|
841
876
|
|
|
842
877
|
```ruby
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
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
|
|
846
891
|
```
|
|
847
892
|
|
|
848
|
-
And then finally, add view for this action, located at
|
|
893
|
+
And then finally, add the view for this action, located at
|
|
849
894
|
`app/views/articles/index.html.erb`:
|
|
850
895
|
|
|
851
896
|
```html+erb
|
|
@@ -866,7 +911,7 @@ And then finally, add view for this action, located at
|
|
|
866
911
|
</table>
|
|
867
912
|
```
|
|
868
913
|
|
|
869
|
-
Now if you go to
|
|
914
|
+
Now if you go to <http://localhost:3000/articles> you will see a list of all the
|
|
870
915
|
articles that you have created.
|
|
871
916
|
|
|
872
917
|
### Adding links
|
|
@@ -895,8 +940,8 @@ Let's add links to the other views as well, starting with adding this
|
|
|
895
940
|
|
|
896
941
|
This link will allow you to bring up the form that lets you create a new article.
|
|
897
942
|
|
|
898
|
-
|
|
899
|
-
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:
|
|
900
945
|
|
|
901
946
|
```erb
|
|
902
947
|
<%= form_for :article, url: articles_path do |f| %>
|
|
@@ -906,7 +951,7 @@ go back to the `index` action:
|
|
|
906
951
|
<%= link_to 'Back', articles_path %>
|
|
907
952
|
```
|
|
908
953
|
|
|
909
|
-
Finally, add
|
|
954
|
+
Finally, add a link to the `app/views/articles/show.html.erb` template to
|
|
910
955
|
go back to the `index` action as well, so that people who are viewing a single
|
|
911
956
|
article can go back and view the whole list again:
|
|
912
957
|
|
|
@@ -924,9 +969,9 @@ article can go back and view the whole list again:
|
|
|
924
969
|
<%= link_to 'Back', articles_path %>
|
|
925
970
|
```
|
|
926
971
|
|
|
927
|
-
TIP: If you want to link to an action in the same controller, you don't
|
|
928
|
-
|
|
929
|
-
|
|
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.
|
|
930
975
|
|
|
931
976
|
TIP: In development mode (which is what you're working in by default), Rails
|
|
932
977
|
reloads your application with every browser request, so there's no need to stop
|
|
@@ -961,7 +1006,7 @@ These changes will ensure that all articles have a title that is at least five
|
|
|
961
1006
|
characters long. Rails can validate a variety of conditions in a model,
|
|
962
1007
|
including the presence or uniqueness of columns, their format, and the
|
|
963
1008
|
existence of associated objects. Validations are covered in detail in [Active
|
|
964
|
-
Record Validations](active_record_validations.html)
|
|
1009
|
+
Record Validations](active_record_validations.html).
|
|
965
1010
|
|
|
966
1011
|
With the validation now in place, when you call `@article.save` on an invalid
|
|
967
1012
|
article, it will return `false`. If you open
|
|
@@ -1010,17 +1055,21 @@ something went wrong. To do that, you'll modify
|
|
|
1010
1055
|
|
|
1011
1056
|
```html+erb
|
|
1012
1057
|
<%= form_for :article, url: articles_path do |f| %>
|
|
1058
|
+
|
|
1013
1059
|
<% if @article.errors.any? %>
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
<
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
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>
|
|
1023
1071
|
<% end %>
|
|
1072
|
+
|
|
1024
1073
|
<p>
|
|
1025
1074
|
<%= f.label :title %><br>
|
|
1026
1075
|
<%= f.text_field :title %>
|
|
@@ -1034,6 +1083,7 @@ something went wrong. To do that, you'll modify
|
|
|
1034
1083
|
<p>
|
|
1035
1084
|
<%= f.submit %>
|
|
1036
1085
|
</p>
|
|
1086
|
+
|
|
1037
1087
|
<% end %>
|
|
1038
1088
|
|
|
1039
1089
|
<%= link_to 'Back', articles_path %>
|
|
@@ -1057,7 +1107,7 @@ standout.
|
|
|
1057
1107
|
|
|
1058
1108
|
Now you'll get a nice error message when saving an article without title when
|
|
1059
1109
|
you attempt to do just that on the new article form
|
|
1060
|
-
|
|
1110
|
+
<http://localhost:3000/articles/new>:
|
|
1061
1111
|
|
|
1062
1112
|

|
|
1063
1113
|
|
|
@@ -1066,12 +1116,27 @@ you attempt to do just that on the new article form
|
|
|
1066
1116
|
We've covered the "CR" part of CRUD. Now let's focus on the "U" part, updating
|
|
1067
1117
|
articles.
|
|
1068
1118
|
|
|
1069
|
-
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:
|
|
1070
1121
|
|
|
1071
1122
|
```ruby
|
|
1123
|
+
def new
|
|
1124
|
+
@article = Article.new
|
|
1125
|
+
end
|
|
1126
|
+
|
|
1072
1127
|
def edit
|
|
1073
1128
|
@article = Article.find(params[:id])
|
|
1074
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
|
|
1075
1140
|
```
|
|
1076
1141
|
|
|
1077
1142
|
The view will contain a form similar to the one we used when creating
|
|
@@ -1082,17 +1147,21 @@ it look as follows:
|
|
|
1082
1147
|
<h1>Editing article</h1>
|
|
1083
1148
|
|
|
1084
1149
|
<%= form_for :article, url: article_path(@article), method: :patch do |f| %>
|
|
1150
|
+
|
|
1085
1151
|
<% if @article.errors.any? %>
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
<
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
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>
|
|
1095
1163
|
<% end %>
|
|
1164
|
+
|
|
1096
1165
|
<p>
|
|
1097
1166
|
<%= f.label :title %><br>
|
|
1098
1167
|
<%= f.text_field :title %>
|
|
@@ -1106,6 +1175,7 @@ it look as follows:
|
|
|
1106
1175
|
<p>
|
|
1107
1176
|
<%= f.submit %>
|
|
1108
1177
|
</p>
|
|
1178
|
+
|
|
1109
1179
|
<% end %>
|
|
1110
1180
|
|
|
1111
1181
|
<%= link_to 'Back', articles_path %>
|
|
@@ -1120,14 +1190,26 @@ via the `PATCH` HTTP method which is the HTTP method you're expected to use to
|
|
|
1120
1190
|
|
|
1121
1191
|
The first parameter of `form_for` can be an object, say, `@article` which would
|
|
1122
1192
|
cause the helper to fill in the form with the fields of the object. Passing in a
|
|
1123
|
-
symbol (`:article`) with the same name as the instance variable (`@article`)
|
|
1124
|
-
automagically leads to the same behavior. This is what is happening here.
|
|
1125
|
-
can be found in [form_for documentation]
|
|
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).
|
|
1126
1197
|
|
|
1127
|
-
Next we need to create the `update` action in
|
|
1128
|
-
`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:
|
|
1129
1201
|
|
|
1130
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
|
+
|
|
1131
1213
|
def update
|
|
1132
1214
|
@article = Article.find(params[:id])
|
|
1133
1215
|
|
|
@@ -1169,14 +1251,14 @@ it appear next to the "Show" link:
|
|
|
1169
1251
|
<th colspan="2"></th>
|
|
1170
1252
|
</tr>
|
|
1171
1253
|
|
|
1172
|
-
<% @articles.each do |article| %>
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
<% 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 %>
|
|
1180
1262
|
</table>
|
|
1181
1263
|
```
|
|
1182
1264
|
|
|
@@ -1187,8 +1269,8 @@ bottom of the template:
|
|
|
1187
1269
|
```html+erb
|
|
1188
1270
|
...
|
|
1189
1271
|
|
|
1272
|
+
<%= link_to 'Edit', edit_article_path(@article) %> |
|
|
1190
1273
|
<%= link_to 'Back', articles_path %>
|
|
1191
|
-
| <%= link_to 'Edit', edit_article_path(@article) %>
|
|
1192
1274
|
```
|
|
1193
1275
|
|
|
1194
1276
|
And here's how our app looks so far:
|
|
@@ -1197,10 +1279,10 @@ And here's how our app looks so far:
|
|
|
1197
1279
|
|
|
1198
1280
|
### Using partials to clean up duplication in views
|
|
1199
1281
|
|
|
1200
|
-
Our `edit` page looks very similar to the `new` page
|
|
1201
|
-
both share the same code for displaying the form. Let's remove
|
|
1202
|
-
by using a view partial. By convention, partial files are
|
|
1203
|
-
underscore.
|
|
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.
|
|
1204
1286
|
|
|
1205
1287
|
TIP: You can read more about partials in the
|
|
1206
1288
|
[Layouts and Rendering in Rails](layouts_and_rendering.html) guide.
|
|
@@ -1210,17 +1292,21 @@ content:
|
|
|
1210
1292
|
|
|
1211
1293
|
```html+erb
|
|
1212
1294
|
<%= form_for @article do |f| %>
|
|
1295
|
+
|
|
1213
1296
|
<% if @article.errors.any? %>
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
<
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
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>
|
|
1223
1308
|
<% end %>
|
|
1309
|
+
|
|
1224
1310
|
<p>
|
|
1225
1311
|
<%= f.label :title %><br>
|
|
1226
1312
|
<%= f.text_field :title %>
|
|
@@ -1234,6 +1320,7 @@ content:
|
|
|
1234
1320
|
<p>
|
|
1235
1321
|
<%= f.submit %>
|
|
1236
1322
|
</p>
|
|
1323
|
+
|
|
1237
1324
|
<% end %>
|
|
1238
1325
|
```
|
|
1239
1326
|
|
|
@@ -1242,8 +1329,8 @@ The reason we can use this shorter, simpler `form_for` declaration
|
|
|
1242
1329
|
to stand in for either of the other forms is that `@article` is a *resource*
|
|
1243
1330
|
corresponding to a full set of RESTful routes, and Rails is able to infer
|
|
1244
1331
|
which URI and method to use.
|
|
1245
|
-
For more information about this use of `form_for`, see
|
|
1246
|
-
|
|
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).
|
|
1247
1334
|
|
|
1248
1335
|
Now, let's update the `app/views/articles/new.html.erb` view to use this new
|
|
1249
1336
|
partial, rewriting it completely:
|
|
@@ -1270,7 +1357,7 @@ Then do the same for the `app/views/articles/edit.html.erb` view:
|
|
|
1270
1357
|
|
|
1271
1358
|
We're now ready to cover the "D" part of CRUD, deleting articles from the
|
|
1272
1359
|
database. Following the REST convention, the route for
|
|
1273
|
-
deleting articles as per output of `rake routes` is:
|
|
1360
|
+
deleting articles as per output of `bin/rake routes` is:
|
|
1274
1361
|
|
|
1275
1362
|
```ruby
|
|
1276
1363
|
DELETE /articles/:id(.:format) articles#destroy
|
|
@@ -1284,9 +1371,11 @@ people to craft malicious URLs like this:
|
|
|
1284
1371
|
<a href='http://example.com/articles/1/destroy'>look at this cat!</a>
|
|
1285
1372
|
```
|
|
1286
1373
|
|
|
1287
|
-
We use the `delete` method for destroying resources, and this route is mapped
|
|
1288
|
-
the `destroy` action inside `app/controllers/articles_controller.rb`, which
|
|
1289
|
-
doesn't exist yet
|
|
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:
|
|
1290
1379
|
|
|
1291
1380
|
```ruby
|
|
1292
1381
|
def destroy
|
|
@@ -1297,13 +1386,67 @@ def destroy
|
|
|
1297
1386
|
end
|
|
1298
1387
|
```
|
|
1299
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
|
+
|
|
1300
1444
|
You can call `destroy` on Active Record objects when you want to delete
|
|
1301
1445
|
them from the database. Note that we don't need to add a view for this
|
|
1302
1446
|
action since we're redirecting to the `index` action.
|
|
1303
1447
|
|
|
1304
1448
|
Finally, add a 'Destroy' link to your `index` action template
|
|
1305
|
-
(`app/views/articles/index.html.erb`) to wrap everything
|
|
1306
|
-
together.
|
|
1449
|
+
(`app/views/articles/index.html.erb`) to wrap everything together.
|
|
1307
1450
|
|
|
1308
1451
|
```html+erb
|
|
1309
1452
|
<h1>Listing Articles</h1>
|
|
@@ -1315,16 +1458,17 @@ together.
|
|
|
1315
1458
|
<th colspan="3"></th>
|
|
1316
1459
|
</tr>
|
|
1317
1460
|
|
|
1318
|
-
<% @articles.each do |article| %>
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
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 %>
|
|
1328
1472
|
</table>
|
|
1329
1473
|
```
|
|
1330
1474
|
|
|
@@ -1342,9 +1486,8 @@ Without this file, the confirmation dialog box wouldn't appear.
|
|
|
1342
1486
|
Congratulations, you can now create, show, list, update and destroy
|
|
1343
1487
|
articles.
|
|
1344
1488
|
|
|
1345
|
-
TIP: In general, Rails encourages
|
|
1346
|
-
|
|
1347
|
-
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
|
|
1348
1491
|
[Rails Routing from the Outside In](routing.html).
|
|
1349
1492
|
|
|
1350
1493
|
Adding a Second Model
|
|
@@ -1393,19 +1536,17 @@ class CreateComments < ActiveRecord::Migration
|
|
|
1393
1536
|
create_table :comments do |t|
|
|
1394
1537
|
t.string :commenter
|
|
1395
1538
|
t.text :body
|
|
1539
|
+
t.references :article, index: true, foreign_key: true
|
|
1396
1540
|
|
|
1397
|
-
|
|
1398
|
-
t.references :article, index: true
|
|
1399
|
-
|
|
1400
|
-
t.timestamps
|
|
1541
|
+
t.timestamps null: false
|
|
1401
1542
|
end
|
|
1402
1543
|
end
|
|
1403
1544
|
end
|
|
1404
1545
|
```
|
|
1405
1546
|
|
|
1406
|
-
The `t.references` line
|
|
1407
|
-
|
|
1408
|
-
|
|
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:
|
|
1409
1550
|
|
|
1410
1551
|
```bash
|
|
1411
1552
|
$ bin/rake db:migrate
|
|
@@ -1487,7 +1628,7 @@ controller. Again, we'll use the same generator we used before:
|
|
|
1487
1628
|
$ bin/rails generate controller Comments
|
|
1488
1629
|
```
|
|
1489
1630
|
|
|
1490
|
-
This creates
|
|
1631
|
+
This creates five files and one empty directory:
|
|
1491
1632
|
|
|
1492
1633
|
| File/Directory | Purpose |
|
|
1493
1634
|
| -------------------------------------------- | ---------------------------------------- |
|
|
@@ -1495,7 +1636,6 @@ This creates six files and one empty directory:
|
|
|
1495
1636
|
| app/views/comments/ | Views of the controller are stored here |
|
|
1496
1637
|
| test/controllers/comments_controller_test.rb | The test for the controller |
|
|
1497
1638
|
| app/helpers/comments_helper.rb | A view helper file |
|
|
1498
|
-
| test/helpers/comments_helper_test.rb | The test for the helper |
|
|
1499
1639
|
| app/assets/javascripts/comment.js.coffee | CoffeeScript for the controller |
|
|
1500
1640
|
| app/assets/stylesheets/comment.css.scss | Cascading style sheet for the controller |
|
|
1501
1641
|
|
|
@@ -1534,8 +1674,8 @@ So first, we'll wire up the Article show template
|
|
|
1534
1674
|
</p>
|
|
1535
1675
|
<% end %>
|
|
1536
1676
|
|
|
1677
|
+
<%= link_to 'Edit', edit_article_path(@article) %> |
|
|
1537
1678
|
<%= link_to 'Back', articles_path %>
|
|
1538
|
-
| <%= link_to 'Edit', edit_article_path(@article) %>
|
|
1539
1679
|
```
|
|
1540
1680
|
|
|
1541
1681
|
This adds a form on the `Article` show page that creates a new comment by
|
|
@@ -1615,8 +1755,8 @@ add that to the `app/views/articles/show.html.erb`.
|
|
|
1615
1755
|
</p>
|
|
1616
1756
|
<% end %>
|
|
1617
1757
|
|
|
1618
|
-
<%= link_to 'Edit
|
|
1619
|
-
<%= link_to 'Back
|
|
1758
|
+
<%= link_to 'Edit', edit_article_path(@article) %> |
|
|
1759
|
+
<%= link_to 'Back', articles_path %>
|
|
1620
1760
|
```
|
|
1621
1761
|
|
|
1622
1762
|
Now you can add articles and comments to your blog and have them show up in the
|
|
@@ -1681,8 +1821,8 @@ following:
|
|
|
1681
1821
|
</p>
|
|
1682
1822
|
<% end %>
|
|
1683
1823
|
|
|
1684
|
-
<%= link_to 'Edit
|
|
1685
|
-
<%= link_to 'Back
|
|
1824
|
+
<%= link_to 'Edit', edit_article_path(@article) %> |
|
|
1825
|
+
<%= link_to 'Back', articles_path %>
|
|
1686
1826
|
```
|
|
1687
1827
|
|
|
1688
1828
|
This will now render the partial in `app/views/comments/_comment.html.erb` once
|
|
@@ -1729,10 +1869,10 @@ Then you make the `app/views/articles/show.html.erb` look like the following:
|
|
|
1729
1869
|
<%= render @article.comments %>
|
|
1730
1870
|
|
|
1731
1871
|
<h2>Add a comment:</h2>
|
|
1732
|
-
<%= render
|
|
1872
|
+
<%= render 'comments/form' %>
|
|
1733
1873
|
|
|
1734
|
-
<%= link_to 'Edit
|
|
1735
|
-
<%= link_to 'Back
|
|
1874
|
+
<%= link_to 'Edit', edit_article_path(@article) %> |
|
|
1875
|
+
<%= link_to 'Back', articles_path %>
|
|
1736
1876
|
```
|
|
1737
1877
|
|
|
1738
1878
|
The second render just defines the partial template we want to render,
|
|
@@ -1805,8 +1945,8 @@ database and send us back to the show action for the article.
|
|
|
1805
1945
|
|
|
1806
1946
|
### Deleting Associated Objects
|
|
1807
1947
|
|
|
1808
|
-
If you delete an article
|
|
1809
|
-
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
|
|
1810
1950
|
you to use the `dependent` option of an association to achieve this. Modify the
|
|
1811
1951
|
Article model, `app/models/article.rb`, as follows:
|
|
1812
1952
|
|
|
@@ -1823,21 +1963,21 @@ Security
|
|
|
1823
1963
|
|
|
1824
1964
|
### Basic Authentication
|
|
1825
1965
|
|
|
1826
|
-
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
|
|
1827
1967
|
delete articles or delete comments.
|
|
1828
1968
|
|
|
1829
1969
|
Rails provides a very simple HTTP authentication system that will work nicely in
|
|
1830
1970
|
this situation.
|
|
1831
1971
|
|
|
1832
|
-
In the `ArticlesController` we need to have a way to block access to the
|
|
1833
|
-
actions if the person is not authenticated
|
|
1834
|
-
`http_basic_authenticate_with` method,
|
|
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
|
|
1835
1975
|
action if that method allows it.
|
|
1836
1976
|
|
|
1837
1977
|
To use the authentication system, we specify it at the top of our
|
|
1838
|
-
`ArticlesController
|
|
1839
|
-
every action
|
|
1840
|
-
|
|
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:
|
|
1841
1981
|
|
|
1842
1982
|
```ruby
|
|
1843
1983
|
class ArticlesController < ApplicationController
|
|
@@ -1848,7 +1988,7 @@ class ArticlesController < ApplicationController
|
|
|
1848
1988
|
@articles = Article.all
|
|
1849
1989
|
end
|
|
1850
1990
|
|
|
1851
|
-
#
|
|
1991
|
+
# snippet for brevity
|
|
1852
1992
|
```
|
|
1853
1993
|
|
|
1854
1994
|
We also want to allow only authenticated users to delete comments, so in the
|
|
@@ -1861,14 +2001,14 @@ class CommentsController < ApplicationController
|
|
|
1861
2001
|
|
|
1862
2002
|
def create
|
|
1863
2003
|
@article = Article.find(params[:article_id])
|
|
1864
|
-
...
|
|
2004
|
+
# ...
|
|
1865
2005
|
end
|
|
1866
2006
|
|
|
1867
|
-
#
|
|
2007
|
+
# snippet for brevity
|
|
1868
2008
|
```
|
|
1869
2009
|
|
|
1870
2010
|
Now if you try to create a new article, you will be greeted with a basic HTTP
|
|
1871
|
-
Authentication challenge
|
|
2011
|
+
Authentication challenge:
|
|
1872
2012
|
|
|
1873
2013
|

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