ca1989

ca1989

Do I need a macro to do this, or can I go away with something else?

Hi all,

I have many components (about ~50) that have 3 common attributes, now I am going to add a couple more, and before I do that I am seeking some advice.

attr :class, :string, default: ""
attr :id, :string, default: nil
attr :rest, :global 

Currently, I have repeated those ~50 times.

  • is there a way to avoid repeating those all the times?
  • is a macro the tool I want (I know nothing about macros)?
  • I would love to keep the class and id attrs separated from the rest for documentation purposes

Thank you
Cheers!

Marked As Solved

dimitarvp

dimitarvp

I am not seriously suggesting it, I am saying it’s one of the potentially viable solutions just to illustrate that it would be too much to use macros here.

That would be a good candidate for a macro. Have that parent have defmacro __using__(opts \\ []) macro and inject code through it.

That way you can have all your 50+ components only have this line at the top:

use Parent, option_1: true, option_2: ["hello", "there"], option_3: :duh

…and the rest will be just their specific parts.


Or, if you are REALLY convinced that this is a strict parent-children relationship and that this will not change – i.e. you will never need multiple parents per one child – then you can just use Elixir’s protocols and apply a little violence.

Also Liked

D4no0

D4no0

I would avoid going this path, as the benefit you gain (1 line of code vs 3 lines of code) is not worth it, because it will make the code much less readable.

D4no0

D4no0

Actually I would avoid using here __using__ as it is not necessary. I would something like this:

defmodule Attributes do
  defmacro generic_attributes() do
    quote do
      attr :class, :string, default: ""
      attr :id, :string, default: nil
      attr :rest, :global 
    end
  end
end

And using it inside of components by:

require Attributes

Attributes.generic_attributes()

The advantages are:

  1. Much more readability, as you can document the macro and have a clear understanding where you use it, opposed to use;
  2. Macro defined in this way can only inject code, to avoid people coming later and adding their “smart” ideas.
dimitarvp

dimitarvp

You are not wrong but I would be completely okay if one module’s only job was to inject code in others. Having huge modules doing many things with many code-injection macros is not exactly a win for readability and maintainability.

In the end it’s your call, and the difference can be easily handled.

Where Next?

Popular in Questions Top

Tee
can someone please explain to me how Enum.reduce works with maps
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
shahryarjb
Hello, I get Persian date from my client and convert it to normal calendar like this: def jalali_string_to_miladi_english_number(persi...
New
LegitStack
I’m trying to make a websocket server in Phoenix or raw Elixir. I heard about gun, I think I could use cowboy, but since I’m not that sma...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
chensan
I have a User schema with a :from_id field set to type :string: defmodule TweetBot.Repo.Migrations.CreateUsers do use Ecto.Migration ...
New
jaysoifer
Is there a way to rollback a specific migration and only that one (“skipping” all the other ones)? Would mix ecto.rollback -v 200809061...
New
svb
Hi! Currently I want to submit a form by pressing the Enter key. However, since my input field is of type “textarea” this is just adds a...
New

Other popular topics Top

senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 43806 214
New
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
josevalim
Hi everyone, One of the features added to Elixir early on to help integration with Erlang code was the idea of overridable function defi...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
hariharasudhan94
Lets say I have map like this fetching from my database %{"_id" => #BSON.ObjectId<58eb1a7a9ad169198c3dXXXX>, "email" => ...
New
svb
Hi! Currently I want to submit a form by pressing the Enter key. However, since my input field is of type “textarea” this is just adds a...
New

We're in Beta

About us Mission Statement