wingyplus

wingyplus

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

Showing Posts 1 to 9

byu

byu

Great. will check it out.

How does it differ from zoi/lib/zoi/struct.ex at main · phcurado/zoi · GitHub ?

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

wingyplus

wingyplus OP

Thanks for the comment :folded_hands:

Actually, it’s a wrapper of those three functions to avoid repetition works.

wingyplus

wingyplus OP

Thanks for the comment. :folded_hands:

I just see that Zoi has a struct helper already (from @byu mentioned). Will refactoring to use those functions instead.

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!

wingyplus

wingyplus OP

Update from the latest main. The defstructure is now changed to defstruct and you can embed the schema into defstruct directly.

The API also use Zoi.Struct under the hood. So the enforce keys and struct declaration is now align with the Zoi upstream.

wingyplus

wingyplus OP

Type composition is now working! You can use t() function to reference another struct.

wingyplus

wingyplus OP

The library is now published on Hex zoi_defstruct | Hex . Feel free to provide feedback, open issues, or pull requests.

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.

— All posts loaded —

Where Next? Top

Trending in Announcing Top

wojtekmach
Hey everyone! Req is an HTTP client for Elixir that I’ve been working on for quite some time. There is already a lot of HTTP clients out...
New
handnot2
Samly can be used to enable SAML 2.0 Single Sign On in a Plug/Phoenix application. This library uses Erlang esaml to provide plug enabl...
New
woylie
Flop is an Elixir library that applies filtering, ordering and pagination parameters to your Ecto queries. offset-based pagination with...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
fuelen
Hi all! I want to present a small library which provides a mix task for generating an Entity-Relationship Diagram for Ecto schemas. You...
New
anuaralfetahe
Hello Published a new library - ProcessHub! ProcessHub is a library designed to manage process distribution within the Elixir cluster. ...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
mudasobwa
I am seeing a lot of aplications of Argumentum ad Vericundiam in software discussions. They do link some piece of writing and point us to...
New
AstonJ
This showed up on my feed.. anyone heard of it? Just hype? Ox Alpha is a reasoning model designed for coding, sustained ag...
New
sergio
It’s not that it’s vocabulary is too advanced. It’s something worse. I get lost trying to follow even a paragraph written by Claude. It’...
New
sorenone
Today we’re releasing Oban for Python. Not an Oban client in Python. Not a pythonx wrapper embedded in Elixir. Nope, it’s a fully operati...
New
akoutmos
@hugobarauna, Dr. Dimitrios Koutmos (my brother) and I (Alex Koutmos) have been hard at work on writing a book on how you can use Elixir ...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews