Defining models for an application is the heart of a Caribou project. Once a model is created a host of capabilities are automatically generated for that newly created model. This section details the means for creating new models and expanding on existing models.
Creating a model is just like creating any other content in a Caribou project. The first step is to acquire a configuration map, which is detailed in the How Configuration Works in Caribou section.
Assuming a configuration exists and it is called config
, a model can be created from the repl with the following call:
(caribou.core/with-caribou config (caribou.model/create :model {:name "Presentation" :fields [{:name "Title" :type "string"} {:name "Preview" :type "asset"}]}))
Some things to note about this code:
caribou.core/with-caribou
with an existing configuration map. This configuration map among other things contains information about the database connection. Since this call is creating a new model, this will actually generate a new table for that model inside whatever database is referred to by the given configuration map under its :database
key. This means of configuration means that you can create models in different databases just by swapping out the configuration map. For clarity, from here on out we will assume the config map is provided.caribou.model/create
. Thiscall is used to create any content inside of a Caribou project, and corresponds to inserting a new row in the database given by the configuration map.:model
, and signifies that we arecreating a model, as opposed to any other content type currently known to the system. Once a model is created (in this case the Presentation model), content of that variety can be created using the same call, but swapping out the key here (which for the case of Presentations, would be :presentation
). If a call to caribou.model/create
is made with a key that does not represent a current model known to the system this will throw an exception.(caribou.model/create :presentation {:title "Caribou!" :preview {:source "path/to/preview/image.png"}}))
In this way, creating a model allows new kinds of content to be created. Everything else in Caribou flows from this basic idea.
There are a number of different field type models can have. Here is a summary:
Beyond the simple field types, much of the richness of a Caribou model structure lies in the associations that are created between models in the system. Model and Field have this relationship, where Model has a "collection" of Fields and Fields are a "part" of Model. This provides a one to many relationship between the Model model and the Field model.
Every association in Caribou is represented by a field in the corresponding models, which means that there is an association field in each model representing the two sides of the association. This means each association type has a reciprocal type, and that every association has one and only one reciprocal association field that lives in another model somewhere.
The different types of associations available in Caribou are:
There are a number of default fields that are added to a model automatically. These play various roles in managing the content internally, and also provide some handy features that all content is likely to need. These fields are:
:id
represents a unique integer identifier that is used throughout Caribou. Every content item in Caribou is given an :id
, and all content can be retrieved based on its model type and its :id
. This is also the mechanism under the scenes that tracks how different items are associated to one another. :id
always increments starting from 1
, so every item obtains a unique :id
within its model table.:position
field allows content to be ordered in an arbitrary fasion. Without the :position
field we would be stuck retrieving content only by name, or id or title or something. :position
allows people to order content exactly how it should appear. Without outside intervention, :position
increments automatically starting from 1
, just like :id
. :position
however can change, whereas once an :id
is acquired it is invariant for the lifetime of the application.true
, prevents the given content item from being modified by a caribou.model/update
call. This is handy to protect the built in model fields from arbitrary changes which could undermine the very functioning of Caribou itself. That is not to say built in models are unchangeable: new fields can be added to any model. But someone cannot remove the "Name" field from a model, for instance. Caribou needs this field to run. Probably you will not need to set this field yourself, but you could have a vital content item that plays a similar role in the application as a whole, in which case setting it to locked
will safeguard that content from changing out from under you.