I'm creating my first Elixir
-Phoenix
app. I've written a few plugs that I want to use in multiple controllers, right now there is a lot of code duplication since the Plug code is being repeated in all of my controllers.
My question is, is there a file where I can put all of my Plugs and then access and use them from different controllers?
# somefile to define my plugs defp load_subject(conn, _) do subject = Subject |> Repo.get conn.params["subject_id"] assign(conn, :subject, subject) end defp load_topic(conn, _) do topic = Topic |> Repo.get conn.params["topic_id"] conn |> assign :topic, topic end
Then use them in my controllers:
# First Controller defmodule MyApp.FirstController do use MyApp.Web, :controller plug :load_subject plug :load_topic plug :action def some_action(conn, _) do # do something end def another_action(conn, _) do # do some other thing end end # Second Controller defmodule MyApp.SecondController do use MyApp.Web, :controller plug :load_subject plug :load_topic plug :action def lame_action(conn, _) do # do something end def cool_action(conn, _) do # do some other thing end end
Plug is a specification for composable modules in between web applications. It is also an abstraction layer for connection adapters of different web servers. The basic idea of Plug is to unify the concept of a "connection" that we operate on.
In the Elixir world, Plug is the specification that enables different frameworks to talk to different web servers in the Erlang VM. If you are familiar with Ruby , Plug tries to solve the same problem that Rack does, just with a different approach.
Phoenix controllers act as intermediary modules. Their functions — called actions — are invoked from the router in response to HTTP requests. The actions, in turn, gather all the necessary data and perform all the necessary steps before invoking the view layer to render a template or returning a JSON response.
You can define the plugs in any module as public functions:
defmodule MyApp.Loaders do import Plug.Conn def load_subject(conn, _) do subject = Subject |> Repo.get conn.params["subject_id"] assign(conn, :subject, subject) end def load_topic(conn, _) do topic = Topic |> Repo.get conn.params["topic_id"] conn |> assign :topic, topic end end
Now you can import it in your controllers and use the plugs:
defmodule MyApp.Controller do use MyApp.Web, :controller import MyApp.Loaders plug :load_subject plug :load_topic plug :action ... end
Alternatively, you can also create a pipeline in your router:
import MyApp.Loaders pipeline :with_subject_and_topic do plug :load_subject plug :load_topic end
And then pipe_through
it in the relevant scopes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With