Ruby on Rails Explained

Jul 20, 2018

When writing controllers in Ruby on rails, using `before_action` (used to be called `before_filter` in earlier versions) is your bread-and-butter for structuring your business logic in a useful way. It's what you want to use to "prepare" the data necessary before the action executes. The action methods or blocks given the the before_action will execute in the order they where called, meaning in the following scenario, the method `authorize_user` will execute first, followed by `find_post` and finally the controller action will execute (which in this example is the `show` method). ```language-rb class PostsController < ApplicationController before_action :authorize_user before_action :find_post def show # ... end private def authorize_user # ... end def find_post # ... end end ``` An important thing to note is that the methods queued up with `before_action` can halt the execution at any time and return a response by calling any of the controller methods that generate a response, i.e. `render`, `redirect`, `head`, etc. Take the following scenario where if there is no Post matching the :id param, then it will call the render method with a specific template and status code and as a result, the controller action `show` will never execute. By the same logic, we can be sure that if the controller action `show` is executed, then there must be a `@post` instance variable present for us to use in the action and views. ```language-rb def find_post @post = Post.find params[:id] rescue ActiveRecord::RecordNotFound => e render template: 'not_found', status: :not_found end ``` Another thing to keep in mind is that `before_acton` methods can use anything that previous methods have prepared (i.e. instance variables). In the following scenario we require a current user to be present, otherwise we return a 401 access denied response. And after that we only allow a post to be shown if it is associated with said user. ```language-rb def authorize_user @current_user = bearer_token.present? && User.find_by token: bearer_token render template: 'access_denied', status: :access_denied if @current_user.nil? end def find_post @post = @current_user.posts.find params[:id] rescue ActiveRecord::RecordNotFound => e render template: 'not_found', status: :not_found end # Helper method to retrieve the Bearer token from Authorization header def bearer_token regex = /^Bearer / header = request.headers['Authorization'] header.gsub(regex, '') if header&.match(regex) end ``` These are just some ways in which you can implement `before_action` methods. Happy coding!