MockeryExtras.Getters (Mockery Extras v0.3.1) View Source

Utilities for defining functions that get map/struct/keyword values up to three levels of nesting.

Even though complex nested structures aren't necessarily the best thing for your code, they sometimes exist:

all = %{
  top1: 1,
  top2: 1.2,
  down: %{
    lower: 2,
    down: %{
      lowest: 3
    }
  }
}

You're stuck with them, at least for now. You'd often prefer not to spread knowledge of the exact structure through the code, because that would make a lot of code fragile in the face of change.

So you can hide the structure behind "getters" that (alone) know how to reach into the structure and retrieve a value. They present a "flattened" API to client code.

Those functions are simple to write manually, but you might as well use a macro to do it for you:

getters([:top1, :top2])
# defines top1/1, top2/1, so that:
# top1(all) => 1
# top2(all) => 2

# Three levels of nesting are allowed.
getters(:down, :down, [:lowest])
# lowest(all) => 3

See getters/1 for details, such as how to specify default values (akin to those of Map.get/3 or Keyword.get/3).

See Stubbing Complex Structures to see how a little bit of custom (copy and tweak) work can improve the testing of code that works against a flattened API, plus an alternative to verbose code like MyStructure.getter(structure).

Link to this section Summary

Functions

Define a single getter with a different name than the field it accesses.

Define N getters, possibly with defaults.

Define N getters for the second level of a nested structure.

Define N getters for the third level of a nested structure.

The same as getters/1 except the functions are generated using defp.

The same as getters/2 except the functions are generated using defp.

The same as getters/3 except the functions are generated using defp.

Link to this section Functions

Link to this macro

getter(name, opts)

View Source (macro)

Define a single getter with a different name than the field it accesses.

For example, this:

getter :meio, for: [:root, :middle]
# meio(root: %{middle: 3}) => 3

A default can also be provided:

getter :meio, for: [:root, :middle], default: "default"
# meio(root: %{}) => "default"

If the getter is for the top level, the for: value needn't be a list:

getter :raiz, for: :root
Link to this macro

getters(names)

View Source (macro)

Define N getters, possibly with defaults.

The argument must be a list. For each atom in the list, a function effectively like the following is defined:

def atom(structure), do: structure[atom]

Note that the getter's argument can be either a Map or a Keyword.

Default values can be given:

getters([:x, y: "some default"])
# y(%{}) => "some default"

If there's no default, a missing value will produce a KeyError.

Link to this macro

getters(top_level, names)

View Source (macro)

Define N getters for the second level of a nested structure.

The first argument is an atom that's expected to index a Map or Keyword. The value of that index is again expected to be a Map or Keyword.

The second argument is a list with the same form as in getters/1. It provides the names for the generated functions. (The first argument plays no role.)

getters(:top, [:x, y: "some default"])
# x(%{top: [x: 1]}) => 1
# y(%{top: [    ]}) => "some default"

Note that the default only applies at the bottom level. The following will raise a RuntimeError:

Link to this macro

getters(top_level, next_level, names)

View Source (macro)

Define N getters for the third level of a nested structure.

Link to this macro

private_getters(names)

View Source (macro)

The same as getters/1 except the functions are generated using defp.

Most often this is used in a module that defines a structure, its getters, and also more complicated functions that work on the structure.

Link to this macro

private_getters(top_level, names)

View Source (macro)

The same as getters/2 except the functions are generated using defp.

Link to this macro

private_getters(top_level, next_level, names)

View Source (macro)

The same as getters/3 except the functions are generated using defp.