Ruby On Rails Controller
π Ruby on Rails Part 3: The Controller - Brain of MVC π§ - Tips, Tricks & Libraries βοΈ
Welcome to Part 3 of our Ruby on Rails MVC series! π After covering Models and Views, we now focus on the Controller, which plays the pivotal role of handling incoming HTTP requests and coordinating data flow between the Model and View. Think of it as the brain of your Rails app, making decisions and ensuring everything runs smoothly. π§ Letβs explore the best practices, hacks, and libraries that will help you write cleaner and more efficient controllers! π‘
π§ What is a Controller in MVC?
In Rails, the Controller is responsible for receiving input from the user (usually through a request), interacting with the model, and rendering the appropriate view. It connects Models and Views by coordinating data and processing. Each action in a controller typically corresponds to an operation your app can perform (like viewing a page, creating a record, or updating data). π―
The goal is to keep your controllers lean and organized by moving logic to the Model and using helpers and concerns where necessary. Letβs get into some tips to make this easier!
π₯ Best Practices and Tips for Controllers
1. Keep Controllers Slim with Service Objects π§Ό
Controllers should be kept thin and simple. If you find yourself writing too much logic in the controller, itβs time to offload that into service objects or your models.
π Example:
# app/controllers/orders_controller.rb
def create
@order = Order.new(order_params)
if OrderProcessor.new(@order).process
redirect_to @order, notice: 'Order was successfully created.'
else
render :new
end
end
In this example, the order processing logic is encapsulated in a service object, making the controller leaner and more readable. π
2. Use Strong Parameters to Whitelist Input π
Always use strong parameters to prevent mass assignment vulnerabilities by whitelisting only the fields you want to permit.
π Example:
def order_params
params.require(:order).permit(:product_id, :quantity, :price)
end
This ensures that only permitted parameters are passed to your model, protecting your application from unwanted data. π
3. Use before_action
for Reusability π
To avoid code repetition, use before_action
callbacks to DRY up your controller actions. This helps in keeping the controller DRY and ensures shared logic is handled efficiently.
π Example:
before_action :set_article, only: [:show, :edit, :update, :destroy]
def set_article
@article = Article.find(params[:id])
end
This way, you donβt have to duplicate the logic in every action, and your controller becomes much more readable. π
4. Paginate Data for Better Performance π
When dealing with large datasets, loading everything at once can slow down your application. Use pagination to load only a portion of the data at a time.
π Example:
def index
@posts = Post.paginate(page: params[:page], per_page: 10)
end
Consider using libraries like Kaminari or WillPaginate to implement pagination easily. π
π Must-Know Libraries for Controllers
1. Pundit - Simplify Authorization with Policies π
Pundit is a great gem for managing authorization. It helps you define policies to control what users are allowed to do in your application.
π Example:
class PostPolicy < ApplicationPolicy
def update?
user.admin? || record.user == user
end
end
You can then use the policy in your controller to authorize user actions:
def update
@post = Post.find(params[:id])
authorize @post
@post.update(post_params)
end
This keeps your authorization logic out of the controller, making your code much cleaner and easier to manage. π§ββοΈ
2. Responders - Handle Different Response Formats Easily π οΈ
Rails controllers often need to respond to various formats (HTML, JSON, XML, etc.). Responders simplifies this by providing an easy way to handle multiple formats without bloating your controller code.
π Example:
class PostsController < ApplicationController
respond_to :html, :json
def show
@post = Post.find(params[:id])
respond_with(@post)
end
end
This makes it super easy to handle API responses and other formats in a single controller action. π
3. ActiveModelSerializers - Format JSON Responses for APIs π
When building APIs, formatting JSON data is crucial. ActiveModelSerializers makes it simple to format your model data for JSON responses in a standardized way.
π Example:
class PostSerializer < ActiveModel::Serializer
attributes :id, :title, :content, :created_at
belongs_to :user
end
# In the controller:
def show
@post = Post.find(params[:id])
render json: @post
end
This gem helps you create custom JSON structures and keeps your API responses organized. π¦
π‘ Pro Hacks for Controllers
1. Use Concerns for Shared Logic Across Controllers π
If you have shared logic across multiple controllers, consider using concerns to group that logic in one place.
π Example:
# app/controllers/concerns/findable.rb
module Findable
extend ActiveSupport::Concern
included do
before_action :set_record, only: [:show, :edit, :update, :destroy]
end
private
def set_record
@record = controller_name.classify.constantize.find(params[:id])
end
end
# Include it in your controllers:
class PostsController < ApplicationController
include Findable
end
This makes your controllers DRY and ensures consistency across your app. π
2. Optimize with Caching for Expensive Queries β‘
For actions that involve expensive database queries, you can use fragment caching to store parts of the view and avoid repeated queries.
π Example:
<% cache @post do %>
<h2><%= @post.title %></h2>
<p><%= @post.content %></p>
<% end %>
This helps reduce database load and improves performance, especially when dealing with frequently accessed data. β‘
3. Use Redirect and Flash Wisely π¦
Providing feedback to users after actions (like creating or updating records) is important. Use flash messages and redirects to guide users smoothly.
π Example:
def create
@post = Post.new(post_params)
if @post.save
redirect_to @post, notice: 'Post was successfully created.'
else
render :new
end
end
This improves the user experience by giving clear and instant feedback. π¬
π Wrapping Up
The Controller is the glue that binds your Rails app together. By applying these tips, tricks, and using powerful libraries like Pundit for authorization, Responders for multiple formats, and ActiveModelSerializers for APIs, you can keep your controllers lean and effective.
With a clear understanding of the Model, View, and Controller in Rails, youβre well on your way to mastering the MVC pattern. π― Stay tuned for more advanced topics in future posts!
Whatβs your go-to tip for organizing controllers? Drop a comment below! π
© Lakhveer Singh Rajput - Blogs. All Rights Reserved.