Rails MVC Violation: Less code in views, more clarity in code


Why Views Should Only Handle Presentation

In the MVC framework, views should only be responsible for presenting data, not preparing it.

When views handle logic and data manipulation, it leads to increased complexity and code duplication.

This complicates testing and violates the single responsibility principle by making the view aware of business logic.

But also add clarity when reading controllers: You can foresee what to expect in the views by reading the controller.

Example of Bad Practice in MVC

Here’s a common pitfall:

Bad View Example

# app/views/users/index.html.erb
<ul>
  <% User.order("last_name").each do |user| %>
    <li><%= user.full_name %></li>
  <% end %>
</ul>

Bad Controller Example

# app/controllers/users_controller.rb
class UsersController < ApplicationController
  def index
    # No user fetching logic here
  end
end

Issues:

  • The view directly queries and sorts records (User.order), which should be encapsulated in the model.
  • The controller does not prepare any data for the view, simplifying its duty but at the cost of MVC integrity.

Code Refactoring: MVC Done Right

Revised Model

# app/models/user.rb
class User < ApplicationRecord
  scope :ordered_by_last_name, -> { order("last_name") }
end

Revised Controller

# app/controllers/users_controller.rb
class UsersController < ApplicationController
  def index
    @users = User.ordered_by_last_name
  end
end

Revised View

# app/views/users/index.html.erb
<ul>
  <% @users.each do |user| %>
    <li><%= user.full_name %></li>
  <% end %>
</ul>

Improvements:

  • The model now encapsulates the logic for ordering users.
  • The controller passes the @users instance variable prepared for display.
  • The view focuses solely on rendering, not processing data.

Enhancing Views with Partials and Collections

Take advantage of Rails partials and collections to make your views even cleaner.

Original Approach

# app/views/users/index.html.erb
<%= render partial: "user", collection: @users %>

Partial File

# app/views/users/_user.html.erb
<li><%= user.full_name %></li>

Using Shortcuts:

<%= render @users %>

With this approach, Rails automatically uses the _user.html.erb partial for each element in @users. This simplifies the view file, enhances readability, and adheres to DRY principles.

Benefits of Using Partials with Collections:

  • Reduced Complexity in Views: Keeps the views clean and focused on presentation.
  • Improved Maintainability: Changes to user presentation need only be made in one partial file.
  • Enhanced Caching Opportunities: Each partial can be cached individually for performance benefits.

Utilizing partials and collections not only adheres to Rails best practices but also leverages Rails’ powerful rendering engine to manage collections more intuitively. This method keeps your codebase clean, manageable, and performant.


Related posts

Free Training By Email:
Building a Rails Engine

We will send udpates but we care about your data.
No spams.

Back to homepage