1
votes

I'm struggling with getting my head around modeling a shopping cart that needs to persist to the back-end. I think I understand the relationships, and how to retrieve data that's in the model...it's how to actually add the data that's tripping me up.

I've got two pretty simple models:

The cart:

export default DS.Model.extend({
    cartitems: hasMany('cartitem')
});

The cart items

export default DS.Model.extend({
    product: belongsTo('product', { async: true }),
    cart: belongsTo('cart'),

    variantCodes: attr(''),
    quantity: attr('number'),
    itemPrice: attr('number'),
    itemOrigPrice: attr('number')

});

I created a cart service that contains properties, computed properties and methods. In this cart service is where I'm having the trouble, starting with my add method:

...

add(item) {
    this.get('store').findRecord('cart', get(this, 'cartId')).then(result => {
        cart.get('cartitems').addObject(this.get('store').createRecord('cartitem', {
                id: item.skuid,
                variantCodes: item.variantCodes,
                quantity: item.quantity,
                itemPrice: item.itemPrice
            })
        );
        cart.save();
    });
}

That kind of works...it shows the cart and cartitem models (with data and relationsips) in the ember inspector, but doesn't send a payload for the cart items to the API. I'm thinking it's because I have to do a save for each cartitem.

But this rig also seems overly complex and I think would result in a bunch of network requests. Is this even the right approach?

I think the DS.EmbeddedRecordsMixin would help here, but I have no idea how that would look. I can't seem to find any examples of it in use for POSTing to the API. Only for retrieving. Any help appreciated!

1
This is an excellent question actually. Did you ever get to the bottom of this? - WooDzu
Posted an answer - tarponjargon

1 Answers

0
votes

I've stumbled on something that seems to work. This uses the ember-concurrency task syntax but that is not a requirement.

addItem: task(function * (product, quantity) {

    let cart = this.get('store').findRecord('cart').get('firstObject'); // or whatever is aliased to the cart record

    // check if the item is already in cart
    let cartItem = yield this.get('store').peekAll('cart-item').findBy('skuid', skuid);
    if (cartItem) {
        cartItem.setProperties({
            skuid: product.get('skuid'),
            cart: cart,
            product: product,
            quantity: cartItem.get('quantity') + quantity
        });
    } else {
        cartItem = yield this.get('store').createRecord('cart-item', {
            skuid: product.get('skuid'),
            cart: cart,
            product: product,
            quantity: quantity
        });
    }

    // persist to back end
    let savedItem = null
    try {
        savedItem = yield cartItem.save();
    } catch(e) {
        console.log("failed out of cartitem save", e);
    }

    // if adding an item can affect the cart (dynamic pricing, promo thresholds)
    // you can do a save of the entire cart here to get it updated
    yield cart.save();

    return savedItem;

});