Code, code, and more code

It's time to get our hands dirty and put fingers to keyboards. As always, we generated a new base application using Sencha Cmd and will use the resulting "main" view as a starting point for our user interface. First though, let's flesh out the data layer that we designed earlier:

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

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

We've used a base model in previous chapters because it gives us a good way of centralizing proxy configuration. The models that inherit from it are all straightforward, as shown in the following code:

// app/model/CartItem.js
Ext.define('Alcohology.model.CartItem', {
    extend: 'Alcohology.model.BaseModel',
    fields: [
        { name: 'productId' },
        { name: 'productName' },
        { name: 'price' },
        { name: 'quantity' }
    ]
});

// app/model/Category.js
Ext.define('Alcohology.model.Category', {
    extend: 'Alcohology.model.BaseModel',
    fields: [
        { name: 'id', type: 'integer'}
    ]
});

// app/model/Order.js
Ext.define('Alcohology.model.Order', {
    extend: 'Alcohology.model.BaseModel',
    fields: [
        { name: 'date', type: 'date' },
        { name: 'items', type: 'auto' }
    ]
});

// app/model/Product.js
Ext.define('Alcohology.model.Product', {
    extend: 'Alcohology.model.BaseModel',
 fields: [
        { name: 'id', type: 'integer'},
        { name: 'name', type: 'string' },
        { name: 'imagePath', type: 'string' }
    ]
});

Looking back at our design, these models exactly follow the specification we laid out. All we've really done is add the Ext JS implementation on top of the original field definitions.

What's in store?

As we know, stores are often just wrappers to give us a few more helpful methods to work with a collection of models. Looking back at our design documents, this is the case for three of the stores in this application:

// app/store/Categories.js
Ext.define('Alcohology.store.Categories', {
    extend: 'Ext.data.Store',
    model: 'Alcohology.model.Category',
    alias: 'store.categories'
});

// app/store/PastOrders.js
Ext.define('Alcohology.store.PastOrders', {
    extend: 'Ext.data.Store',
    model: 'Alcohology.model.Order',
    alias: 'store.pastorders'
});

// app/store/Products.js
Ext.define('Alcohology.store.Products', {
    extend: 'Ext.data.Store',
    model: 'Alcohology.model.Product',
    alias: 'store.products'
});

All very straightforward. The cart store is a bit more interesting, as shown in the following code:

// app/store/Cart.js
Ext.define('Alcohology.store.Cart', {
    extend: 'Ext.data.Store',
    model: 'Alcohology.model.CartItem',
    alias: 'store.cart',

    addProduct: function(product) {
        // find a product with a matching ID
        var item = this.findRecord('productId', product.getId());

        if(item) {
            item.set('quantity', item.get('quantity') + 1);
            item.commit();
        } else {
            item = this.add({
                productName: product.get('name'),
                price: product.get('price'),
                productId: product.getId(),
                quantity: 1
            });
        }

        return item;
    },

    toOrder: function() {
        var items = [], total = 0;

        this.each(function(item) {
            items.push({
                name: item.get('productName'),
                quantity: item.get('quantity')
            });

            total += item.get('price') * item.get('quantity'),
        });

        return Ext.create('Alcohology.model.Order', {
            date: new Date(), items: items, total: total
        });
    }
});

Many of the stores we've built in past chapters have been used to store information that has been fetched from the server. Here, we're using the store as an in-memory representation of the shopping cart itself; we're adding a couple of custom methods to help with this function.

The addProduct method will add the specified product to the store by converting it to a CartItem model. If a product with the same ID already exists as an item in the cart, it will have its quantity increased by one rather than being duplicated.

The toOrder method converts the whole cart to an Order model, which is used later in the application to show past orders in the user's account.

These methods are interesting because they demonstrate a place where we're not writing glue code or code that handles events. It's the code that deals with the really interesting parts of an application, sometimes called "business logic". One of the benefits of developing a strong architecture with strong development practices is that you will have less boilerplate code and more time to work on the business logic that's important to your client.

In Chapter 11, Application Testing, we'll look at ways to isolate this business logic and create automated tests that give you confidence in your code base.

That's our data layer in place, so we can move on to building the user interface.

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

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