The Chicago Boss API is mostly stable, but still might change before 1.0.

Jump to: Specifying table and column names   Generated instance methods   Associations (belongs_to, has)   Save hooks

BossRecords are specially compiled parameterized modules that follow the "active record" pattern. BossRecords go into your project's src/model/ folder and will have functions generated for saving them into the database and for accessing related BossRecords. Important aspects of BossRecords:

Specifying table and column names

If you're connecting to an existing SQL database, you may want to override the default table and column names. (By default, the table name is the plural form of the model name, and the column names are the lowercase, underscored versions of the attribute variables.)

To specify your own database layout, you can use the -table and -columns module attributes:

-table("my_table_name").
-columns([{attribute1, "my_column_name"}]).

These names can be accessed at run-time with the database_table/0 and database_columns/0 functions; see below.

Generated functions

Generated instance functions of a BossRecord include:

attribute_names() -> [::atom()]

A list of the lower-case boss_record parameters.

attribute_types() -> [{::atom(), ::atom()}]

A proplist of the types of each boss_record parameter, if specified.

database_columns() -> [{::atom(), ::string()}]

A proplist of the database field names of each boss_record parameter.

database_table() -> ::string()

The name of the database table used to store boss_record records (if any).

validate_types() -> ok | {error, [ErrorMessages]}

Validates the parameter types of boss_record without saving to the database.

validate() -> ok | {error, [ErrorMessages]}

Validates this boss_record without saving to the database. Errors are generated from this model's validation_tests/0 function (if defined), which should return a list of {TestFunction, ErrorMessage} tuples. For each test, TestFunction should be a fun of arity 0 that returns true if the record is valid or false if it is invalid. ErrorMessage should be a (constant) string that will be included in ErrorMessages if the associated TestFunction returns false on this particular boss_record.

save() -> {ok, SavedBossRecord} | {error, [ErrorMessages]}

Saves this boss_record record to the database. The returned record will have an auto-generated ID if the record's ID was set to 'id'. Performs validation first, returning ErrorMessages if validation fails. See validate/0.

set(AttributeProplist[{Attribute::atom(), Value}]) -> BossRecord

Set multiple record attributes at once. Does not save the record.

set(Attribute::atom(), NewValue::any()) -> BossRecord

Set the value of a particular attribute. Does not save the record.

attributes() -> [{Attribute::atom(), Value::string() | undefined}]

A proplist of the boss_record parameters and their values.

reset(Counter::atom()) -> ok | {error, Reason}

Reset a counter to zero

incr(Counter::atom()) -> ::integer()

Atomically increment a counter by 1.

incr(Counter::atom(), Increment::integer()) -> ::integer()

Atomically increment a counter by the specified increment

belongs_to_names() -> [::atom()]

Retrieve a list of the names of belongs_to associations.

belongs_to_types() -> [{::atom(), ::atom()}]

Retrieve a proplist of the belongs_to associations and their types.

belongs_to() -> [{::atom(), BossRecord}]

Retrieve all of the belongs_to associations at once.

id() -> Id

Returns the value of Id

get(Path::string()) -> Value

Returns a deeply nested value described by a dot-separated Path (e.g. "puppy.mother.name")

Other getters and setters are generated based on the parameters of your BossRecord.

Associations

Special associations are generated from the following module attributes:

-belongs_to(foo).

Requires a matching FooId in the parameter list. Adds a function foo() which returns the BossRecord (of any type, usually foo) with ID equal to the current BossRecord's FooId. If the model name differs from the field name, use -belongs_to_<model name>(<field name>).

-has({bar, 1}).
-has({bars, Count}). % Count > 1
-has({bars, many}).

Generates a function bar() or bars() which returns up to Count "bar" BossRecords with FooId equal to this BossRecord's ID. If Count is greater than 1, also creates first_bar() and last_bar() which return the first and last items in the association.

When Count is not equal to 1, has can also take a proplist of options as the third element in the tuple:

-has({bars, many, [{order_by, first_name}]}).

Valid options are:

Note that Time and float attributes are stored internally as integers, so sort them with num_ascending or num_descending.

The two above attributes work similar to belongs_to and has_many/has_one in Rails.

-counter(foo_counter).

Generates a function foo_counter() which returns the value of the counter, initialized to zero. Each BossRecord may have an unlimited number of counters. Manipulate the counters with reset and incr above.

SPECIAL NOTE: Everything in the Model directory will be compiled as a BossRecord rather than as a regular Erlang module; you don't need to do or declare anything special.

Save/delete hooks

You can specify logic to be run anytime a BossRecord is saved, or before it is deleted. Just define one or more of these functions in your module:

before_create/0 and before_update/0 should return one of:

before_delete/0 should return ok to continue with the deletion, or {error, Reason} to abort the deletion.

Return values for the other hook functions are ignored.