Data first

All our models will inherit from a base model, which will be used to specify the following command:

// app/model/BaseModel.js
Ext.define('Instrumatics.model.BaseModel', {
    extend: 'Ext.data.Model',

    schema: {
        namespace: 'Instrumatics.model',
        urlPrefix: 'http://localhost:3000',
        proxy: {
            type: 'ajax',
            url: '{prefix}/{entityName:uncapitalize}'
        }
    },
});

Note

We've assumed that we have an API server running at localhost on port 3000 and supplied this information as the URL prefix.

We used the schema configuration in the last chapter, but now that we're about to use it with multiple models, it really comes into its own. In each of the models that inherit from BaseModel, the model's name will be inserting into the proxy URL in place of the entityName token. This avoids duplicating the URL configuration across multiple models. We can now create our LogEntry model as per our design:

// app/model/LogEntry.js
Ext.define('Instrumatics.model.LogEntry', {
    extend: 'Instrumatics.model.BaseModel',

    fields: [
        { name: 'value' },
        { name: 'subType' },
        { name: 'type' },
        { name: 'time', type: 'date' }
    ]    
});

Via the schema, this will result in the following URL:

http://localhost:3000/logEntry

Other than this, we're just implementing the fields, we specified in the design, on to the LogStream class:

// app/model/LogStream.js
Ext.define('Instrumatics.model.LogStream', {
    extend: 'Instrumatics.model.LogEntry',
});

This was simple. The LogStream class inherits all of the fields from the LogEntry class, but thanks to the use of the schema configuration in the BaseClass, LogStream will have a URL like this:

http://localhost:3000/logStream

Finally, here's the Statistics model:

// app/model/Statistic.js
Ext.define('Instrumatics.model.Statistic', {
    extend: 'Instrumatics.model.BaseModel',
    fields: [
        { name: 'category' },
        { name: 'label' },
        { name: 'percentage', type: 'number' }
    ]
});

Just the three fields from the design here and it gives us a model that produces this URL:

http://localhost:3000/statistic

Nothing in our data layer is particularly taxing, as we thought through the implementation during our design phase. By having an awareness of the features Ext JS provides before sitting down to write code, we were able to reduce code duplication by having the proxy configuration in a base class.

We should always look for places, either via refactoring or through the initial design, where we can reduce duplicated code. In this example, we could have had the same functionality by setting the proxy configuration on each of LogEntry, LogStream, and Statistic, but in the event where we want to change some part of the config, such as the hostname of the API, we'd have to change it in multiple locations. By centralizing in the way that we have, we will have less code to maintain and it's easier to work with.

One thing to note in the model classes earlier is the way we define the fields. There are two options in Ext JS, one option is to pass a field definition as an object literal as we have in our code, and the second option is to pass a string containing the field name. To use the Statistic class as an example, the field config will look like this:

'category',
'label',
{ name: 'percentage', type: 'number' }

Why choose one over the other? The answer is for consistency. This is a perfect example of something that could go in the programming style guide for your team, so rather than having one class declared using one method and a second class using another method, we have a unified approach. No alarms and no surprises for a new developer who opens up your model files and finds the field definitions well organized.

There is a third approach for field definitions; not bothering with them. Ext JS allows you to leave out the field definitions and will create them on the fly based on the data the model is consuming.

We're all for reducing the amount of code to maintain, but sometimes, it's better to be explicit. If we needed to use one of the other configuration options in a field, such as convert, then we'd have to manually define that field anyway, and so on, and then be left with some fields explicit in the model and some created on the fly.

This is a matter of preference, but for our purposes, we'll always define the full field definitions. It's consistent and self-documenting; we're always aware of the fields it's consuming when looking at a model file.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset