An application manages data of some kind. It could be anything from cars to banking accounts, orders, customers, contacts or anything in between. When building an application is usually a good idea to first spend time thinking about what data the application will manage and how that data is related.
When building an application we need to describe to the platform what our data looks like. A kind of data, like a car has a set of properties – a car will have a make, a model and year model and potentially several more properties – each of these properties in turn have a kind – integer, date, string etc. An application can manage many different kinds of data, we call a kind of data a model. The properties of a model we call attributes.
Here’s an example of a model describing a car, with its attributes listed:
You can think of the model as a recipe for describing the data we want to manage. We call an actual piece of data a record. A record is of a certain kind, i.e. belonging to a model. Here is an example of a record of our car model:
If you’re still struggling to grasp this consider the analogy of an excel-sheet – you can think of your sheet as a model where each column is an attribute and each row is a record and each cell would be an attribute value for a specific record. The columns have names and types, just like an attribute and the rows have values – just like a record:
The attribute is the smallest piece of data that we manage, an attribute is a property of something bigger – a model, as we discussed in the previous section. So what kind of attributes are there ? The Appivo platform supports the following types:
|String||A piece of text, can hold up to 8000 characters.|
|Integer||An integer value. It can hold signed values from -2147483648 to 2147483647 or unsigned values from 0 to 4294967295.|
|Float||A floating point value. This is a normalize size, double precision floating point number that can hold approximately up to 15 decimal digits.|
|Boolean||A boolean value, true or false.|
|Date & Time||A date and a time|
|Point||Coordinates in a geographic coordinate system, longitude and latitude.|
|State||A value that can only be one of a number of user defined values.|
A model can have a large number of attributes, there is a limit but it depends on the type of columns being used. The most important limitation is that of record-size as a single record cannot occupy more than 64Kb of data, typically most space is consumed by strings.
Aside the attributes that you add to your model the system enforces a set of system attributes, they are:
|id||ID||The primary key – serves as globally unique identifier for a record|
|created_at||Date & Time||Date & Time for when the record was created|
|updated_at||Date & Time||Date & Time for when the record was last updated|
|ver||ver||The records version-number, increments by one every time the record is updated|
In addition the system will add so called foreign key attributes as needed. A foreign key attribute is an attribute needed to keep the identity of a related record, more on this in the section below.
Now that you’ve hopefully understood the concepts of models, attributes and records it is time to introduce yet another concept – relations. We will continue with our car model as an example. Our car model has an attribute called “Make” which represents the manufacturer of the car, what if we wanted to manage more details regarding the manufacturers ? We could of course add more attributes for providing manufacturer details to our car model, like this:
This would work but it has a few issues. Lets add the new attributes for our car record, it would look like this:
Now consider a case where we have hundreds or thousands of car records in our application, each record would state that ManufacturerCountry-attribute is USA if the Manufacturer-attribute is Ford. Seems redundant, doesn’t it ? As a general rule of thumb one should avoid such constructs when defining data models. Imagine that Ford would move all its manufacturing to say Canada, all those car records with Ford as manufacturer would now need to be updated – inconvenient. So how should one go about modeling such a thing ? Let us break up our car model in two models – Car and Manufacturer (imagine you have two excel-sheets – one for manufacturers and one for cars):
We have now split out the manufacturer attributes and placed them in its own model “Manufacturer” and we have introduced a connection between the two models – a relation. A relation has a few properties, or constraints if you will. A relation describes how one model relates to another, let’s look at a few examples to make it clear:
- A car is made by one manufacturer but a manufacturer may make many cars
- A country can have many car manufacturers and a car manufacturer can have factories in many countries.
Each end of the relationship has a cardinality. The cardinality dictates how many records can be at either end of the relationship, as the examples above describe this depends on the nature of our data. The Appivo platform has the following cardinalities:
|Zero or one||There can be one record or no record|
|One||There must be exactly one record|
|Zero to many||There can be any number of records, including no records at all|
|One to many||There can be any number of records but at least one|
If you think of a relationship as a connection between two models we need to name the ends of that connection. Here’s an example to illustrate the point:
Let’s say we have two models Car and Person. We want to model that a Car is always owned by a Person and that a Person may own many cars. Since it is ownership that we are modeling here we will could name the ends of the relation like this:
From the Persons point of view – he/she has a set of OwnedCars and from the Cars perspective it is Owned. The names of the relation ends have several uses, for instance when building queries.
Finally, there’s a concept of ownership in a relation, this is not to be mixed up with the fact that we had car ownership as an example above. The right way to think of ownership in terms of a relation is instead whether a record of a model can exist on its own, without being related to the other model.
In our example above a Car doesn’t necessarily have to be owned by a Person and a Person doesn’t have to own a Car – though it should be said that this is a decision that you as the application developer will have to make as it depends on what rules you want to enforce in your application.
Lets take another example to see where ownership is needed. Consider a case where we are modeling invoices, a trivial model of an invoice could look like this:
We have two models – the Invoice model which keeps the data you would typically find in the top part of an invoice – invoice-number, customer and probably an adress etc. The other model represents the individual rows of the invoice – each row mentions an article, a quantity of that article and the unit price of the article. This is a common way to model invoices. The purpose of this example was to illustrate the concept of ownership however. Remember that earlier we said ownership is a way to declare whether records of a model can exist on their own or not. So lets ask ourselves a couple of questions:
- Can an Invoice exist without having any InvoiceRows ? Most likely an invoice will always have rows but it seems OK for it to exist without any.
- Can an InvoiceRow without being related to an Invoice ? No, this makes no sense at all – the invoice row by itself is fairly meaningless.
So having the answers to these questions we can conclude that there appears to be an ownership aspect in this model – Invoice owns InvoiceRows as they cannot exist by themselves. There is a functional aspect of this ownership – when you delete an Invoice the system will automatically delete the related InvoiceRows since they are not allowed to exist by themselves without violating the rule that we created.
If your application needs to store documents – binaries such as images, videos, word-documents etc then you can make use of document models. A document model is a model that aside from being able to store attributes just like ordinary models also stores a binary.
Document models have some additional system-attributes:
|filename||String||The name of the file|
|filesize||Integer||The size of the file in bytes|
|contenttype||String||The mime-type of the file|
|height||Integer||For images this attribute holds the height of the image in pixels, for all other document-types it will be null|
|width||Integer||For images this attribute holds the width of the image in pixels, for all other document-types it will be null|