exconstructor v1.1.0 ExConstructor

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.1.0"}]
    end
  2. Ensure ExConstructor is started before your application:

    def application do
      [applications: [:exconstructor]]
    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-2017 Appcues, Inc.

ExConstructor is released under the MIT License.

Summary

Functions

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

Macros

use ExConstructor defines a constructor for the current module’s struct

Alias for __using__, for those who prefer an explicit invocation

Types

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

Functions

populate_struct(struct, map_or_kwlist)

Specs

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.

populate_struct(struct, map_or_kwlist, opts)

Specs

populate_struct(struct, map_or_kwlist, map_or_kwlist) :: struct
populate_struct(struct, map_or_kwlist, %ExConstructor.Options{atoms: term, camelcase: term, strings: term, underscore: term, uppercamelcase: term}) :: 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.

Macros

__using__(name_or_opts \\ :new)

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, uppercamelcase, 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.

define_constructor(name_or_opts \\ :new)

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