shahryarjb

shahryarjb

Need help to create nested struct macro (A.B.C)

Hello, I am developing a macro to create nested struct in a module or (module → module …), I took the original code from this repo, because it had been abandoned and I want many options for validation etc, I move it inside my project, you can see it in this link.

The problem:

To create a nested struct, I create a new module in one module. For example (A.B.C) is made. Since struct B cannot be called in A at compile time, I just want to create a field named module in its parent struct.
But it seems that the parent has already been compiled and does not allow me to do this.

Please see this part of code:
https://github.com/mishka-group/mishka_developer_tools/blob/master/lib/macros/guarded_struct.ex#L303-L318

in this part I create another module, but how can define a filed which struct type with options

defmodule A do
  defstruct name: "", :b 
  
  defmodule B do
    defstruct name: ""
  end
end

I tried to use @before_compile {__CALLER__.module, :add_parent_field_of_sub_field} to add module attribute like using this

https://github.com/mishka-group/mishka_developer_tools/blob/master/lib/macros/guarded_struct.ex#L296-L300

== Compilation error in file lib/macros/guarded_struct.ex ==
** (ArgumentError) cannot set attribute @before_compile inside function/macro

Even I use this macro inside sub_field macro, to define a field, but it has no effect on my code

Example code I want finally:

  defmodule TestNestedStruct do
    use GuardedStruct

    guardedstruct do
      field(:title, String.t())
      field(:subject, String.t())

      sub_field(:oop, struct(), enforce: true) do
        field(:title, String.t())
        field(:fam, String.t())

        sub_field(:soos, struct(), enforce: true) do
          field(:fam, String.t())
        end

        field(:site, String.t())
      end

      field(:site, String.t())
    end
  end

If I create a field has same name with module name, I can check it inside my builder function.

I have no idea how can do it, thank you in advance

First Post!

shahryarjb

shahryarjb

I think it works for me, but I need more test, if my idea is good for this problem?

  defmacro sub_field(name, type, opts \\ [], do: block) do
    ast = register_struct(block, opts)
    type = Macro.escape(type)

    converted_name =
      name
      |> Atom.to_string()
      |> Macro.camelize()
      |> String.to_atom()
      |> then(&Module.concat(__CALLER__.module, &1))

    quote do
      GuardedStruct.__field__(unquote(name), unquote(type), unquote(opts), __ENV__)

      defmodule unquote(converted_name) do
        unquote(ast)
      end
    end
  end

Output

%MishkaDeveloperToolsTest.GuardedStructTest.TestNestedStruct{
  site: nil,
  oop: nil,
  subject: nil,
  title: nil
}
[:site, :oop, :subject, :title]
[
  __struct__: 0,
  __struct__: 1,
  builder: 1,
  enforce_keys: 0,
  enforce_keys: 1,
  keys: 0,
  keys: 1
]
--------------------------------
%MishkaDeveloperToolsTest.GuardedStructTest.TestNestedStruct.Oop{
  site: nil,
  soos: nil,
  fam: nil,
  title: nil
}
[:site, :soos, :fam, :title]
[
  __struct__: 0,
  __struct__: 1,
  builder: 1,
  enforce_keys: 0,
  enforce_keys: 1,
  keys: 0,
  keys: 1
]
--------------------------------
%MishkaDeveloperToolsTest.GuardedStructTest.TestNestedStruct.Oop.Soos{fam: nil}
[:fam]
[
  __struct__: 0,
  __struct__: 1,
  builder: 1,
  enforce_keys: 0,
  enforce_keys: 1,
  keys: 0,
  keys: 1
]

If you see I just create a field in parent struct and I will check it inside builder function, there is no way I think to load and call the B struct inside A struct field, I think, am I right?

Where Next?

Popular in Questions 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
LegitStack
I’m hoping you guys can give me some general advice and perhaps code examples if you’re feeling up to it. I’m very interested in Elixir,...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
Werner
Hi, I’m using Ubuntu 18.04 and after updating to OTP-24.0 yesterday i have this warning when I run “mix local.hex”: 14:57:30.512 [warn] ...
New
polypush135
As many of you may have realized by now (sorry for all the posts here) I’ve been working on a db problem where I’m trying to aggregate a ...
New
sacepums
Hey guys. I'm new to elixir and im really stocked about it. But I ran into a bit of problem - I need to convert a date sting, for examp...
New
kostonstyle
Hi all I want to have a unix time, from the current time plus 1 hour. DateTime.now + 1 hour How to get it in elixir? Thanks
New
beno
I will often find my self writing things similar to: case some_value do nil -> something() "" -> something() _ -> someth...
New
idi527
I’ve been re-reading swift book again and noticed that multiline strings there don’t have a trailing line break, unlike in elixir iex(2)...
New

Other popular topics Top

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
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
itssasanka
Hi all, Trying to get some more clarity over utc_datetime and naive_datetime for Ecto: https://hexdocs.pm/ecto/Ecto.Schema.html#module-...
New
axelson
This post is a wiki (feel free to hit the edit button near the bottom right of this post to add your own changes!) This post collects co...
239 45766 226
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lis...
New
danschultzer
None of the current solutions worked well for me, so I went ahead and built a user management system from scratch. This project took far...
548 27727 240
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
johnnyicon
Hi all, I've just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I'm trying to use Postg...
New
AstonJ
We’ve put together this wiki for Phoenix LiveView - please feel free to add any info you feel is worth including. What is Phoenix LiveV...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New

We're in Beta

About us Mission Statement