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

tduccuong
Hi, is there any work on GUI with Elixir, that is similar to Electron/Javascript? My idea is to bundle Phoenix and BEAM into a single se...
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
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
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
hariharasudhan94
lets say i have a sample like a = 20; b = 10; if (a > b) do {:ok, "a"} end if (a < b) do {:ok, b} end if (a == b) do {:ok, "eq...
New
nobody
Hi! In PHP: $SERVER['SERVERADDR'] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
komlanvi
Hi everyone, I was playing with phoenix liveView but I run into an issue. I have a form and want to validate each input text when the te...
New
Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
marick
I had some trouble figuring out how to make many-to-many associations work. Once I got it working, I wrote a blog post. Because I'm a nov...
New

Other popular topics Top

Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
AstonJ
Posting this to see if we can make things easier for people to get into Neovim. If you use Neovim and have a favourite distro please let ...
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
JeremM34
Hello, how can I check the Phoenix version ? Thanks !
New
boundedvariable
I am going through the kafka architecture. All the features what the kafka is providing are already in Erlang. I would like hear your opi...
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
klo
Got a question about when to concat vs. prepending items to list then reversing to achieve appending. So i know lists boil down to [1 | ...
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New

We're in Beta

About us Mission Statement