mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Merge pull request #28912 from kaspth/getting-started-form-with
[ci skip] form_with in the getting started guide.
This commit is contained in:
commit
39e6eea9e5
2 changed files with 100 additions and 67 deletions
|
@ -543,6 +543,36 @@ module ActionView
|
||||||
# and adds an authenticity token needed for cross site request forgery
|
# and adds an authenticity token needed for cross site request forgery
|
||||||
# protection.
|
# protection.
|
||||||
#
|
#
|
||||||
|
# === Resource-oriented style
|
||||||
|
#
|
||||||
|
# In many of the examples just shown, the +:model+ passed to +form_with+
|
||||||
|
# is a _resource_. It corresponds to a set of RESTful routes, most likely
|
||||||
|
# defined via +resources+ in <tt>config/routes.rb</tt>.
|
||||||
|
#
|
||||||
|
# So when passing such a model record, Rails infers the URL and method.
|
||||||
|
#
|
||||||
|
# <%= form_with model: @post do |form| %>
|
||||||
|
# ...
|
||||||
|
# <% end %>
|
||||||
|
#
|
||||||
|
# is then equivalent to something like:
|
||||||
|
#
|
||||||
|
# <%= form_with scope: :post, url: post_path(@post), method: :patch do |form| %>
|
||||||
|
# ...
|
||||||
|
# <% end %>
|
||||||
|
#
|
||||||
|
# And for a new record
|
||||||
|
#
|
||||||
|
# <%= form_with model: Post.new do |form| %>
|
||||||
|
# ...
|
||||||
|
# <% end %>
|
||||||
|
#
|
||||||
|
# is equivalent to something like:
|
||||||
|
#
|
||||||
|
# <%= form_with scope: :post, url: posts_path do |form| %>
|
||||||
|
# ...
|
||||||
|
# <% end %>
|
||||||
|
#
|
||||||
# ==== +form_with+ options
|
# ==== +form_with+ options
|
||||||
#
|
#
|
||||||
# * <tt>:url</tt> - The URL the form submits to. Akin to values passed to
|
# * <tt>:url</tt> - The URL the form submits to. Akin to values passed to
|
||||||
|
|
|
@ -509,23 +509,23 @@ harmoniously! It's time to create the form for a new article.
|
||||||
|
|
||||||
To create a form within this template, you will use a *form
|
To create a form within this template, you will use a *form
|
||||||
builder*. The primary form builder for Rails is provided by a helper
|
builder*. The primary form builder for Rails is provided by a helper
|
||||||
method called `form_for`. To use this method, add this code into
|
method called `form_with`. To use this method, add this code into
|
||||||
`app/views/articles/new.html.erb`:
|
`app/views/articles/new.html.erb`:
|
||||||
|
|
||||||
```html+erb
|
```html+erb
|
||||||
<%= form_for :article do |f| %>
|
<%= form_with scope: :article, local: true do |form| %>
|
||||||
<p>
|
<p>
|
||||||
<%= f.label :title %><br>
|
<%= form.label :title %><br>
|
||||||
<%= f.text_field :title %>
|
<%= form.text_field :title %>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<%= f.label :text %><br>
|
<%= form.label :text %><br>
|
||||||
<%= f.text_area :text %>
|
<%= form.text_area :text %>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<%= f.submit %>
|
<%= form.submit %>
|
||||||
</p>
|
</p>
|
||||||
<% end %>
|
<% end %>
|
||||||
```
|
```
|
||||||
|
@ -533,12 +533,12 @@ method called `form_for`. To use this method, add this code into
|
||||||
If you refresh the page now, you'll see the exact same form from our example above.
|
If you refresh the page now, you'll see the exact same form from our example above.
|
||||||
Building forms in Rails is really just that easy!
|
Building forms in Rails is really just that easy!
|
||||||
|
|
||||||
When you call `form_for`, you pass it an identifying object for this
|
When you call `form_with`, you pass it an identifying scope for this
|
||||||
form. In this case, it's the symbol `:article`. This tells the `form_for`
|
form. In this case, it's the symbol `:article`. This tells the `form_with`
|
||||||
helper what this form is for. Inside the block for this method, the
|
helper what this form is for. Inside the block for this method, the
|
||||||
`FormBuilder` object - represented by `f` - is used to build two labels and two
|
`FormBuilder` object - represented by `form` - is used to build two labels and two
|
||||||
text fields, one each for the title and text of an article. Finally, a call to
|
text fields, one each for the title and text of an article. Finally, a call to
|
||||||
`submit` on the `f` object will create a submit button for the form.
|
`submit` on the `form` object will create a submit button for the form.
|
||||||
|
|
||||||
There's one problem with this form though. If you inspect the HTML that is
|
There's one problem with this form though. If you inspect the HTML that is
|
||||||
generated, by viewing the source of the page, you will see that the `action`
|
generated, by viewing the source of the page, you will see that the `action`
|
||||||
|
@ -547,15 +547,15 @@ this route goes to the very page that you're on right at the moment, and that
|
||||||
route should only be used to display the form for a new article.
|
route should only be used to display the form for a new article.
|
||||||
|
|
||||||
The form needs to use a different URL in order to go somewhere else.
|
The form needs to use a different URL in order to go somewhere else.
|
||||||
This can be done quite simply with the `:url` option of `form_for`.
|
This can be done quite simply with the `:url` option of `form_with`.
|
||||||
Typically in Rails, the action that is used for new form submissions
|
Typically in Rails, the action that is used for new form submissions
|
||||||
like this is called "create", and so the form should be pointed to that action.
|
like this is called "create", and so the form should be pointed to that action.
|
||||||
|
|
||||||
Edit the `form_for` line inside `app/views/articles/new.html.erb` to look like
|
Edit the `form_with` line inside `app/views/articles/new.html.erb` to look like
|
||||||
this:
|
this:
|
||||||
|
|
||||||
```html+erb
|
```html+erb
|
||||||
<%= form_for :article, url: articles_path do |f| %>
|
<%= form_with scope: :article, url: articles_path, local: true do |form| %>
|
||||||
```
|
```
|
||||||
|
|
||||||
In this example, the `articles_path` helper is passed to the `:url` option.
|
In this example, the `articles_path` helper is passed to the `:url` option.
|
||||||
|
@ -592,6 +592,10 @@ familiar error:
|
||||||
You now need to create the `create` action within the `ArticlesController` for
|
You now need to create the `create` action within the `ArticlesController` for
|
||||||
this to work.
|
this to work.
|
||||||
|
|
||||||
|
NOTE: by default `form_with` submits forms using Ajax thereby skipping full page
|
||||||
|
redirects. To make this guide easier to get into we've disabled that with
|
||||||
|
`local: true` for now.
|
||||||
|
|
||||||
### Creating articles
|
### Creating articles
|
||||||
|
|
||||||
To make the "Unknown action" go away, you can define a `create` action within
|
To make the "Unknown action" go away, you can define a `create` action within
|
||||||
|
@ -956,7 +960,7 @@ Now, add another link in `app/views/articles/new.html.erb`, underneath the
|
||||||
form, to go back to the `index` action:
|
form, to go back to the `index` action:
|
||||||
|
|
||||||
```erb
|
```erb
|
||||||
<%= form_for :article, url: articles_path do |f| %>
|
<%= form_with scope: :article, url: articles_path, local: true do |form| %>
|
||||||
...
|
...
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
@ -1067,7 +1071,7 @@ something went wrong. To do that, you'll modify
|
||||||
`app/views/articles/new.html.erb` to check for error messages:
|
`app/views/articles/new.html.erb` to check for error messages:
|
||||||
|
|
||||||
```html+erb
|
```html+erb
|
||||||
<%= form_for :article, url: articles_path do |f| %>
|
<%= form_with scope: :article, url: articles_path, local: true do |form| %>
|
||||||
|
|
||||||
<% if @article.errors.any? %>
|
<% if @article.errors.any? %>
|
||||||
<div id="error_explanation">
|
<div id="error_explanation">
|
||||||
|
@ -1084,17 +1088,17 @@ something went wrong. To do that, you'll modify
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<%= f.label :title %><br>
|
<%= form.label :title %><br>
|
||||||
<%= f.text_field :title %>
|
<%= form.text_field :title %>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<%= f.label :text %><br>
|
<%= form.label :text %><br>
|
||||||
<%= f.text_area :text %>
|
<%= form.text_area :text %>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<%= f.submit %>
|
<%= form.submit %>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<% end %>
|
<% end %>
|
||||||
|
@ -1159,7 +1163,7 @@ it look as follows:
|
||||||
```html+erb
|
```html+erb
|
||||||
<h1>Edit article</h1>
|
<h1>Edit article</h1>
|
||||||
|
|
||||||
<%= form_for(@article) do |f| %>
|
<%= form_with(model: @article) do |form| %>
|
||||||
|
|
||||||
<% if @article.errors.any? %>
|
<% if @article.errors.any? %>
|
||||||
<div id="error_explanation">
|
<div id="error_explanation">
|
||||||
|
@ -1176,17 +1180,17 @@ it look as follows:
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<%= f.label :title %><br>
|
<%= form.label :title %><br>
|
||||||
<%= f.text_field :title %>
|
<%= form.text_field :title %>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<%= f.label :text %><br>
|
<%= form.label :text %><br>
|
||||||
<%= f.text_area :text %>
|
<%= form.text_area :text %>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<%= f.submit %>
|
<%= form.submit %>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<% end %>
|
<% end %>
|
||||||
|
@ -1202,12 +1206,11 @@ This option tells Rails that we want this form to be submitted
|
||||||
via the `PATCH` HTTP method which is the HTTP method you're expected to use to
|
via the `PATCH` HTTP method which is the HTTP method you're expected to use to
|
||||||
**update** resources according to the REST protocol.
|
**update** resources according to the REST protocol.
|
||||||
|
|
||||||
The first parameter of `form_for` can be an object, say, `@article` which would
|
The arguments to `form_with` could be model objects, say, `model: @article` which would
|
||||||
cause the helper to fill in the form with the fields of the object. Passing in a
|
cause the helper to fill in the form with the fields of the object. Passing in a
|
||||||
symbol (`:article`) with the same name as the instance variable (`@article`)
|
symbol scope (`scope: :article`) just creates the fields but without anything filled into them.
|
||||||
also automagically leads to the same behavior.
|
More details can be found in [form_with documentation]
|
||||||
More details can be found in [form_for documentation]
|
(http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_with).
|
||||||
(http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_for).
|
|
||||||
|
|
||||||
Next, we need to create the `update` action in
|
Next, we need to create the `update` action in
|
||||||
`app/controllers/articles_controller.rb`.
|
`app/controllers/articles_controller.rb`.
|
||||||
|
@ -1304,7 +1307,7 @@ Create a new file `app/views/articles/_form.html.erb` with the following
|
||||||
content:
|
content:
|
||||||
|
|
||||||
```html+erb
|
```html+erb
|
||||||
<%= form_for @article do |f| %>
|
<%= form_with model: @article, local: true do |form| %>
|
||||||
|
|
||||||
<% if @article.errors.any? %>
|
<% if @article.errors.any? %>
|
||||||
<div id="error_explanation">
|
<div id="error_explanation">
|
||||||
|
@ -1321,29 +1324,29 @@ content:
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<%= f.label :title %><br>
|
<%= form.label :title %><br>
|
||||||
<%= f.text_field :title %>
|
<%= form.text_field :title %>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<%= f.label :text %><br>
|
<%= form.label :text %><br>
|
||||||
<%= f.text_area :text %>
|
<%= form.text_area :text %>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<%= f.submit %>
|
<%= form.submit %>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<% end %>
|
<% end %>
|
||||||
```
|
```
|
||||||
|
|
||||||
Everything except for the `form_for` declaration remained the same.
|
Everything except for the `form_with` declaration remained the same.
|
||||||
The reason we can use this shorter, simpler `form_for` declaration
|
The reason we can use this shorter, simpler `form_with` 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 [Resource-oriented style]
|
For more information about this use of `form_with`, see [Resource-oriented style]
|
||||||
(http://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_with-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:
|
||||||
|
@ -1682,17 +1685,17 @@ So first, we'll wire up the Article show template
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2>Add a comment:</h2>
|
<h2>Add a comment:</h2>
|
||||||
<%= form_for([@article, @article.comments.build]) do |f| %>
|
<%= form_with(model: [ @article, @article.comments.build ], local: true) do |form| %>
|
||||||
<p>
|
<p>
|
||||||
<%= f.label :commenter %><br>
|
<%= form.label :commenter %><br>
|
||||||
<%= f.text_field :commenter %>
|
<%= form.text_field :commenter %>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<%= f.label :body %><br>
|
<%= form.label :body %><br>
|
||||||
<%= f.text_area :body %>
|
<%= form.text_area :body %>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<%= f.submit %>
|
<%= form.submit %>
|
||||||
</p>
|
</p>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
@ -1701,7 +1704,7 @@ So first, we'll wire up the Article show template
|
||||||
```
|
```
|
||||||
|
|
||||||
This adds a form on the `Article` show page that creates a new comment by
|
This adds a form on the `Article` show page that creates a new comment by
|
||||||
calling the `CommentsController` `create` action. The `form_for` call here uses
|
calling the `CommentsController` `create` action. The `form_with` call here uses
|
||||||
an array, which will build a nested route, such as `/articles/1/comments`.
|
an array, which will build a nested route, such as `/articles/1/comments`.
|
||||||
|
|
||||||
Let's wire up the `create` in `app/controllers/comments_controller.rb`:
|
Let's wire up the `create` in `app/controllers/comments_controller.rb`:
|
||||||
|
@ -1763,17 +1766,17 @@ add that to the `app/views/articles/show.html.erb`.
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<h2>Add a comment:</h2>
|
<h2>Add a comment:</h2>
|
||||||
<%= form_for([@article, @article.comments.build]) do |f| %>
|
<%= form_with(model: [ @article, @article.comments.build ]) do |form| %>
|
||||||
<p>
|
<p>
|
||||||
<%= f.label :commenter %><br>
|
<%= form.label :commenter %><br>
|
||||||
<%= f.text_field :commenter %>
|
<%= form.text_field :commenter %>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<%= f.label :body %><br>
|
<%= form.label :body %><br>
|
||||||
<%= f.text_area :body %>
|
<%= form.text_area :body %>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<%= f.submit %>
|
<%= form.submit %>
|
||||||
</p>
|
</p>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
@ -1829,17 +1832,17 @@ following:
|
||||||
<%= render @article.comments %>
|
<%= render @article.comments %>
|
||||||
|
|
||||||
<h2>Add a comment:</h2>
|
<h2>Add a comment:</h2>
|
||||||
<%= form_for([@article, @article.comments.build]) do |f| %>
|
<%= form_with(model: [ @article, @article.comments.build ]) do |form| %>
|
||||||
<p>
|
<p>
|
||||||
<%= f.label :commenter %><br>
|
<%= form.label :commenter %><br>
|
||||||
<%= f.text_field :commenter %>
|
<%= form.text_field :commenter %>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<%= f.label :body %><br>
|
<%= form.label :body %><br>
|
||||||
<%= f.text_area :body %>
|
<%= form.text_area :body %>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<%= f.submit %>
|
<%= form.submit %>
|
||||||
</p>
|
</p>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
@ -1859,17 +1862,17 @@ Let us also move that new comment section out to its own partial. Again, you
|
||||||
create a file `app/views/comments/_form.html.erb` containing:
|
create a file `app/views/comments/_form.html.erb` containing:
|
||||||
|
|
||||||
```html+erb
|
```html+erb
|
||||||
<%= form_for([@article, @article.comments.build]) do |f| %>
|
<%= form_with(model: [ @article, @article.comments.build ]) do |form| %>
|
||||||
<p>
|
<p>
|
||||||
<%= f.label :commenter %><br>
|
<%= form.label :commenter %><br>
|
||||||
<%= f.text_field :commenter %>
|
<%= form.text_field :commenter %>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<%= f.label :body %><br>
|
<%= form.label :body %><br>
|
||||||
<%= f.text_area :body %>
|
<%= form.text_area :body %>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<%= f.submit %>
|
<%= form.submit %>
|
||||||
</p>
|
</p>
|
||||||
<% end %>
|
<% end %>
|
||||||
```
|
```
|
||||||
|
|
Loading…
Reference in a new issue