Question
Rails before_action vs before_filter: What's the Difference in Rails 4?
Question
In Rails 4 and later, generated CRUD controllers use before_action instead of before_filter. Both appear to behave the same way. What is the difference between before_action and before_filter, and why does Rails use before_action in newer code?
Example controller generated by Rails:
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
def show
end
def edit
end
def update
if @post.update(post_params)
redirect_to @post
else
render :edit
end
end
def destroy
@post.destroy
redirect_to posts_url
end
private
def set_post
@post = Post.find(params[:id])
end
end
Short Answer
By the end of this page, you will understand how controller callbacks work in Rails, why before_action and before_filter look identical in Rails 4, and which one you should use in modern Rails applications. You will also see practical examples, common patterns, and mistakes to avoid when using callbacks in controllers.
Concept
In Rails controllers, a callback lets you run code automatically before, after, or around controller actions such as index, show, create, or update.
For example, you might want to:
- load a record before
show - check authentication before
edit - verify authorization before
destroy - set common data for multiple actions
Historically, Rails used names like:
before_filterafter_filteraround_filter
Later, Rails introduced clearer names:
before_actionafter_actionaround_action
In Rails 4, before_action was added as a clearer, preferred name for before_filter. For a time, they both worked and were effectively aliases of each other. In other words, they referred to the same callback mechanism.
Why the rename matters:
- "Action" is clearer than "filter" for controller code.
- It matches what is actually happening: code runs around a controller action.
- It improves readability for beginners and teams.
- New Rails code, guides, and generators follow the newer naming.
So the key idea is:
- Behavior: effectively the same in Rails 4
- Difference: mainly naming and convention
- Recommendation: use
before_actionin modern Rails code
This matters in real programming because controller callbacks are used constantly for cross-cutting logic such as authentication, authorization, setup, and validation. Understanding them helps you read and maintain Rails applications more confidently.
Mental Model
Think of a controller action like entering a room to perform a task.
- The action is the task you came to do.
- A before_action is the checklist you complete before entering.
- An after_action is the cleanup you do afterward.
- An around_action is someone watching the whole process from start to finish.
before_filter and before_action are like two labels for the same checklist in Rails 4. Rails eventually preferred the label that makes more sense: action.
Syntax and Examples
The basic syntax for a controller callback in Rails looks like this:
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
def show
end
private
def set_post
@post = Post.find(params[:id])
end
end
What this does
Before Rails runs the show, edit, update, or destroy action, it first calls set_post.
That means @post is already available inside those actions and their views.
Older equivalent syntax
class PostsController < ApplicationController
before_filter :set_post, only: [:show, :edit, :update, :destroy]
def show
end
private
def set_post
@post = Post.find(params[:id])
end
end
In Rails 4, this is effectively the same idea.
Another common example: authentication
class AdminController < ApplicationController
before_action :require_admin
def dashboard
end
private
def require_admin
redirect_to root_path unless current_user&.admin?
end
end
Here, require_admin runs before dashboard. If the user is not an admin, Rails redirects them instead of continuing normally.
Restricting callbacks
You can control where a callback runs:
before_action :authenticate_user!, only: [:edit, :update]
before_action :set_post, except: [:index, :new, :create]
only:means run the callback only for the listed actions.except:means run it for every action except the listed ones.
Step by Step Execution
Consider this controller:
class PostsController < ApplicationController
before_action :set_post, only: [:show]
def show
@title = @post.title.upcase
end
private
def set_post
@post = Post.find(params[:id])
end
end
Now imagine a request comes in for:
GET /posts/5
Step-by-step
-
Rails receives the request for
show. -
Rails checks whether any callbacks should run before
show. -
before_action :set_post, only: [:show]matches, so Rails runsset_post. -
Inside
set_post, Rails runs:@post = Post.find(params[:id]) -
params[:id]is5, so Rails looks up the post with ID 5. -
@postis now available to the controller. -
Rails enters the
showaction. -
The action runs:
@title = @post.title.upcase -
Rails renders the
showview. -
The view can use
@postand@title.
Important takeaway
The callback runs before the action body, which is why setup logic like loading a model is a common use case.
Real World Use Cases
Controller callbacks are very common in real Rails apps.
1. Authentication
before_action :authenticate_user!
Used to make sure a user is signed in before accessing protected pages.
2. Loading shared records
before_action :set_order, only: [:show, :update, :cancel]
Avoids repeating @order = Order.find(params[:id]) in multiple actions.
3. Authorization
before_action :require_admin, only: [:destroy]
Prevents non-admin users from accessing sensitive actions.
4. Setting common view data
before_action :load_categories
Useful when many actions need the same sidebar or navigation data.
5. Request preparation
before_action :normalize_search_params, only: [:index]
Can clean or transform input before an action uses it.
6. Auditing or logging with related callbacks
Although before_action is common, teams may also use after_action or around_action for logging, timing, or tracking request behavior.
Real Codebase Usage
In real projects, developers usually use callbacks for shared controller concerns, but they try to keep callbacks focused and easy to understand.
Common patterns
Guard clauses for access control
before_action :require_login
private
def require_login
return if current_user
redirect_to login_path, alert: "Please sign in"
end
This is simple and readable: allow the request if the condition is met; otherwise redirect early.
Shared setup methods
before_action :set_project, only: [:show, :edit, :update]
private
def set_project
@project = Project.find(params[:id])
end
This avoids duplication across multiple actions.
Using callbacks with strong parameters indirectly
Callbacks often prepare state, while the action handles saving:
def update
if @project.update(project_params)
redirect_to @project
else
render :edit
end
end
Keeping callbacks narrow
Good callbacks usually do one thing:
- authenticate
- load a resource
- verify permissions
- prepare shared data
When teams become cautious
Too many callbacks can make controller flow harder to follow because behavior is happening "behind the scenes." In larger codebases, developers often:
- keep callback names explicit
- avoid complex business logic in callbacks
- move heavy logic into service objects or models when appropriate
- use
only:andexcept:carefully so callback scope stays obvious
Common Mistakes
1. Thinking before_filter and before_action are different features in Rails 4
In Rails 4, they are effectively aliases for the same controller callback behavior.
2. Using old naming in new code
Broken from a style perspective, even if it may still work in some versions:
before_filter :set_post
Preferred modern style:
before_action :set_post
Use the current convention so your code matches Rails guides and generators.
3. Forgetting to limit the callback to relevant actions
Problematic:
before_action :set_post
If index or new does not have params[:id], this may fail.
Better:
before_action :set_post, only: [:show, :edit, :update, :destroy]
4. Putting too much logic inside a callback
Hard to read:
def set_post
@post = Post.find(params[:id])
@comments = @post.comments.recent.limit(20)
@author = @post.author
@permissions = PermissionService.new(current_user, @post)
@analytics = AnalyticsService.track(@post)
end
Better: keep callbacks focused and move extra logic where it belongs.
5. Hiding important behavior
If many callbacks run before an action, it becomes hard to understand what the action really depends on.
To avoid this:
- use clear names like
set_postorrequire_admin - avoid unnecessary callbacks
- keep callback chains short
6. Assuming a callback always halts execution automatically
A callback can redirect or render, but you should understand the flow clearly in your Rails version and code style.
Example:
def require_admin
redirect_to root_path unless current_user&.admin?
end
Be intentional about what should happen when access is denied.
Comparisons
| Concept | Meaning | Typical Use | Modern Preference |
|---|---|---|---|
before_filter | Run code before a controller action | Older Rails codebases | No |
before_action | Run code before a controller action | Modern Rails codebases | Yes |
after_action | Run code after a controller action | Logging, cleanup, headers | Yes |
around_action | Wrap code around a controller action | Timing, transactions, instrumentation | Yes |
before_filter vs before_action
- In Rails 4, they behave the same for practical purposes.
before_actionis the newer, clearer name.- Rails generators and guides prefer
before_action.
Callback vs writing code directly inside each action
| Approach | Pros | Cons |
|---|---|---|
| Callback | Reduces duplication, centralizes shared setup | Can hide control flow |
| Inline code in each action | Explicit and easy to trace | Repetition across actions |
only: vs except:
| Option | Meaning | Best when |
|---|---|---|
only: | Run for listed actions only | A callback applies to a small set of actions |
except: | Run for all actions except listed ones | A callback applies almost everywhere |
As a rule of thumb, only: is often easier for beginners to read because it shows exactly where the callback applies.
Cheat Sheet
# Modern Rails callback
before_action :method_name
# Older alias seen in older code
before_filter :method_name
# Limit callback to certain actions
before_action :set_post, only: [:show, :edit, :update, :destroy]
# Exclude certain actions
before_action :authenticate_user!, except: [:index, :show]
Key facts
before_actionruns before a controller action.- In Rails 4,
before_actionandbefore_filterare effectively aliases. - Use
before_actionin modern code. - Common uses:
- authentication
- authorization
- loading records
- setting shared data
- Keep callbacks small and focused.
- Prefer clear method names like
set_post,require_login,load_categories. - Use
only:orexcept:to avoid running callbacks where they do not belong.
Good pattern
before_action :set_post, only: [:show, :edit, :update, :destroy]
Avoid
before_action :do_everything
FAQ
Is before_filter deprecated in Rails 4?
Rails 4 introduced before_action as the preferred name. In later Rails versions, before_filter was deprecated and then removed, so modern code should use before_action.
Do before_action and before_filter behave differently?
In Rails 4, for normal controller usage, they are effectively the same callback mechanism.
Why did Rails rename before_filter to before_action?
Because before_action is clearer and better describes that the callback runs before a controller action.
Should I replace before_filter in older projects?
If you are maintaining an older app, updating to before_action can improve consistency and help with future Rails upgrades.
When should I use before_action?
Use it for shared controller setup such as loading records, checking authentication, or enforcing authorization.
Can I overuse controller callbacks?
Yes. Too many callbacks can make controller flow hard to follow. Keep them small, clear, and limited to shared concerns.
What is the difference between before_action and around_action?
before_action runs before the action. around_action wraps the whole action, so it can run code both before and after it.
Mini Project
Description
Build a small Rails-style controller example that uses before_action to load a record and protect an admin-only action. This project demonstrates the most common real uses of controller callbacks: shared setup and access control.
Goal
Create a controller that loads an article before selected actions and blocks non-admin users from deleting articles.
Requirements
[ "Create an ArticlesController with show, edit, update, and destroy actions.", "Use before_action to load the article for actions that need params[:id].", "Use before_action to restrict destroy to admin users only.", "Keep callback methods in the private section.", "Redirect non-admin users instead of allowing destroy to continue." ]
Keep learning
Related questions
Add a Default Value to an Existing Column in a Rails Migration
Learn how to add or change a default value on an existing database column using Rails Active Record migrations safely.
Calling a Class Method from an Instance in Ruby
Learn how to call a class method from an instance in Ruby using self.class, with examples, pitfalls, and practical usage patterns.
Calling an Overridden Monkey-Patched Method in Ruby
Learn how to call the original method when monkey patching in Ruby, including alias_method patterns, examples, pitfalls, and practical usage.