:ok.get_by/3 is undefined

I am trying to implement user auth in a new Phoenix 1.3 app and am getting the following error:

function :ok.get_by/3 is undefined (module :ok is not available)

nofile :ok.get_by/3
lib/MyApp_web/controllers/auth.ex:24 MyAppWeb.Auth.login_by_username/4
lib/MyApp_web/controllers/session_controller.ex:9 MyAppWeb.SessionController.create/2
lib/MyApp_web/controllers/session_controller.ex:1 MyAppWeb.SessionController.action/2
lib/MyApp_web/controllers/session_controller.ex:1 MyAppWeb.SessionController.phoenix_controller_pipeline/2
lib/MyApp_web/endpoint.ex:1 MyAppWeb.Endpoint.instrument/4

Here is my lib/MyApp_web/controllers/auth.ex file:

  def login(conn, user) do
    conn
    |> assign(:current_user, user)
    |> put_session(:user_id, user.id)
    |> configure_session(renew: true)
  end

  def login_by_username(conn, username, password, opts) do
    repo = Keyword.fetch(opts, :repo)
    user = repo.get_by(MyApp.Accounts.User, username: username)

  cond do
    user && checkpw(password, user.password_hash) ->
      {:ok, login(conn, user)}
    user ->
      {:error, :unauthorized, conn}
    true ->
      dummy_checkpw()
    {:error, :notfound, conn}
   end
  end

Here is my session controller:

def new(conn, _params) do
  render(conn, "new.html")
end

  def create(conn, %{"session" => %{"username" => username, "password" => password}}) do
    case MyAppWeb.Auth.login_by_username(conn, username, password, repo: Repo) do
      {:ok, conn} ->
        conn
        |> put_flash(:info, "welcome back")
        |> redirect(to: page_path(conn, :index))
      {:error, _reason, conn} ->
        conn
        |> put_flash(:error, "invalid username/password")
        |> render("new.html")
    end
  end

Any insight would be appreciated.

Keyword.fetch returns {:ok, value}, or :error. You need to either destructure the return or use Keyword.fetch!

What is the reason for passing Repo in to login_by_username? You should be able to do MyApp.Repo.get_by() inside of login_by_username without passing it.

1 Like

Keyword.fetch returns {:ok, key}.

So if you do

{:ok, repo} = Keyword.fetch(opts, :repo)
user = repo.get_by(...)
1 Like

For information on ‘why’ that error happens, see: Tuple Calls

2 Likes

Hi Kyle,

Thanks for the insight. I was using the user auth from Programming Phoenix.

  • Rich

Thanks all, I was able to solve the issue using:

user = MyApp.Repo.get_by!(MyApp.Accounts.User, username: username)
  • Rich