ExConstructor (exconstructor v1.2.12)

ExConstructor is an Elixir library that makes it easy to instantiate structs from external data, such as that emitted by a JSON parser.

Add use ExConstructor after a defstruct statement to inject a constructor function into the module.

The generated constructor, called new by default, handles map-vs-keyword-list, string-vs-atom-keys, and camelCase-vs-under_score input data issues automatically, DRYing up your code and letting you move on to the interesting parts of your program.

Installation

  1. Add ExConstructor to your list of dependencies in mix.exs:

     def deps do
       [{:exconstructor, "~> 1.2.11"}]
     end

Usage

Example:

defmodule TestStruct do
  defstruct field_one: 1,
            field_two: 2,
            field_three: 3,
            field_four: 4,
  use ExConstructor
end

TestStruct.new(%{"field_one" => "a", "fieldTwo" => "b", :field_three => "c", :FieldFour => "d"})
# => %TestStruct{field_one: "a", field_two: "b", field_three: "c", field_four: "d"}

For advanced usage, see __using__/1 and populate_struct/3.

Authorship and License

ExConstructor is copyright 2016-2021 Appcues, Inc.

ExConstructor is released under the MIT License.

Summary

Functions

use ExConstructor defines a constructor for the current module's struct.

Alias for __using__, for those who prefer an explicit invocation.

Returns a copy of struct into which the values in map_or_kwlist have been applied.

Returns a copy of struct into which the values in map_or_kwlist have been applied.

Types

Link to this type

map_or_kwlist()

@type map_or_kwlist() ::
  %{required(String.t()) => any()}
  | %{required(atom()) => any()}
  | [{String.t(), any()}]
  | [{atom(), any()}]

Functions

Link to this macro

__using__(name_or_opts \\ :new)

(macro)

use ExConstructor defines a constructor for the current module's struct.

If name_or_opts is an atom, it will be used as the constructor name. If name_or_opts is a keyword list, name_or_opts[:name] will be used as the constructor name. By default, :new is used.

Additional options in name_or_opts are stored in the @exconstructor_default_options module attribute.

The constructor is implemented in terms of populate_struct/3. It accepts a map or keyword list of keys and values map_or_kwlist, and an optional opts keyword list.

Keys of map_or_kwlist may be strings or atoms, in camelCase or under_score format.

opts may contain keys strings, atoms, camelcase and underscore. Set these keys false to prevent testing of that key format in map_or_kwlist. All default to true.

For the default name :new, the constructor's definition looks like:

@spec new(ExConstructor.map_or_kwlist, Keyword.t) :: %__MODULE__{}
def new(map_or_kwlist, opts \\ []) do
  ExConstructor.populate_struct(%__MODULE__{}, map_or_kwlist, Keyword.merge(@exconstructor_default_options, opts))
end
defoverridable [new: 1, new: 2]

Overriding new/2 is allowed; the generated function can be called by super. Example uses include implementing your own opts handling.

Link to this macro

define_constructor(name_or_opts \\ :new)

(macro)

Alias for __using__, for those who prefer an explicit invocation.

Link to this function

populate_struct(struct, map_or_kwlist)

@spec populate_struct(
  struct(),
  map_or_kwlist()
) :: struct()

Returns a copy of struct into which the values in map_or_kwlist have been applied.

Keys of map_or_kwlist may be strings or atoms, in camelCase or under_score format.

Link to this function

populate_struct(struct, map_or_kwlist, opts)

@spec populate_struct(
  struct(),
  map_or_kwlist(),
  %ExConstructor.Options{
    atoms: term(),
    camelcase: term(),
    strings: term(),
    underscore: term(),
    uppercamelcase: term()
  }
  | map_or_kwlist()
) :: struct()

Returns a copy of struct into which the values in map_or_kwlist have been applied.

Keys of map_or_kwlist may be strings or atoms, in camelCase, UpperCamelCase, or under_score format.

opts may contain keys strings, atoms, camelcase, uppercamelcase, and underscore. Set these keys false to prevent testing of that key format in map_or_kwlist. All default to true.