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:
commit
681fbecebd
1 changed files with 72 additions and 87 deletions
|
@ -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>
|
||||||
|
|
Loading…
Reference in a new issue