1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Merge pull request #14961 from jonatack/patch-7

Follow-up to #14905 and formatting pass [ci skip]
This commit is contained in:
Robin Dupret 2014-05-04 20:16:22 +02:00
commit 681fbecebd

View file

@ -267,8 +267,9 @@ invoke scss
create app/assets/stylesheets/welcome.css.scss create app/assets/stylesheets/welcome.css.scss
``` ```
Most important of these are of course the controller, located at `app/controllers/welcome_controller.rb` Most important of these are of course the controller, located at
and the view, located at `app/views/welcome/index.html.erb`. `app/controllers/welcome_controller.rb` and the view, located at
`app/views/welcome/index.html.erb`.
Open the `app/views/welcome/index.html.erb` file in your text editor. Delete all Open the `app/views/welcome/index.html.erb` file in your text editor. Delete all
of the existing code in the file, and replace it with the following single line of the existing code in the file, and replace it with the following single line
@ -433,17 +434,16 @@ class, define a `new` method so that the controller now looks like this:
```ruby ```ruby
class ArticlesController < ApplicationController class ArticlesController < ApplicationController
def new def new
end end
end end
``` ```
With the `new` method defined in `ArticlesController`, if you refresh With the `new` method defined in `ArticlesController`, if you refresh
<http://localhost:3000/articles/new> you'll see another error: <http://localhost:3000/articles/new> you'll see another error:
![Template is missing for articles/new](images/getting_started/template_is_missing_articles_new.png) ![Template is missing for articles/new]
(images/getting_started/template_is_missing_articles_new.png)
You're getting this error now because Rails expects plain actions like this one You're getting this error now because Rails expects plain actions like this one
to have views associated with them to display their information. With no view to have views associated with them to display their information. With no view
@ -507,7 +507,6 @@ method called `form_for`. To use this method, add this code into
```html+erb ```html+erb
<%= form_for :article do |f| %> <%= form_for :article do |f| %>
<p> <p>
<%= f.label :title %><br> <%= f.label :title %><br>
<%= f.text_field :title %> <%= f.text_field :title %>
@ -521,7 +520,6 @@ method called `form_for`. To use this method, add this code into
<p> <p>
<%= f.submit %> <%= f.submit %>
</p> </p>
<% end %> <% end %>
``` ```
@ -571,11 +569,10 @@ edit_article GET /articles/:id/edit(.:format) articles#edit
root GET / welcome#index root GET / welcome#index
``` ```
The `articles_path` helper tells Rails to point the form The `articles_path` helper tells Rails to point the form to the URI Pattern
to the URI Pattern associated with the `articles` prefix; and associated with the `articles` prefix; and the form will (by default) send a
the form will (by default) send a `POST` request `POST` request to that route. This is associated with the `create` action of
to that route. This is associated with the the current controller, the `ArticlesController`.
`create` action of the current controller, the `ArticlesController`.
With the form and its associated route defined, you will be able to fill in the With the form and its associated route defined, you will be able to fill in the
form and then click the submit button to begin the process of creating a new form and then click the submit button to begin the process of creating a new
@ -596,13 +593,11 @@ underneath the `new` action, as shown:
```ruby ```ruby
class ArticlesController < ApplicationController class ArticlesController < ApplicationController
def new def new
end end
def create def create
end end
end end
``` ```
@ -641,10 +636,10 @@ parameters but nothing in particular is being done with them.
### Creating the Article model ### Creating the Article model
Models in Rails use a singular name, and their corresponding database tables use Models in Rails use a singular name, and their corresponding database tables
a plural name. Rails provides a generator for creating models, which use a plural name. Rails provides a generator for creating models, which most
most Rails developers tend to use when creating new models. Rails developers tend to use when creating new models. To create the new model,
To create the new model, run this command in your terminal: run this command in your terminal:
```bash ```bash
$ rails generate model Article title:string text:text $ rails generate model Article title:string text:text
@ -655,26 +650,23 @@ with a _title_ attribute of type string, and a _text_ attribute
of type text. Those attributes are automatically added to the `articles` of type text. Those attributes are automatically added to the `articles`
table in the database and mapped to the `Article` model. table in the database and mapped to the `Article` model.
Rails responded by creating a bunch of files. For Rails responded by creating a bunch of files. For now, we're only interested
now, we're only interested in `app/models/article.rb` and in `app/models/article.rb` and `db/migrate/20140120191729_create_articles.rb`
`db/migrate/20140120191729_create_articles.rb` (your name could be a bit (your name could be a bit different). The latter is responsible for creating
different). The latter is responsible the database structure, which is what we'll look at next.
for creating the database structure, which is what we'll look at next.
TIP: Active Record is smart enough to automatically map column names to TIP: Active Record is smart enough to automatically map column names to model
model attributes, which means you don't have to declare attributes attributes, which means you don't have to declare attributes inside Rails
inside Rails models, as that will be done automatically by Active models, as that will be done automatically by Active Record.
Record.
### Running a Migration ### Running a Migration
As we've just seen, `rails generate model` created a _database As we've just seen, `rails generate model` created a _database migration_ file
migration_ file inside the `db/migrate` directory. inside the `db/migrate` directory. Migrations are Ruby classes that are
Migrations are Ruby classes that are designed to make it simple to designed to make it simple to create and modify database tables. Rails uses
create and modify database tables. Rails uses rake commands to run migrations, rake commands to run migrations, and it's possible to undo a migration after
and it's possible to undo a migration after it's been applied to your database. it's been applied to your database. Migration filenames include a timestamp to
Migration filenames include a timestamp to ensure that they're processed in the ensure that they're processed in the order that they were created.
order that they were created.
If you look in the `db/migrate/20140120191729_create_articles.rb` file (remember, If you look in the `db/migrate/20140120191729_create_articles.rb` file (remember,
yours will have a slightly different name), here's what you'll find: yours will have a slightly different name), here's what you'll find:
@ -699,8 +691,8 @@ in case you want to reverse it later. When you run this migration it will create
an `articles` table with one string column and a text column. It also creates an `articles` table with one string column and a text column. It also creates
two timestamp fields to allow Rails to track article creation and update times. two timestamp fields to allow Rails to track article creation and update times.
TIP: For more information about migrations, refer to [Rails Database TIP: For more information about migrations, refer to [Rails Database Migrations]
Migrations](migrations.html). (migrations.html).
At this point, you can use a rake command to run the migration: At this point, you can use a rake command to run the migration:
@ -742,50 +734,47 @@ end
Here's what's going on: every Rails model can be initialized with its Here's what's going on: every Rails model can be initialized with its
respective attributes, which are automatically mapped to the respective respective attributes, which are automatically mapped to the respective
database columns. In the first line we do just that database columns. In the first line we do just that (remember that
(remember that `params[:article]` contains the attributes we're interested in). `params[:article]` contains the attributes we're interested in). Then,
Then, `@article.save` is responsible for saving the model in the database. `@article.save` is responsible for saving the model in the database. Finally,
Finally, we redirect the user to the `show` action, which we'll define later. we redirect the user to the `show` action, which we'll define later.
TIP: As we'll see later, `@article.save` returns a boolean indicating TIP: As we'll see later, `@article.save` returns a boolean indicating whether
whether the article was saved or not. the article was saved or not.
If you now go to If you now go to <http://localhost:3000/articles/new> you'll *almost* be able
<http://localhost:3000/articles/new> you'll *almost* be able to create an to create an article. Try it! You should get an error that looks like this:
article. Try it! You should get an error that looks like this:
![Forbidden attributes for new article](images/getting_started/forbidden_attributes_for_new_article.png) ![Forbidden attributes for new article]
(images/getting_started/forbidden_attributes_for_new_article.png)
Rails has several security features that help you write secure applications, Rails has several security features that help you write secure applications,
and you're running into one of them now. This one is called and you're running into one of them now. This one is called `[strong_parameters]
`[strong_parameters](http://guides.rubyonrails.org/action_controller_overview.html#strong-parameters)`, (http://guides.rubyonrails.org/action_controller_overview.html#strong-parameters)`,
which requires us to tell Rails exactly which parameters are allowed into which requires us to tell Rails exactly which parameters are allowed into our
our controller actions. controller actions.
Why do you have to bother? The ability to grab and automatically assign Why do you have to bother? The ability to grab and automatically assign all
all controller parameters to your model in one shot makes the programmer's controller parameters to your model in one shot makes the programmer's job
job easier, but this convenience also allows malicious use. What if a easier, but this convenience also allows malicious use. What if a request to
request to the server was crafted to look like a new article form submit the server was crafted to look like a new article form submit but also included
but also included extra fields with values that violated your applications extra fields with values that violated your applications integrity? They would
integrity? They would be 'mass assigned' into your model and then into the be 'mass assigned' into your model and then into the database along with the
database along with the good stuff - potentially breaking your application good stuff - potentially breaking your application or worse.
or worse.
We have to whitelist our controller parameters to prevent wrongful We have to whitelist our controller parameters to prevent wrongful mass
mass assignment. In this case, we want to both allow and require the assignment. In this case, we want to both allow and require the `title` and
`title` and `text` parameters for valid use of `create`. The syntax for `text` parameters for valid use of `create`. The syntax for this introduces
this introduces `require` and `permit`. The change will involve one line `require` and `permit`. The change will involve one line in the `create` action:
in the `create` action:
```ruby ```ruby
@article = Article.new(params.require(:article).permit(:title, :text)) @article = Article.new(params.require(:article).permit(:title, :text))
``` ```
This is often factored out into its own method so it can be reused by This is often factored out into its own method so it can be reused by multiple
multiple actions in the same controller, for example `create` and `update`. actions in the same controller, for example `create` and `update`. Above and
Above and beyond mass assignment issues, the method is often made beyond mass assignment issues, the method is often made `private` to make sure
`private` to make sure it can't be called outside its intended context. it can't be called outside its intended context. Here is the result:
Here is the result:
```ruby ```ruby
def create def create
@ -802,13 +791,14 @@ private
``` ```
TIP: For more information, refer to the reference above and TIP: For more information, refer to the reference above and
[this blog article about Strong Parameters](http://weblog.rubyonrails.org/2012/3/21/strong-parameters/). [this blog article about Strong Parameters]
(http://weblog.rubyonrails.org/2012/3/21/strong-parameters/).
### Showing Articles ### Showing Articles
If you submit the form again now, Rails will complain about not finding If you submit the form again now, Rails will complain about not finding the
the `show` action. That's not very useful though, so let's add the `show` action. That's not very useful though, so let's add the `show` action
`show` action before proceeding. before proceeding.
As we have seen in the output of `rake routes`, the route for `show` action is As we have seen in the output of `rake routes`, the route for `show` action is
as follows: as follows:
@ -824,17 +814,15 @@ As we did before, we need to add the `show` action in
`app/controllers/articles_controller.rb` and its respective view. `app/controllers/articles_controller.rb` and its respective view.
NOTE: A frequent practice is to place the standard CRUD actions in each NOTE: A frequent practice is to place the standard CRUD actions in each
controller in the following order: `index`, `show`, `new`, `edit`, `create`, controller in the following order: `index`, `show`, `new`, `edit`, `create`, `update`
`update` and `destroy`. You may use any order you choose, but keep in mind that and `destroy`. You may use any order you choose, but keep in mind that these
these are public methods; as mentioned earlier in this guide, they must be are public methods; as mentioned earlier in this guide, they must be placed
placed before any private or protected method in the controller in order to before any private or protected method in the controller in order to work.
work.
Given that, let's add the `show` action, as follows: Given that, let's add the `show` action, as follows:
```ruby ```ruby
class ArticlesController < ApplicationController class ArticlesController < ApplicationController
def show def show
@article = Article.find(params[:id]) @article = Article.find(params[:id])
end end
@ -887,7 +875,6 @@ first method in the controller. Let's do it:
```ruby ```ruby
class ArticlesController < ApplicationController class ArticlesController < ApplicationController
def index def index
@articles = Article.all @articles = Article.all
end end
@ -981,9 +968,9 @@ article can go back and view the whole list again:
<%= link_to 'Back', articles_path %> <%= link_to 'Back', articles_path %>
``` ```
TIP: If you want to link to an action in the same controller, you don't TIP: If you want to link to an action in the same controller, you don't need to
need to specify the `:controller` option, as Rails will use the current specify the `:controller` option, as Rails will use the current controller by
controller by default. default.
TIP: In development mode (which is what you're working in by default), Rails TIP: In development mode (which is what you're working in by default), Rails
reloads your application with every browser request, so there's no need to stop reloads your application with every browser request, so there's no need to stop
@ -1341,8 +1328,8 @@ The reason we can use this shorter, simpler `form_for` declaration
to stand in for either of the other forms is that `@article` is a *resource* to stand in for either of the other forms is that `@article` is a *resource*
corresponding to a full set of RESTful routes, and Rails is able to infer corresponding to a full set of RESTful routes, and Rails is able to infer
which URI and method to use. which URI and method to use.
For more information about this use of `form_for`, see For more information about this use of `form_for`, see [Resource-oriented style]
[Resource-oriented style](//api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_for-label-Resource-oriented+style). (http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_for-label-Resource-oriented+style).
Now, let's update the `app/views/articles/new.html.erb` view to use this new Now, let's update the `app/views/articles/new.html.erb` view to use this new
partial, rewriting it completely: partial, rewriting it completely:
@ -1403,7 +1390,6 @@ The complete `ArticlesController` in the
```ruby ```ruby
class ArticlesController < ApplicationController class ArticlesController < ApplicationController
def index def index
@articles = Article.all @articles = Article.all
end end
@ -1459,8 +1445,7 @@ them from the database. Note that we don't need to add a view for this
action since we're redirecting to the `index` action. action since we're redirecting to the `index` action.
Finally, add a 'Destroy' link to your `index` action template Finally, add a 'Destroy' link to your `index` action template
(`app/views/articles/index.html.erb`) to wrap everything (`app/views/articles/index.html.erb`) to wrap everything together.
together.
```html+erb ```html+erb
<h1>Listing Articles</h1> <h1>Listing Articles</h1>