Having trouble with redirect

My goal as expressed in the code examples below is the following:

When a user logs in and is NOT a subscriber they should be forwarded to the subscriber page.

If they ARE a subscriber then they should be forwarded to their user page - IE users/#{id}.

I have working code that redirects to a page that is NOT a user page and it works fine. This is expressed in the first example below. The second code example is a modified version of the first that has been changed in an attempt to get the result expressed in this posting and does not work.

Working code without user redirect

defmodule AppxWeb.LoginController do
  use AppxWeb, :controller
  alias Appx.Accounts.User
  alias Appx.Repo

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

  def create(conn, %{"email" => email_address}) do
    case Repo.get_by(User, email: email_address) do
      %User{id: user_id, subscriber: subscriber?} ->
        conn
        |> put_session(:user_id, user_id)
        |> redirect(to: redirect_path(subscriber?))

      nil ->
        conn
        |> put_flash(:error, "#{email_address} not found")
        |> redirect(to: redirect_path(:index))
    end
  end

  defp redirect_path(true) do
    "/dashboard"
  end

  defp redirect_path(false) do
    "/subscribe"
  end
end

Non working code
The code below gives the following error when the user attempts to log in as a non subscriber


defmodule AppxWeb.LoginController do
  use AppxWeb, :controller
  alias Appx.Accounts.User
  alias Appx.Repo

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

  def create(conn, %{"email" => email_address}) do
    case Repo.get_by(User, email: email_address) do
      %User{id: user_id, subscriber: subscriber?} ->
        conn
        |> put_session(:user_id, user_id)
        |> redirect(to: redirect_path(subscriber?, user_id)) # added second argument

      nil ->
        conn
        |> put_flash(:error, "#{email_address} not found")
        |> redirect(to: redirect_path(:index))
    end
  end

  defp redirect_path(true, id) do  # added second parameter

    "/user/#{id}"                  # added id
  end

  defp redirect_path(false) do  
    "/subscribe"
  end
end

I also tried

  defp redirect_path(false, _id) do    # added id ?
    "/subscribe"
  end

There’s no redirect_path(false, id) and also no redirect_path function matching the call of redirect_path(:index).

How do I fix it?

I’ll have to play with this to make sure, but I think I answered my own problem here:

defmodule AppxWeb.LoginController do
  use AppxWeb, :controller
  alias Appx.Accounts.User
  alias Appx.Repo

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

  def create(conn, %{"email" => email_address}) do
    case Repo.get_by(User, email: email_address) do
      %User{id: user_id, subscriber: false} ->
        conn
        |> put_session(:user_id, user_id)
        |> redirect(to: redirect_path(false))

      %User{id: user_id, subscriber: true} ->
        conn
        |> put_session(:user_id, user_id)
        |> redirect(to: redirect_path(true, user_id))

      nil ->
        conn
        |> put_flash(:error, "#{email_address} not found")
        |> redirect(to: redirect_path(:index))
    end
  end



  defp redirect_path(bool) do

    "/subscribe"
  end

  defp redirect_path(bool, id) do
    # Get ID and do...
    # /users/#{id}

    "/users/#{id}"
  end

end

That’s not the way to do it. You should use the automatic path helper generated by your router. I don’t know what it is called for you because you didn’t show your router, but for example if you have a route get "/users/:id", UserController, :view, then you would use user_path(:view, id). You’re not supposed to define those functions yourself.

Assuming the function is user_path(:view, id) how would you change my code to incorporate it ? I don’t understand what you are saying or what you are inferring that I do. What you are saying doesn’t make any sense without more context

For example your “user is subscriber” clause you would change to:

      %User{id: user_id, subscriber: true} ->
        conn
        |> put_session(:user_id, user_id)
        |> redirect(to: user_path(:view, user_id))

But we would need to see your router.ex to see what the correct name for the path helper is.

user_path(conn, :view, user_id) probably. (needs a conn or an endpoint).

Oh yes, sorry, forgot that one. :slight_smile: Shouldn’t try to type these off the top of my head.

When I change it to match your code It doesn’t work and I get an error. My user action function is named show not view. I changed it and it still didn’t work.

Just for clarity, the code in my answer is not in my user controller(s). It is in a different controller file named login_controller.ex.

EDIT

Nevenrmend, I saw idiots post and changed it accordingly. It seems to work for the time being. I will play with it for a bit.

Can you paste your router.ex? It would really help us. The path helpers are generated based on the controller names. The documentation for them is here: https://hexdocs.pm/phoenix/routing.html#path-helpers

See my edit above