Reputation: 75820
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:
params
from a Plug
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!
Upvotes: 17
Views: 3479
Reputation: 23184
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.
Upvotes: 25
Reputation: 66
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.
Upvotes: 3