Edit GS guide § Using Partials to Share View Code [ci-skip]

Fixes #39920.
Resolves #38329.

Co-Authored-By: Ryan Bigg <me@ryanbigg.com>
This commit is contained in:
Jonathan Hefner 2020-10-28 17:04:03 -05:00
parent 0bf055e5f1
commit e7b6928704
1 changed files with 40 additions and 51 deletions

View File

@ -1132,82 +1132,71 @@ validations fail and the update is successful, the action redirects the browser
to the article's page. Else, the action redisplays the form, with error to the article's page. Else, the action redisplays the form, with error
messages, by rendering `app/views/articles/edit.html.erb`. messages, by rendering `app/views/articles/edit.html.erb`.
### Using partials to clean up duplication in views #### Using Partials to Share View Code
Our `edit` page looks very similar to the `new` page; in fact, they Our `edit` form will look the same as our `new` form. Even the code will be the
both share the same code for displaying the form. Let's remove this same, thanks to the Rails form builder and resourceful routing. The form builder
duplication by using a view partial. By convention, partial files are automatically configures the form to make the appropriate kind of request, based
prefixed with an underscore. on whether the model object has been previously saved.
TIP: You can read more about partials in the Because the code will be the same, we're going to factor it out into a shared
[Layouts and Rendering in Rails](layouts_and_rendering.html) guide. view called a *partial*. Let's create `app/views/articles/_form.html.erb` with
the following contents:
Create a new file `app/views/articles/_form.html.erb` with the following
content:
```html+erb ```html+erb
<%= form_with model: @article, local: true do |form| %> <%= form_with model: article, local: true do |form| %>
<div>
<% if @article.errors.any? %>
<div id="error_explanation">
<h2>
<%= pluralize(@article.errors.count, "error") %> prohibited
this article from being saved:
</h2>
<ul>
<% @article.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<%= form.label :title %><br> <%= form.label :title %><br>
<%= form.text_field :title %> <%= form.text_field :title %>
</p> <%= article.errors.full_messages_for(:title).each do |message| %>
<div><%= message %></div>
<% end %>
</div>
<p> <div>
<%= form.label :text %><br> <%= form.label :body %><br>
<%= form.text_area :text %> <%= form.text_area :body %><br>
</p> <%= article.errors.full_messages_for(:body).each do |message| %>
<div><%= message %></div>
<% end %>
</div>
<p> <div>
<%= form.submit %> <%= form.submit %>
</p> </div>
<% end %> <% end %>
``` ```
Everything except for the `form_with` declaration remained the same. The above code is the same as our form in `app/views/articles/new.html.erb`,
The reason we can use this shorter `form_with` declaration except that all occurrences of `@article` have been replaced with `article`.
to stand in for either of the other forms is that `@article` is a *resource* Because partials are shared code, it is best practice that they do not depend on
corresponding to a full set of RESTful routes, and Rails is able to infer specific instance variables set by a controller action. Instead, we will pass
which URI and method to use. the article to the partial as a local variable.
For more information about this use of `form_with`, see [Resource-oriented style]
(https://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 Let's update `app/views/articles/new.html.erb` to use the partial via [`render`](
partial, rewriting it completely: https://api.rubyonrails.org/classes/ActionView/Helpers/RenderingHelper.html#method-i-render):
```html+erb ```html+erb
<h1>New Article</h1> <h1>New Article</h1>
<%= render 'form' %> <%= render "form", article: @article %>
<%= link_to 'Back', articles_path %>
``` ```
Then do the same for the `app/views/articles/edit.html.erb` view: NOTE: A partial's filename must be prefixed **with** an underscore, e.g.
`_form.html.erb`. But when rendering, it is referenced **without** the
underscore, e.g. `render "form"`.
And now, let's create a very similar `app/views/articles/edit.html.erb`:
```html+erb ```html+erb
<h1>Edit Article</h1> <h1>Edit Article</h1>
<%= render 'form' %> <%= render "form", article: @article %>
<%= link_to 'Back', articles_path %>
``` ```
TIP: To learn more about partials, see [Layouts and Rendering in Rails § Using
Partials](layouts_and_rendering.html#using-partials).
### Deleting Articles ### Deleting Articles
We're now ready to cover the "D" part of CRUD, deleting articles from the We're now ready to cover the "D" part of CRUD, deleting articles from the