5. The Data Model

The Data Model defines the structure of the database that will be used by your app, and should be determined by the nature and structure of the data that is to be accessed and used in the app. JourneyApps supports fully relational data models:

  • You define the Models that are required in the app

  • For each model you define various Fields, each with a specific type (for example a name field of type text to store the Name of the object, or a created_at field of type datetime to store the exact date and time the object was created)

  • You also define the Relationships between Models, which are used to link related models (for example a one-to-many relationship between cart and item, i.e. a cart can have many items linked to it)

  • You can also define special fields for default display values, app indexes, and for configuring webhooks

These then describe the structure and nature of data that can be stored in each model. An instance of a model is called an object, and each object has a unique, system generated, identifier called the id of the object.

Learn more about relational databases

Understanding the basics of relational databases will simplify the design of your app's data model significantly. If you are not familiar with relational databases, we suggest that you read more about them using online resources.

Single, Common Data Model

A valuable feature of JourneyApps is that the Data Model for an app only needs to be defined once, in OXIDE, and is then used throughout the entire JourneyApps Cloud. Once you've defined your Data Model it will be used by the application, the Backend, the API and all other related JourneyApps services.

Syntax

This is an example of a Data Model for a simple asset management app. It contains two models, asset and building. Most of the data collected are for the assets, and a building can have many assets - a one-to-many relationship.

For details, see Data Model Configuration.

schema.xml
<data-model>
  <model name="asset" label="Asset">
    <field name="make" label="Make" type="text:name"/>
    <field name="model" label="Model" type="text:name"/>
    <field name="serial_number" label="Serial Number" type="text:number"/>
    <field name="description" label="Description" type="text"/>
    <field name="picture" label="Picture" type="photo"/>
    <field name="condition" label="Condition" type="single-choice">
      <option key="good">Good</option>
      <option key="ok">Ok</option>
      <option key="bad">Bad</option>
    </field>

    <belongs-to model="building"/>

    <display>{make} {model} {serial_number}</display>
  </model>

  <model name="building" label="Building">
    <field name="name" label="Name" type="text:name"/>

    <has-many model="asset" name="assets"/>

    <display>{name}</display>
  </model>
</data-model>

A Real-World Example

We mentioned that we'll use a real-world example of an app throughout the tutorial, and you saw in the JourneyApps Approach to Building Apps section on the What is JourneyApps? page that the Data Model is the best place to start when you build an app on JourneyApps. So let's introduce our real-world example app and then build the Data Model for it:

Real-World Example: Construction Punch List

In the construction and real estate industries, a "punch list" is often created to keep inventory of the things that an owner or tenant isn't happy with when a building project is finished or when they move into a new leased building.

Things that could appear on a punch list include: Cracks in ceiling and walls, skirting boards that aren't properly affixed, uneven or unfinished drywall, crooked fixtures, loose wiring, poor insulation, leaking pipes, etc.

A great alternative to compiling and maintaining a punch list manually is to build a mobile app on JourneyApps that allows capturing and centralized tracking of punch list items electronically. Photos, notes and GPS locations can easily be attached to each item, and it is easy to export the punch list and send it to someone, or to build a web portal that pulls data from to the JourneyApps API where stakeholders can browse the punch list.

We will now create a new blank app to start building the punch List app.

Important: Start Again with a New App.

Navigate to the OXIDE Dashboard (top left corner) and repeat the instructions in Section 2: Creating a New App to create a new app named "Punch List", and then link your mobile device to that app using the Test App action.

Open up the Data Model Workspace

After creating the new Punch List app, go to the Data Model Workspace. You should see the following:

What you are seeing is your data model xml code, also called the schema, in the right editor pane, the ERD for your current data model rendered in the left editor pane, and the Data Model panel on the left of the screen. Notice that any new JourneyApps application that you create starts with two models in the Data Model, user and push_notification. The user model is used to store information about the end users of your app and is required for most apps. By default, the user model has one field, name, of type text which stores the user's name. The default push_notification model is used and pre-configured to allow you to easily create and send Push Notifications to your app users, but more about that at a later stage.

Your schema.xml file should contain the following:

schema.xml
<?xml version="1.0" encoding="UTF-8"?>
<data-model>
    <!-- Do not remove this - it is used to store information about your app's users: -->
    <model name="user" label="User">
        <field name="name" label="Name" type="text:name"/>

        <display>{name}</display>
    </model>

    <!-- Used for Push Notifications - to send a push notification, create a 'push_notification' object -->
    <!--                               and specify the recipient in the 'belongs to user' relationship -->
    <!-- For more details, refer to: http://resources.journeyapps.com/v4/push-notifications -->
    <model name="push_notification" label="Push Notification">
        <field name="message" label="Message" type="text" />
        <field name="received_at" label="Received At" type="datetime" />
        <field name="created_at" label="Created At" type="datetime" />

        <belongs-to model="user" />
        <display>{message} ({user})</display>
        <notify-user message="{message}" received-field="received_at" recipient-field="user"/>
    </model>

    <!-- ADD MODELS HERE: -->

</data-model>

Whenever you modify your Data Model XML code (the schema.xml file), the ERD will be updated automatically.

Building the Data Model

Let's look at what the requirements are for our Punch List app's Data Model

App Design: Construction Punch List. The simplest Data Model for our Punch List App is to have a collection of punch list items, each with a photo, comments and status (Open/Closed). Our app will then allow users to capture new punch list items that are initially "Open", which they can then later change to "Closed" when the punch has been taken care of.

Add a Model

Therefore, we need to add a new model to our Data Model named item. Below "ADD MODELS HERE" in the XML, type model and you should see an auto-complete suggestion underneath your cursor. Insert the auto-complete suggestion by pressing return/enter (If there is only one auto-complete suggestion it will be selected by default and so there is no need to select it first). If you do not see the auto-complete suggestion, or you have clicked-away from it, simply get your cursor back to the end of the word you were typing and press Ctrl + spacebar.

For our newly added model, enter item as the name of the model, and Item as the label (the name="" attribute is what is used to refer to the model in your code, whereas the label="" attribute is a human-readable label for the model that is used in other parts of the platform).

<model name="item" label="Item">
    <field name="" label="" type="" />

    <display></display>
</model>

Add Some Fields to the Object Type

Now populate your first data model field, comments, and specify its type as text.

<model name="item" label="Item">
    <field name="comments" label="Comments" type="text" />
  
    <display></display>
</model> 

Next we want to add an attribute to store the photo of the punch list item. Type photo on the next line and once you see the auto-complete suggestion for a photo field hit return/enter to insert. This will give you a field for a photo and now you just need to add the name and the label. Fill in photo as the name and Photo as the label.

<model name="item" label="Item">
    <field name="comments" label="Comments" type="text" />
    <field name="photo" label="Photo" type="photo" />

    <display></display>
</model>

To add our last field for the "status" of our punch list item, we'll use the single-choice type — which is used to create a fixed "list" of values that a specific field can contain). (A full guide to all the possible field types in JourneyApps can be found here.) Type single-choice on the next line and insert the auto-complete suggestion for the single-choice field, not the single-choice-integer field, and fill in status for the name and Status for the label. To populate and specify the list of options that this field can contain you need to list <option> tags inside the single-choice field. Therefore, set the contents of those tags to Open and Closed.

Pro Tip: Jump between _XML_** input fields**

You can use Ctrl + . and Ctrl + , to move your cursor to the next and previous input fields in any xml code in JourneyApps. Try it now in your Data Model (schema.xml)

<model name="item" label="Item">
    <field name="comments" label="Comments" type="text" />
    <field name="photo" label="Photo" type="photo" />
    <field name="status" label="Status" type="single-choice">
        <option key="Open">Open</option>
        <option key="Closed">Closed</option>
    </field>
    <display></display>
</model>

Display Format

The last thing we need to customize is how our item objects will be displayed by default (e.g. when they are shown in a list). This is specified using the <display></display> tag that you can see below your fields. Inside the display tags we can make use of String interpolation. In xml string interpolation of variables/placeholders is accomplished using curly brackets. So, here you can specify which field values should be included when the object is displayed. Field names are wrapped in curly brackets, and you can also include some raw text. Let's make our punch List items display their Status, followed by a hyphen and then their Comments:

<display>{status} - {comments}</display>

You can learn more about xml format strings / string interpolation in detail in this section of the reference documentation.

That's It!

We've now created the first version of the Data Model for our Punch List app. This will now automatically be used to determine the structure of the "database" in your app and elsewhere throughout the JourneyApps ecosystem (e.g. for storing your app's data in the cloud, exposing that data through the backend API, etc.).

At this time your Data Model (schema.xml) should like like this.

schema.xml
<?xml version="1.0" encoding="UTF-8"?>
<data-model>
    <!-- Do not remove this - it is used to store information about your app's users: -->
    <model name="user" label="User">
        <field name="name" label="Name" type="text:name"/>

        <display>{name}</display>
    </model>

    <!-- Used for Push Notifications - to send a push notification, create a 'push_notification' object -->
    <!--                               and specify the recipient in the 'belongs to user' relationship -->
    <!-- For more details, refer to: http://resources.journeyapps.com/v4/push-notifications -->
    <model name="push_notification" label="Push Notification">
        <field name="message" label="Message" type="text" />
        <field name="received_at" label="Received At" type="datetime" />
        <field name="created_at" label="Created At" type="datetime" />

        <belongs-to model="user" />
        <display>{message} ({user})</display>
        <notify-user message="{message}" received-field="received_at" recipient-field="user"/>
    </model>

    <!-- ADD MODELS HERE: -->
    <model name="item" label="Item">
        <field name="comments" label="Comments" type="text" />
        <field name="photo" label="Photo" type="photo" />
        <field name="status" label="Status" type="single-choice">
            <option key="Open">Open</option>
            <option key="Closed">Closed</option>
        </field>
        
        <display>{status} - {comments}</display>
    </model>    

</data-model>

Last updated