solnic / drops

🛠️ Tools for working with data effectively - data contracts using types, schemas, domain validation rules, type-safe casting, and more.
Other
257 stars 6 forks source link

Add built-in number type #41

Closed solnic closed 9 months ago

solnic commented 9 months ago

This adds a built-in Number type, which is just a union([:integer, :float]) under the hood:

defmodule ProductContract do
  use Drops.Contract

  schema do
    %{
      required(:name) => string(:filled?),
      required(:price) => number()
    }
  end
end

ProductContract.conform(%{name: "Book", price: 31.2})
# {:ok, %{name: "Book", price: 31.2}}

ProductContract.conform(%{name: "Book", price: 31})
# {:ok, %{name: "Book", price: 31}}

{:error, errors} = ProductContract.conform(%{name: "Book", price: []})
Enum.map(errors, &to_string/1)
# ["price must be a number"]

This type required making use of type opts, which now can be declared as an @opts module attribute in your custom types. The Number type is defined as:

defmodule Drops.Types.Number do
  use(Drops.Type, union([:integer, :float]))

  @opts name: :number
end

The :name option is then used to return a simple error message instead of the default union error like foo must be an integer or foo must be a float.

Using opts will be leveraged more by other future features.

refs #33