Ruby Science
Extract Partial
Extracting a partial is a technique used for removing complex or duplicated view code from your application. This is the equivalent of using long method and extract method in your views and templates.
Uses
- Removes duplicated code from views.
- Avoids shotgun surgery by forcing changes to happen in one place.
- Removes divergent change by removing a reason for the view to change.
- Groups common code.
- Reduces view size and complexity.
- Makes view logic easier to reuse, which makes it easier to avoid duplication.
Steps
- Create a new file for partial prefixed with an underscore (_filename.html.erb).
- Move common code into newly created file.
- Render the partial from the source file.
Example
Let’s revisit the view code for adding and editing questions.
Note: There are a few small differences in the files (the URL endpoint and the label on the submit button).
# app/views/questions/new.html.erb<h1>Add Question</h1>
<%= simple_form_for @question, as: :question, url: survey_questions_path(@survey) do |form| -%>
<%= form.hidden_field :type %>
<%= form.input :title %>
<%= render "#{@question.to_partial_path}_form", question: @question, form: form %>
<%= form.submit 'Create Question' %>
<% end -%>
# app/views/questions/edit.html.erb<h1>Edit Question</h1>
<%= simple_form_for @question, as: :question, url: question_path do |form| -%>
<%= form.hidden_field :type %>
<%= form.input :title %>
<%= render "#{@question.to_partial_path}_form", question: @question, form: form %>
<%= form.submit 'Update Question' %>
<% end -%>
First, extract the common code into a partial, remove any instance
variables and use question
and url
as local
variables:
# app/views/questions/_form.html.erb<%= simple_form_for question, as: :question, url: url do |form| -%>
<%= form.hidden_field :type %>
<%= form.input :title %>
<%= render "#{question.to_partial_path}_form", question: question, form: form %>
<%= form.submit %>
<% end -%>
Move the submit button text into the locales file:
# config/locales/en.yml
en:
helpers:
submit:
question:
create: 'Create Question'
update: 'Update Question'
Then render the partial from each of the views, passing in the values
for question
and url
:
# app/views/questions/new.html.erb<h1>Add Question</h1>
<%= render 'form', question: @question, url: survey_questions_path(@survey) %>
# app/views/questions/edit.html.erb<h1>Edit Question</h1>
<%= render 'form', question: @question, url: question_path %>
Next Steps
- Check for other occurrences of the duplicated view code in your application and replace them with the newly extracted partial.
Ruby Science
The canonical reference for writing fantastic Rails applications from authors who have created hundreds.