wingyplus

wingyplus

ZoiDefstruct - an extension for Zoi to generate Elixir struct

I just did a dirty hack after seeing Zoi on x.com a few hours ago.

Quick Introduction

The zoi_defstruct is a library to help you generate a struct from the Zoi object schema (over Zoi.object). Let’s see a small example below:

defmodule K8S.Deployment do
  use ZoiDefstruct

  @schema Zoi.object(%{
            apiVersion: Zoi.string(),
            metadata:
              Zoi.object(%{
                name: Zoi.string()
              }),
            spec:
              Zoi.object(%{
                replicas: Zoi.integer() |> Zoi.optional()
              })
          })

  defstructure(@schema)
end

When you call a defstructure The macro generates a struct with enforced keys and typespec for you automatically. So in the IEx, you can see:

A struct:

iex(4)> K8S.Deployment.__struct__()
%K8S.Deployment{spec: nil, metadata: nil, apiVersion: nil}

A typespec declaration:

iex(1)> t K8S.Deployment
@type t() :: %{
        spec: %{optional(:replicas) => integer()},
        metadata: %{name: binary()},
        apiVersion: binary()
      } 

ArgumentError if it has no required keys:

iex(5)> %K8S.Deployment{}
** (ArgumentError) the following keys must also be given when building struct K8S.Depl
oyment: [:spec, :metadata, :apiVersion]
    (examples 0.1.0) expanding struct: K8S.Deployment.__struct__/1
    iex:5: (file)

Since this is a quick hack, it has numerous edge cases that need to be addressed. Please feel free to provide feedback or suggestions. Opening an issue or pull request is very welcome.

I need to give special thanks to Zoi for making this awesome library!

https://github.com/wingyplus/zoi_defstruct

Most Liked

charlieaten

charlieaten

Great work @wingyplus, this is some inspiring stuff.

One concern I had though with this approach is that having a defstruct-like DSL that looks like Kernel.defstruct but behaves differently can be confusing.

Your work inspired me to experiment with Sigil, a proof-of-concept DSL for defining nested structs and validating external data using Zoi:

defmodule Post do
  use Sigil.Schema

  schema do
    field :title, Zoi.string()

    field :image, Image do
      field :url, Zoi.string()
      field :blurhash, Zoi.string()

      field :metadata, Metadata do
        field :size, Zoi.integer() |> Zoi.optional()
        field :format, Zoi.string() |> Zoi.optional()
      end
    end
  end
end

I’m still iterating and may try more compact forms for types like:

field :age, :integer, coerce: true

This has been a great way to learn macros and DSL design, and aims to complement(and obviously heavily inspired by) Ecto. Whereas Ecto handles data mapping and persistence at the external data/application(and database) layer, validation libraries like zoi and the likes and thus Sigil aim to provide a layer that works great for things like wrapping external api’s into client libraries and doing validation and egornomic casting into elixir constructs.

Thanks again—I hope others find it interesting.

phcurado

phcurado

awesome @wingyplus

You can leverage some of the helpers on the Zoi Struct module as @byu mentioned. I personally decided to not add any macros into the library (unless strictly necessary like infering type specs) but I added these helpers for anyone who wishes to extend it.
Thanks for using Zoi, awesome to see this

nulltree

nulltree

I’m so happy libraries like Zoi seem to catch on and inspire extension (infant adoption steps, but still).

They complement my way of thinking really well!

Where Next?

Popular in Announcing Top

wmnnd
Hi there, for my project DBLSQD, I needed a file storage solution that is a bit more flexible than Arc. Because I thought others might f...
New
sasajuric
I’d like to announce a small library called boundaries. This is an experimental project which explores the idea of enforcing boundaries ...
New
kip
Image is an image processing library for Elixir. It is based upon the fabulous vix library that provides a libvips wrapper for Elixir. I...
622 19010 194
New
mindok
What is ContEx? A pure Elixir server-side data plotting/charting library outputting SVG. It has nice barcharts in particular and works g...
New
treble37
Just looking for a little feedback on a tiny helper library I built - Sometimes I find the need to convert maps with atom keys to maps w...
New
hpopp
After just over two years in development, this latest version of Pigeon is what I finally consider done in regards to my original vision ...
New
michalmuskala
Hello everybody. I have just released Jason - a new JSON library. You might be wondering, why do we need a new library? The primary foc...
New
zachdaniel
Ash Framework What is Ash? Ash Framework is a declarative, resource-oriented application development framework for Elixir. A resource can...
New
anshuman23
Hello all, I have been working on my proposed project called Tensorflex as part of Google Summer of Code 2018.. Tensorflex can be used f...
New
New

Other popular topics Top

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
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
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
chrismccord
Phoenix 1.4.0 released Phoenix 1.4 is out! This release ships with exciting new features, most notably with HTTP2 support, improved deve...
688 31194 112
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
grych
Hi folks, Few months ago I have announced the proof-of-concept of the library to manipulate the browsers DOM objects directly from Elixi...
639 52774 488
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1144 54250 245
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

We're in Beta

About us Mission Statement