Plug call results in an argument error

Hello geeks,

I just wrote my first plug, here is it:

defmodule RumblWeb.AuthController do
  import Plug.Conn
  def init(opts) do
    Keyword.fetch(opts, :repo)
  end

  def call(conn, repo) do
    user_id = get_session(conn, :user_id)
    user = user_id && repo.get(Rumbl.User, user_id)
    assign(conn, :current_user, user)
  end

but whenever I try to access the route that uses that plug I get the following error ** (ArgumentError) argument error :erlang.apply({:ok, Rumbl.Repo}, :get, []) (rumbl) lib/rumbl_web/controllers/auth_controller.ex:9: RumblWeb.AuthController.call/2 (rumbl) RumblWeb.Router.browser/2 (rumbl) lib/rumbl_web/router.ex:1: RumblWeb.Router.__pipe_through0__/1 (phoenix) lib/phoenix/router.ex:283: Phoenix.Router.__call__/2 (rumbl) lib/rumbl_web/endpoint.ex:1: RumblWeb.Endpoint.plug_builder_call/2 (rumbl) lib/plug/debugger.ex:122: RumblWeb.Endpoint."call (overridable 3)"/2 (rumbl) lib/rumbl_web/endpoint.ex:1: RumblWeb.Endpoint.call/2 (phoenix) lib/phoenix/endpoint/cowboy2_handler.ex:42: Phoenix.Endpoint.Cowboy2Handler.init/4
any help?

Thanks in advance.

Welcome to the forum!

https://hexdocs.pm/plug/Plug.html#moduledoc

The result returned by init/1 is passed as second argument to call/2 . Note that init/1 may be called during compilation and as such it must not return pids, ports or values that are not specific to the runtime.

So what is passed in the opts of call/2 isn’t the repo.

From page 89 of Programming Phoenix 1.4
https://media.pragprog.com/titles/phoenix14/code/authentication/listings/rumbl/lib/rumbl_web/controllers/auth.ex

Note how _opts argument is ignored and the repo is accessed via the Accounts context.


You may want to have a look at


The error message is based on this:

:erlang.apply({:ok, Rumbl.Repo}, :get, [])

So what happened:

  def init(opts) do
    Keyword.fetch(opts, :repo)
  end

Keyword.fetch/2 returns a tuple that was then passed as the opts parameter. But even

  def init(opts) do
    {:ok, repo} = Keyword.fetch(opts, :repo)
    repo
  end

Would just return the Rumbl.Repo atom value that is simply the name of the module.

6 Likes

Wow, Thank you very much for this answer.