How to "nil" check in html eex?

Hi!
I am studying elixir and phoenix from Udemy course.

What I was trying to do is this,
User creates a new topic for discussion, and only user that creates topic can edit and delete them from indexi page.
So in index.html.eex

<ul class="collection">
  <%= for topic <- @topics do %>
   <li class="collection-item">
     <%= link topic.title, to: topic_path(@conn, :show, topic) %>

      **<% if @conn.assigns.user.id == topic.user_id do %>**
        <div class="right">
           <%= link "Edit", to: topic_path(@conn, :edit, topic)%>
           <%= link "Delete", to: topic_path(@conn, :delete, topic), method: :delete %>
        </div>
      <% end %>

   </li>
  <% end %>
</ul>

in topic controller

def index(conn, _params) do
    topics = Repo.all(Topic)
    render conn, "index.html", topics: topics
end

and I got

function nil.id/0 is undefined or private

I think it is because of assigns.user is nil before sign in, in this line @conn.assigns.user.id.
So How can I solve this problem?

Thank you!

Maybe?

if @conn.assigns.user && @conn.assigns.user.id == topic.user.id do

You can also create a method in your view module like:

def topic_owner?(%{id: id}, %{user_id: u_id}) do
    id == u_id
end

def topic_owner?(_, _), do: false

And then use it on your view templates as:

<%= if topic_owner?(@conn.assigns.user, topic) do %>

3 Likes

assigns is just a Map.

<% if (Map.hasKey? @conn.assigns, :user) && (@conn.assigns.user.id == topic.user_id) do %>

would test for the presence of the :user key first. Alternately

<% if (get_in @conn.assigns, [:user, :id]) == topic.user_id do %>

is probably preferable as Kernel.get_in/2 will simply return nil if it can’t navigate down the path.

Edit: but wrapping the whole thing in a well named function is always a good idea.

1 Like

I assume you are working on the Udemy course, because I am getting the same error.

I found this solution in the Q&A…

“”"
I had to change this line of code

<%= if @conn.assigns.user.id == topic.user_id do %>
to

<%= if @conn.assigns.user != nil and @conn.assigns.user.id == topic.user_id do %>

“”"
https://www.udemy.com/the-complete-elixir-and-phoenix-bootcamp-and-tutorial/learn/v4/questions/2395736

Would anyone know how this affects things/safety moving forward?
Thanks!

Hi, i was able to login by running the server and going to localhost:4000/auth/github.

Something like this might be the easiest solution.

<%= unless is_nil @conn.assigns.user and @conn.assigns.user.id == topic.user_id  do %>
        <div class="right">
           <%= link "Edit", to: topic_path(@conn, :edit, topic)%>
           <%= link "Delete", to: topic_path(@conn, :delete, topic), method: :delete %>
        </div>
<% end %>
1 Like
<%= if @conn[:assigns][:user][:id] == topic.user_id do %>
  …
<% end %>

This uses the fact, that nil[:foo] will return nil.

But to be honest, I’d create a helper function current_user which does exactly that, return either the currently logged in user or a value signaling that no user is currently logged in.

Its not that you have less to type, but its easier to read…

2 Likes