ruby
45 lines · 9 steps
How before_action filters guard a Rails controller
A Rails controller layers authentication, record loading, and ownership checks through ordered before_action filters.
Explained by
highlit
1class ArticlesController < ApplicationController
2 before_action :authenticate_user!
3 before_action :set_article, only: %i[show edit update destroy]
4 before_action :authorize_owner!, only: %i[edit update destroy]
5 skip_before_action :authenticate_user!, only: %i[index show]
6
7 def index
8 @articles = Article.published
9 end
10
11 def show
12 end
13
14 def edit
15 end
16
17 def update
18 if @article.update(article_params)
19 redirect_to @article, notice: "Article updated."
20 else
21 render :edit, status: :unprocessable_entity
22 end
23 end
24
25 def destroy
26 @article.destroy
27 redirect_to articles_path, notice: "Article deleted."
28 end
29
30 private
31
32 def set_article
33 @article = Article.find(params[:id])
34 end
35
36 def authorize_owner!
37 return if @article.user == current_user
38
39 redirect_to articles_path, alert: "Not authorized."
40 end
41
42 def article_params
43 params.require(:article).permit(:title, :body, :published)
44 end
45end
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1before_action filters run in declaration order, so authentication, loading, and authorization stack predictably around each action.
- 2Scoping filters with only:/skip lets one controller serve public reads and protected writes without per-action conditionals.
- 3Returning early from an authorization filter and redirecting halts the action chain before the body ever runs.
Related explainers
ruby
require "shellwords" require "open3" module Backup
Building safe shell commands in Ruby
shell-out
subprocess
command-injection
Intermediate
7 steps
ruby
class UserAgentParser BROWSERS = [ [/Edg\/([\d.]+)/, "Edge"], [/OPR\/([\d.]+)/, "Opera"],
Parsing user-agent strings in Ruby
regex
pattern-matching
lookup-tables
Intermediate
8 steps
ruby
class LogAggregator BUCKET_FORMAT = "%Y-%m-%dT%H:%M" def initialize(entries)
Bucketing log entries by the minute in Ruby
aggregation
hashing
enumerable
Intermediate
5 steps
ruby
class WeeklySignupsReport DEFAULT_WEEKS = 12 def initialize(weeks: DEFAULT_WEEKS, source: User.all)
Building a weekly signups report in Rails
service object
aggregation
group by
Intermediate
7 steps
ruby
class ApplicationController < ActionController::Base EXPERIMENTS = { checkout_button_color: %w[control blue green], onboarding_flow: %w[control streamlined]
How A/B test cohorts are assigned in Rails
a-b-testing
cookies
hashing
Intermediate
8 steps
go
package middleware import ( "net/http"
Per-plan export limits in Gin middleware
middleware
rate-limiting
authorization
Intermediate
7 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/how-before_action-filters-guard-a-rails-controller-explained-ruby-c54b/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.