Fl4m3Ph03n1x

Fl4m3Ph03n1x

How to convert a typed definition to a typedstruct?

Background

I am moving towards defined data structures in my application, and I find that TypedStruct is quite useful.

Questions

However, I have recently found a little hickup. I don’t know how to convert this definition into a typedstruct:

  @type order_info :: %{
    (visible :: String.t()) => boolean,
    (order_type :: String.t()) => String.t(),
    (platform :: String.t()) => String.t(),
    (platinum :: String.t()) => non_neg_integer,
    (user :: String.t()) => %{
      (ingame_name :: String.t()) => String.t(),
      (status :: String.t()) => String.t()
    }
  }

My main issue here is the user map. Aside from the fact I don’t know how to define a typedstruct inside a trypedstruct, how do you folks do this?

  1. Do you simply define a map inside the order_info typedstruct and ignore the mandatory parameters for the user map?
  2. Do you create another typedstruct (called user) that goes inside the typedsctruct called order_info?
  3. What is the standard option in Elixir ?

Marked As Solved

Fl4m3Ph03n1x

Fl4m3Ph03n1x

Answer

After talking with other folks at the community I have opted for separating the User into a struct, in its own module, inside an OrderInfo directory:

lib/
  order_info/
    user.ex
  order_info.ex

I personally find this works great for readability. So for readability purposes this is what I ended up with:

defmodule AuctionHouse.Data.OrderInfo.User do
  @moduledoc """
  Represents the account information for a User.
  """

  use TypedStruct

  alias AuctionHouse.Shared.Utils

  @type user :: %{
          (ingame_name :: String.t()) => String.t(),
          (status :: String.t()) => String.t()
        }

  typedstruct enforce: true do
    @typedoc "Account information of an User"

    field(:ingame_name, String.t())
    field(:status, String.t())
  end

  @spec new(user) :: __MODULE__.t()
  def new(
        %{
          "ingame_name" => ingame_name,
          "status" => status
        } = user
      )
      when is_binary(ingame_name) and is_binary(status),
      do: Utils.string_map_to_struct(user, __MODULE__)
end

An then OrderInfo is basically the same, as seen by this typedstruct definition:

  typedstruct enforce: true do
    @typedoc "Information about an order"

    field(:visible, boolean())
    field(:order_type, String.t())
    field(:platform, String.t())
    field(:platinum, non_neg_integer())
    field(:user, __MODULE__.User.t())
  end

Extra

One thing to mention here, is that struct will not convert string maps to structures, only atom maps. So in order to achieve my goal of converting string maps to structures, I created this little helper function:

defmodule AuctionHouse.Shared.Utils do
  @moduledoc """
  Set of functions used across the app, for utility purposes, like dealing with
  tuples, maps and other data structures.
  """

  alias Morphix

  @spec string_map_to_struct(data :: map, target_struct :: module | struct) ::
          target_struct :: struct
  def string_map_to_struct(data, target_struct) do
    data
    |> Morphix.atomorphiform!()
    |> data_to_struct(target_struct)
  end

  @spec data_to_struct(data :: Enumerable.t(), target_struct :: module | struct) ::
          target_struct :: struct
  def data_to_struct(data, target_struct), do: struct(target_struct, data)
end

Here I used Morphix to do the hard work, but this can also be achieved by other means, see:

Many thanks to all of the people who helped me get this far, from other communities as well:

Where Next?

Popular Backend topics Top

pillaiindu
Cross posting from HashNode. A friend of mine is creating Uber-like app for a small company with 200 to 1000 cars. The app will operate ...
New
Rainer
Is there somewhere a good introduction to rust for experienced programmers (with years of C++/C#/Java experience)? Wanted to give it a t...
New
IhorYachmenov
Hello. I have an iOS app where needs a proxying website through private server(HTTP / HTTPS proxy), but its idea each time has some trou...
New
Kurisu
Hello and happy new year! I would like to buy a Ruby On Rails ebook for learning purpose. What would be the ROR equivalent of “Programm...
New
gagan7995
API 4 Path: /user/following/ Method: GET Description: Returns the list of all names of people whom the user follows Response [ { ...
New
Fl4m3Ph03n1x
Background I am trying to encode a structure into json format using the Jason library. However, this is not working as expected. Code L...
New
Fl4m3Ph03n1x
Background I have to queries that return a colossal amount of data on their own. I cannot use Repo.all as doing so would materialize thes...
New
harwind
In C, how they are different? char str[] = "xyz"; // statement //and char str[4] = "xyz"; // statement The first, i...
/c
New
harwind
I’m presently working on a backend development project to build a RESTful API using Python and Flask. The Scaler backend developer site h...
New
Shiny
Hey community, this is my first post here so I will try to be as concise as possible and I appreciate any feedback. I’ve been writing Ro...
New

Other popular topics Top

PragmaticBookshelf
Free and open source software is the default choice for the technologies that run our world, and it’s built and maintained by people like...
New
PragmaticBookshelf
Write Elixir tests that you can be proud of. Dive into Elixir’s test philosophy and gain mastery over the terminology and concepts that u...
New
PragmaticBookshelf
Design and develop sophisticated 2D games that are as much fun to make as they are to play. From particle effects and pathfinding to soci...
New
PragmaticBookshelf
Learn different ways of writing concurrent code in Elixir and increase your application's performance, without sacrificing scalability or...
New
DevotionGeo
The V Programming Language Simple language for building maintainable programs V is already mentioned couple of times in the forum, but I...
New
PragmaticBookshelf
Create efficient, elegant software tests in pytest, Python's most powerful testing framework. Brian Okken @brianokken Edited by Kat...
New
AstonJ
We’ve talked about his book briefly here but it is quickly becoming obsolete - so he’s decided to create a series of 7 podcasts, the firs...
New
PragmaticBookshelf
Get the comprehensive, insider information you need for Rails 8 with the new edition of this award-winning classic. Sam Ruby @rubys ...
New
AstonJ
Curious what kind of results others are getting, I think actually prefer the 7B model to the 32B model, not only is it faster but the qua...
New
mindriot
Ok, well here are some thoughts and opinions on some of the ergonomic keyboards I have, I guess like mini review of each that I use enoug...
New