Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails' before_filter equivalent in Phoenix

I've just started working on my first Phoenix app, and the issue is that I have some common lines of code in every action in my controller, that I would like to separate out. They fetch data from multiple Ecto Models and save them to variables for use.

In Rails, I could simply define a method and call it using before_filter in my controller. I could access the result from an @variable. I understand that using Plugs is the key but I'm unclear on how to achieve this, more specifically:

  • Accessing the request params from a Plug
  • and making the variables accessible in actions

As a reference, this is the rails version of what i'm trying to do:

class ClassController < ApplicationController
    before_filter :load_my_models

    def action_one
        # Do something with @class, @students, @subject and @topics
    end

    def action_two
        # Do something with @class, @students, @subject and @topics
    end

    def action_three
        # Do something with @class, @students, @subject and @topics
    end

    def load_my_models
        @class    = Class.find    params[:class_id]
        @subject  = Subject.find  params[:subject_id]

        @students = @class.students
        @topics   = @subject.topics
    end
end

Thanks!

like image 919
Sheharyar Avatar asked Jun 20 '15 20:06

Sheharyar


2 Answers

You can indeed achieve this with a Plug and Plug.Conn.assign.

defmodule TestApp.PageController do
  use TestApp.Web, :controller

  plug :store_something
  # This line is only needed in old phoenix, if your controller doesn't
  # have it already, don't add it.
  plug :action

  def index(conn, _params) do
    IO.inspect(conn.assigns[:something]) # => :some_data
    render conn, "index.html"
  end

  defp store_something(conn, _params) do
    assign(conn, :something, :some_data)
  end
end

Remember to add the plug declaration before your action plug, as they are executed in-order.

like image 172
Paweł Obrok Avatar answered Oct 25 '22 22:10

Paweł Obrok


This is better as a comment but I lack the rep; with the current version of Phoenix (1.3.4, August of 2018), if you use the top answer's code, you would only want to do plug :store_something: do not use plug :action as it is redundant. The actions will run after the plugs which you listed.

If you include plug :action you will get (Plug.Conn.AlreadySentError) the response was already sent as the action will run twice and Phoenix will be mad at you.

like image 25
Foggy Avatar answered Oct 25 '22 23:10

Foggy