9 ms·
I agree. I've been using Elixir for almost five years and I wrote my first macro this morning. I needed _slightly_ customized code in each instance of set of
by dugmartin 5y ago
I agree. I've been using Elixir for almost five years and I wrote my first macro this morning. I needed _slightly_ customized code in each instance of set of GenServers and it turned out a macro was the cleanest way to do it.
That said, understanding macros will help you sprinkle in your own "magic" in Phoenix though. I normally import a custom view helpers module inside the lib/<project>_web.ex file in this macro like this:
defp view_helpers do
quote do
...
import <project>Web.ViewHelpers
end
end
Then you can add methods in <project>Web.ViewHelpers and they are automagically imported into all your templates, eg.
> lib/<project>_web/view_helpers.ex:
defmodule <project>Web.ViewHelpers do
use Phoenix.HTML # this allows you to use link(), ~E, etc
def tagline, do: "Running light without overbyte"
end
> lib/<project>_web/templates/foo.html.heex
...
<div class="tagline">{tagline()}</div>
- dqv 5y agoAnd actually the <project>Web macros are a great way to show people when macros are useful. A fun exercise for beginners might be to have them manually import those modules. And it illuminates some aspects of Phoenix in general e.g. "oh I'm importing Phoenix.Controller in all my views." In other words, the fact that you're rendering a view from a controller is not the reason you have controller functions available in your views, it's because your importing Phoenix.Controller when you "use ProjectWeb, :view"
- dugmartin 5y agoYeah, the "magic" dispatcher code in <project>_web.ex is pretty powerful but I'm not sure it would be easy for beginners to grok it: @doc """ When used, dispatch to the appropriate controller/view/etc. """ defmacro __using__(which) when is_atom(which) do apply(__MODULE__, which, []) end That said I much prefer how Phoenix puts this code explicitly in each project and doesn't hide it in a gem like Rails.
- dqv 5y agoFor example’s sake, it would be fine to just remove that and do it manually: defmacro __using__(:view), do: view() But I think explaining what each element does in that dispatcher would be helpful. Especially in cases with typos.