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:
The first parameter of a BossRecord should always be called Id
, and the
other parameters should be CamelCased attributes of your data model.
All parameters will be available as lower-case, underscored functions,
e.g. -module(foo, [Id, TheText])
will generate the getter functions
id()
and the_text()
.
Parameters can contain typespecs, e.g. -module(foo, [Id, SomeString::string(), ...]).
. Valid types are:
string()
binary()
integer()
float()
date()
datetime()
timestamp()
boolean()
Types, while optional, are validated before saving to the database.
BossRecords can be instantiated with either my_module:new/N
(like any other parameterized module), or with boss_record:new(my_module, Attributes)
, where Attributes
is a proplist.
To auto-generate an ID, pass the atom 'id'
as the first parameter to my_module:new/N
. Alternatively, just use boss_record:new/2
.
Call my_module:new/N
with strings, binaries, integers, floats, erlang:now()
tuples, DateTime tuples, or atoms for all other parameters
You can add your own functions to a BossRecord module, which will have access to the generated functions described below.
To see the full API for a BossRecord called foo
at any time during development, point your browser to /doc/foo on your dev server.
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:
These names can be accessed at run-time with the database_table/0
and database_columns/0
functions; see below.
Generated instance functions of a BossRecord include:
A list of the lower-case boss_record
parameters.
A proplist of the types of each boss_record
parameter, if specified.
A proplist of the database field names of each boss_record
parameter.
The name of the database table used to store boss_record
records (if any).
Validates the parameter types of boss_record
without saving to the database.
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
.
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 multiple record attributes at once. Does not save the record.
Set the value of a particular attribute. Does not save the record.
A proplist of the boss_record
parameters and their values.
Reset a counter to zero
Atomically increment a counter by 1.
Atomically increment a counter by the specified increment
Retrieve a list of the names of belongs_to
associations.
Retrieve a proplist of the belongs_to
associations and their types.
Retrieve all of the belongs_to
associations at once.
Returns the value of Id
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.
Special associations are generated from the following module attributes:
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>)
.
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:
Valid options are:
order_by
- attribute to sort on. Defaults to 'id'descending
- whether to values from high to low (a boolean).module
- If the assocation name is different than the underlying module, use this option to specify the underlying module.foreign_key
- If the associated module uses something unexpected for the foreign key, use this option to specify the foreign key (e.g. person_id
).include
- a list of belongs_to associations to pre-fetch (atoms). Requires the database cache to be enabled.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.
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.
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()
- executed just before a new BossRecord is saved to the database.before_update()
- executed just before an existing BossRecord is saved to the database.after_create()
- executed just after a new BossRecord is saved to the database.after_update()
- executed just after an existing BossRecord is saved to the database.before_delete()
- executed just before a BossRecord is removed from the database.before_create/0
and before_update/0
should return one of:
ok
- Continue with the save{ok, ModifiedRecord}
- Save ModifiedRecord
instead{error, Reason}
- Abort the savebefore_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.