Extracting our dashboard’s configuration out of the controller will let us keep our controller simple and focuses, and let us test things more easily in the future when things become more complicated. Where we want to end up is creating an object in our controller and rendering it in our view:
# app/controllers/dashboards_controller.rb
class DashboardsController < ApplicationController
def show
@dashboard = Dashboard.new
end
end
<%= render @dashboard %>
We’ll start by pulling the posts
and comments
into the new class:
# app/models/dashboard.rb
class Dashboard
def posts
Post
.where(publish_at: [..Time.current])
.order(publish_at: :desc)
.limit(10)
end
def comments
Comment.all
.order(create_at: :desc).limit(10)
end
end
To support loading a partial to render itself, the Dashboard
class also needs to implement to_partial_path
class Dashboard
def to_partial_path
"dashboards/dashboard"
end
end
and our updated partial:
<!-- app/views/dashboards/_dashboard.html.erb -->
<div class="grid grid-cols-2">
<div>
<h2>Recent Posts</h2>
<ul>
<%= dashboard.posts.each do |post| %>
<li><%= link_to post.title, post %></li>
<% end %>
</ul>
</div>
<div>
<h2>Recent Comments</h2>
<ul>
<%= dashboard.comments.each do |comment| %>
<li><%= link_to comment.body,
post_path(comment.post_id, anchor: dom_id(comment))
%></li>
<% end %>
</ul>
</div>
</div>
For this simple example there isn’t a huge win for this extraction, but as you grow your system you can treat these as reusable components. That is where isolating the component gives a benefit, and lets you build a more robust and understandable system.