3 ms·
It’s too early for you to try metaprogramming. It has very simple rules but proficiency with the language is advised when diving into macros. You might want to
by nesarkvechnep 5y ago
It’s too early for you to try metaprogramming. It has very simple rules but proficiency with the language is advised when diving into macros. You might want to read Chris McCord’s “Metaprogramming Elixir”. The author is also one of Phoenix’s authors.
- dugmartin 5y agoI 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.