Is it possible to do this with Macros?

Hi there,

I actually haven’t looked into macros yet, so what I’d like to do might not be possible to to at all. However, I’m wondering if it’s possible to do the following using macros:

# Write this:
can!(link("Edit", to: user_path(@conn, :edit, @user)))
                               |                   |
                               ---------------------
                                         |
                                        \|/
                 -------------------------
# Get this:      |
                 |
                \|/
       ---------------------
       |                   |
if can?(@conn, :edit, @user) do
  link("Edit", to: user_path(@conn, :edit, @user))
end

Yes, that’s doable. However, why are user and conn prefixed with @? It also doesn’t seem all that helpful to do this with macros vs a normal approach with functions.

1 Like

I wanted to use it in my Phoenix templates, so these @s are just assigns. I also don’t think that macros are a good way to do what I want anymore, I will rather do it with functions.

I just thought that I could make code like the following a bit nicer, but I’ll just build a function for “checked links or so”.

<%= if can?(@conn, :show, user) do %>
  <%= link "Show", to: user_path(@conn, :show, user) %>
<% end %>

<%= if can?(@conn, :edit, user) do %>
  <%= link "Edit", to: user_path(@conn, :edit, user) %>
<% end %>

<%= if can?(@conn, :delete, user) do %>
  <%= link "Delete", to: user_path(@conn, :delete, user), method: :delete, data: [confirm: "Are you sure?"] %>
<% end %>

What about the helper function returns link only when when “can” and nil in the other case?

def link_when_can(conn, title, action, user) do
  if can?(conn, action, user) do
    link title, to: user_path(conn, action, user)
  else
    nil #not really needed, just for readability
  end
end

in template:

<%= link_when_can @conn, "Show", :show, user %>

Note the function! convention is used in the standard library for functions that may raise exceptions… I believe the function based approach mentioned by grych is a better option, but the macro version is also possible.