29
.
04
.
2024
25
.
07
.
2022
Ruby on Rails
Backend
Tutorial

Should I use Action Filters?

Mateusz Woźniczka
Ruby Developer

You are developing your first Rails app, which is most likely a Blog - we all have been there :).

At some point, you end up with a controller created by scaffold, which looks more or less, like this:


class PostsController < ApplicationController
  before_action :set_post, only: %i[ show edit update destroy ]

  # GET /posts or /posts.json
  def index
    @posts = Post.all
  end

  # GET /posts/1 or /posts/1.json
  def show
  end

  # GET /posts/new
  def new
    @post = Post.new
  end

  # GET /posts/1/edit
  def edit
  end

  # (...) update create and destroy actions are hidden
  # for the sake of readability

  private
    # Use callbacks to share common setup or constraints between actions.
  def set_post
    @post = Post.find(params[:id])
  end
end

Rails generated set_post method, and even tells you to Use callbacks to share common setup or constraints between actions.

The code is DRY as it can be, you have a nice looking before_action, so it must be the famous Rails way of doing things - and it is.

However some developers (including me) are writing code in a different way.

Why?

Let's assume, that we stick to Filters (it is the official name of this feature despite the fact, that scaffold is calling it callback) - after implementing additional functionalities we can end up with something like this:


class PostsController < ApplicationController
  before_action :set_post, only: %i[ show edit update destroy ]
  before_action :set_user, only: %i[ edit update ]
  before_action :check_admin, only: :destroy
  after_action :send_email, only: %i[ update destroy ]

  # GET /posts or /posts.json
  def index
    @posts = Post.all
  end

  # GET /posts/1 or /posts/1.json
  def show
  end

  # GET /posts/new
  def new
    @post = Post.new
  end

  # GET /posts/1/edit
  def edit
  end

  # (...)

end

Reading edit action has just become a bit harder, because you ended up with an empty action, which is in fact does quite a lot of things.

So in order to understand what is going on there you have to jump back and forth between the filters. And this is relatively simple action - you can image what happens, when the app grows.

What is the 'right' way?

Alternative approach is actually really simple - just call the method inside the action. That's it.

Then you end up with code like this:


class PostsController < ApplicationController

  # GET /posts or /posts.json
  def index
    @posts = Post.all
  end

  # GET /posts/1 or /posts/1.json
  def show
    set_post
  end

  # GET /posts/new
  def new
    @post = Post.new
  end

  # GET /posts/1/edit
  def edit
    set_post
  end

  # (...) update create and destroy actions are hidden
  # for the sake of readability

  private
    # Use callbacks to share common setup or constraints between actions.
  def set_post
    @post = Post.find(params[:id])
  end
end

Now, at first glance at edit or show action you know which method is called.

Got it - let's forget about Action Filters

Actually, not really - they are used for authentication / authorization - you will more than once see code like this, especially when working with devise gem:


class PostsController < ApplicationController
  before_action :authenticate_user!
end

Wrap up

If you are not dealing with authentication / autorization try avoiding using Action Filters (referred by some as ''callbacks'') - they make code harder to read.

Mateusz Woźniczka
Ruby Developer

Check my Twitter

Check my Linkedin

Did you like it? 

Sign up To VIsuality newsletter

READ ALSO

Safe navigation operator '&.' vs '.try' in Rails

14
.
11
.
2023
Mateusz Woźniczka
Ruby on Rails
Backend
Ruby
Tutorial

What does the ||= operator actually mean in Ruby?

14
.
11
.
2023
Mateusz Woźniczka
Ruby on Rails
Backend
Ruby
Tutorial

How to design an entity - DDD in Ruby on Rails

17
.
03
.
2024
Paweł Strzałkowski
Ruby on Rails
Domain-Driven Design
Backend
Tutorial

Entity - DDD in Ruby on Rails

17
.
03
.
2024
Paweł Strzałkowski
Ruby on Rails
Domain-Driven Design
Backend
Tutorial

Should I use instance variables in Rails views?

14
.
11
.
2023
Mateusz Woźniczka
Ruby on Rails
Frontend
Backend
Tutorial

Data Quality in Ruby on Rails

14
.
11
.
2023
Michał Łęcicki
Ruby on Rails
Backend
Software

We started using Event Storming. Here’s why!

14
.
11
.
2023
Mariusz Kozieł
Event Storming
Visuality

First Miłośnicy Ruby Warsaw Meetup

14
.
11
.
2023
Michał Łęcicki
Conferences
Visuality

Should I use Action Filters?

14
.
11
.
2023
Mateusz Woźniczka
Ruby on Rails
Backend
Tutorial

Value Object - DDD in Ruby on Rails

17
.
03
.
2024
Paweł Strzałkowski
Ruby on Rails
Domain-Driven Design
Backend
Tutorial

Introduction to DDD in Ruby on Rails

17
.
03
.
2024
Paweł Strzałkowski
Ruby on Rails
Domain-Driven Design
Backend
Tutorial

Safe data migrations in Rails

17
.
03
.
2024
Paweł Strzałkowski
Ruby on Rails
Backend
Tutorial

I love dev, and so do we!

14
.
11
.
2023
Michał Łęcicki
Software
Conferences

Updated guide to recruitment process at Visuality

14
.
11
.
2023
Michał Łęcicki
Visuality
HR

Visuality Academy for wannabe Junior Engineers

14
.
11
.
2023
Michał Piórkowski
HR
Visuality

How to approach funding as an MVP

14
.
11
.
2023
Michał Piórkowski
Business
Startups

Visuality 13th birthday

14
.
11
.
2023
Michał Piórkowski
HR
Visuality

How To Receive Emails With a Rails App in 2021

14
.
11
.
2023
Michał Łęcicki
Ruby on Rails
Tutorial

Project Quality in IT - How to Make Sure You Will Get What You Want?

02
.
10
.
2024
Wiktor De Witte
Ruby on Rails
Project Management
Business

5 Trends in HR Tech For 2021

14
.
11
.
2023
Maciej Zdunek
Business
Project Management