View Source Estructura.User (estructura v1.6.0)

Nested example. The source code of the file follows.


defmodule Calculated do
  @moduledoc false
  def person(this) do
    this.name <> ", " <> this.address.city
  end
end

use Estructura.Nested, calculated: [person: &Calculated.person/1]

shape %{
  created_at: :datetime,
  name: :string,
  address: %{city: :string, street: %{name: [:string], house: :string}},
  person: :string,
  data: %{age: :float}
}

init %{
  name: "Aleksei",
  address: %{city: "Barcelona"}
}

coerce do
  def data.age(age) when is_float(age), do: {:ok, age}
  def data.age(age) when is_integer(age), do: {:ok, 1.0 * age}
  def data.age(age) when is_binary(age) do
    age
    |> Float.parse()
    |> case do
      {age, ""} -> {:ok, age}
      {age, _rest} -> {:ok, age}
      :error -> {:ok, 0.0}
    end
  end
end

coerce do
  def name(value) when is_binary(value), do: {:ok, value}
  def name(value) when is_atom(value), do: {:ok, Atom.to_string(value)}
end

validate do
  def address.street.house(house), do: {:ok, house}
end

Now one can cast it from map as below

User.cast %{address: %{city: "London", street: %{name: "Baker", house: "221 Bis"}}, data: %{age: 32}, name: "Watson"}

{:ok,
   %Estructura.User{
     address: %Estructura.User.Address{
       city: "London",
       street: %Estructura.User.Address.Street{house: "221 Bis", name: "Baker"}
     },
     data: %Estructura.User.Data{age: 32.0},
     name: "Watson",
     person: "Watson, London"}}

Summary

Functions

Returns the generator to be used in StreamData-powered property testing, based on the specification given to use Estructura.Nested, which contained

Casts the map representation as given to Estructura.Nested.shape/1 to the nested Estructura instance.

Gets the value for the given key from the structure

Safely parses the json, applying all the specified validations and coercions

Same as parse/1 but either returns the result of successful parsing or raises

Puts the value for the given key into the structure, passing coercion and validation, returns {:ok, updated_struct} or {:error, reason} if there is no such key

Puts the value for the given key into the structure, passing coercion and validation, returns the value or raises if there is no such key

Types

t()

@type t() :: %Estructura.User{
  data: Estructura.User.Data.t(),
  name: String.t(),
  address: Estructura.User.Address.t(),
  person: String.t(),
  created_at: DateTime.t(),
  birthday: Date.t()
}

Functions

__generator__()

@spec __generator__() ::
  StreamData.t(%Estructura.User{
    address: term(),
    birthday: term(),
    created_at: term(),
    data: term(),
    name: term(),
    person: term()
  })

See Estructura.User.__generator__/1

__generator__(this)

@spec __generator__(%Estructura.User{
  address: term(),
  birthday: term(),
  created_at: term(),
  data: term(),
  name: term(),
  person: term()
}) ::
  StreamData.t(%Estructura.User{
    address: term(),
    birthday: term(),
    created_at: term(),
    data: term(),
    name: term(),
    person: term()
  })

Returns the generator to be used in StreamData-powered property testing, based on the specification given to use Estructura.Nested, which contained

shape

%{
  data: %{age: :float},
  name: :string,
  address: %{city: :string, street: %{name: [:string], house: :string}},
  person: :string,
  created_at: :datetime,
  birthday: :date
}

coerce

  def coerce_age(age) when is_float(age) do
    {:ok, age}
  end
  def coerce_age(age) when is_integer(age) do
    {:ok, 1.0 * age}
  end
  def coerce_age(age) when is_binary(age) do
    age
    |> Float.parse()
    |> case do
      {age, ""} -> {:ok, age}
      {age, _rest} -> {:ok, age}
      :error -> {:ok, 0.0}
    end
  end
  def coerce_created_at(value) do
    Estructura.Coercers.Datetime.coerce(value)
  end
  def coerce_birthday(value) do
    Estructura.Coercers.Date.coerce(value)
  end
  def coerce_name(value) when is_binary(value) do
    {:ok, value}
  end
  def coerce_name(value) when is_atom(value) do
    {:ok, Atom.to_string(value)}
  end

validate

  def validate_house(house) do
    {:ok, house}
  end

The argument given would be used as a template to generate new values.

cast(content, options \\ [])

Casts the map representation as given to Estructura.Nested.shape/1 to the nested Estructura instance.

If split: true is passed as an option, it will attempt to put foo_bar into nested %{foo: %{bar: _}}

cast!(content, options \\ [])

get(data, key, default \\ nil)

@spec get(
  %Estructura.User{
    address: term(),
    birthday: term(),
    created_at: term(),
    data: term(),
    name: term(),
    person: term()
  },
  Estructura.Config.key(),
  any()
) :: any()

Gets the value for the given key from the structure

parse(input)

@spec parse(binary()) :: {:ok, struct()} | {:error, Exception.t()}

Safely parses the json, applying all the specified validations and coercions

parse!(input)

@spec parse!(binary()) :: struct() | no_return()

Same as parse/1 but either returns the result of successful parsing or raises

put(data, key, value)

@spec put(
  %Estructura.User{
    address: term(),
    birthday: term(),
    created_at: term(),
    data: term(),
    name: term(),
    person: term()
  },
  Estructura.Config.key(),
  any()
) ::
  {:ok,
   %Estructura.User{
     address: term(),
     birthday: term(),
     created_at: term(),
     data: term(),
     name: term(),
     person: term()
   }}
  | {:error, any()}

Puts the value for the given key into the structure, passing coercion and validation, returns {:ok, updated_struct} or {:error, reason} if there is no such key

put!(data, key, value)

@spec put!(
  %Estructura.User{
    address: term(),
    birthday: term(),
    created_at: term(),
    data: term(),
    name: term(),
    person: term()
  },
  Estructura.Config.key(),
  any()
) ::
  %Estructura.User{
    address: term(),
    birthday: term(),
    created_at: term(),
    data: term(),
    name: term(),
    person: term()
  }
  | no_return()

Puts the value for the given key into the structure, passing coercion and validation, returns the value or raises if there is no such key

recalculate_calculated(data)