String comparison in Elixir

I'm trying to compare to bits of string in Elixir - if they're equal then the if block fires or the else block should fire.

def show(conn, %{"id" => id}) do
    Logger.info id
    Logger.info "----------"
    Logger.info conn.assigns.current_user
    if conn.assigns.current_user == id do
        professional = Repo.get!(Professional, id)
        render(conn, "show.html", professional: professional)
    else
      conn
      |> put_flash(:error, "You must be logged in for that!")
      |> redirect(to: site_path(conn, :index))
      |> halt()
    end

In the above, Logger.info id and Logger.info conn.assigns.current_user both return the same thing, but the if block is never entered.

What am I doing wrong?

Upvotes: 3

Views: 12320

Answers (3)

Aleksei Matiushkin
Aleksei Matiushkin

Reputation: 121000

Multiline if is a code smell in 99% of cases. Your snippet might be rewritten as:

case to_string(conn.assigns.current_user) do
id ->
  render(conn, "show.html", professional: Repo.get!(Professional, id))
_ ->
  conn
  |> put_flash(:error, "You must be logged in for that!")
  |> redirect(to: site_path(conn, :index))
  |> halt()
end

I have put this as an answer just to show the approach, the answer by @greg is still better.

Single-line ifs are often used as ternaries in other languages, though:

if a < 42, do: "tiny", else: "huge"

Upvotes: 2

Ninigi
Ninigi

Reputation: 1311

As greg said, it is most likely that your id in the params is a string, so you would have to make sure you are comparing the same types of objects. I would avoid parsing to integer though, because it can yield some unexpected result for example if your id is nil.

I'm not an expert in elixir, but here are a few solutions I can think of:

# String interpolation will automatically cast the interpolated values to string
if "#{conn.assigns.current_user}" == "#{id}" do

# Casting to char list can handle nil values as well as strings and integers
if to_char_list(conn.assigns.current_user) == to_char_list(id) do

# Regular to_string
if to_string(conn.assigns.current_user) == to_string(id) do

Upvotes: 2

greg
greg

Reputation: 102

I'm guessing your conn.assigns.current_user is a number and id is a string. IO.inspect(is_binary(conn.assigns.current_user))

Upvotes: 5

Related Questions