Addressing Data in Bundleable Models
What are Bundle-able Models?
The BaseModel and Attributes
Each table in the CollectiveAccess database schema has a corresponding model class in app/models. All models inherit from the BaseModel class, which provides a variety of basic functionality, including field-level data validation, generation of insert, update and delete SQL, support for "special" field types including historic and inexact date ranges and processed media and automated generation for field editing HTML.
Some models inherit from BaseModelWithAttributes, a sub-class of BaseModel that provides "attribute" functionality for its sub-classes. Attributes are user defined data fields based upon definitions in the ca_metadata_elements table. Beyond being user defined, and therefore allowing for flexible run-time modify-able cataloguing schema, the metadata element/attribute system provides several benefits over standard SQL table-level fields:
- Attributes may repeat
- Attributes may be comprised of multiple values arranged in a value hierarchy
- Attributes values may be parsed, validated, stored and indexed using plugins. This allows CA to support many specialized fields types, and makes it easy for developers to add new field types without modification to the core of the application. For example, supporting the entry and display of geographic coordinates requires only the development of a short "Geocode" plugin, which knows how to parse incoming latitude/longitude data, and how to return it as a map or as text.
Of course, the fact that they are user-defined is the biggest advantage. Attributes allow CA to be configured to support most any cataloguing standard. With a few exceptions, most data stored in a CA system is stored in attributes.
In summary any model that inherits from BaseModelWithAttributes is effectively endowed with the ability to have any number of repeating, complex user-defined data fields.
Attributes provide workhorse storage for all sorts of data. There are a few categories of information that play special roles in CollectiveAccess and therefore require somewhat different handling. One such category is labels - name or titles for key cataloguing items such as collections objects, entities (eg. people or organizations), geographic places, collections, storage locations, etc. Labels aren't just bits of text attached to a record - they are key to identification of individual catalogued items and are required by the CA user interface in various places.
Models that inherit from BundleableLabelableBaseModelWithAttributes are endowed with the ability to take on labels as well as attributes. When displaying a catalogued item you'll typically identify it by using its the label methods provided by BundleableLabelableBaseModelWithAttributes to fetch the appropriate label. BundleableLabelableBaseModelWithAttributes also provided methods to add, edit and delete labels as well as define 'non-preferred' alternate labels.
Between labels, which identify catalogued items, and attributes which describe them, it would seem like everything is covered. There are a few basic bits of information, however, that due to their ubiquity in data models and specific functionality in CA are "baked" into the CA database schema. Called "intrinsic fields," these data elements are implemented as standard database fields. They never repeat and do not take attribute value types. Rather than are restricted to the basic field types supported by BaseModel. There are relatively few intrinsic fields. One field common to all key data items is the identifier field (idno for objects, entities, places, occurrences and collections; idno_stub for object lots), which interacts with the CA multipart ID numbering system. Others include the "lifespan" field in entities and places and the extent and extent_units fields in object records.
Another key (and common) intrinsic field is type_id, which indicates the specific type for each item record. The types of attributes that may be attached to a given item record are determined by the type_id.
Whether you're writing CA back-end code, customizing a CA front-end or writing a script to dump or manipulate CA-hosted metadata odds are you're going to need to access all of the types of data described in previous sections. Each type is stored in its own way. Attributes are stored in related records in the ca_attributes and ca_attribute_values tables; labels in their own related tables; intrinsic fields in the core item table and relationships in both related item records and "linking" records.
You could access these various storage structures directly using crafted SQL queries, but that would be messy, verbose and prone to failure whenever the underlying data model changes. To make things a bit easier, CA provides interfaces for standardized and convenient retrieval of all types of stored data. These interfaces minimize the need to write custom data access code and abstract the underlying storage implementation so your code can focus on processing and manipulating data rather than figuring out where it is.
Data access contexts
There are two contexts in CA where your code will need to access stored item data. The interfaces for each are very similar with a few differences to be aware of:
Search results representing many items
From a model representing a single item