Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ember Data does not allow duplicate entries in hasMany relationships

I have the following model:

#order/model.coffee
Order = DS.Model.extend {
  line_items: DS.hasMany 'product', {async: true}
}

At some point I want to add the some products to the order. I found that I can only add the product once, adding the same product again does not work:

#product/route.coffee
...
actions:
    # Not actually my code but illustrates the problem
    addToCart: (product1, product2)->
      order = @modelFor 'order'
      console.log order.get('line_items.length') # prints 0

      order.get('line_items').pushObject product1
      console.log order.get('line_items.length') # prints 1

      order.get('line_items').pushObject product2
      console.log order.get('line_items.length') # prints 2

      order.get('line_items').pushObject product1
      console.log order.get('line_items.length') # prints 2

      order.get('line_items').pushObject product2
      console.log order.get('line_items.length') # prints 2


      ...

The problem is that the user might want a single item more than once. The simplest way to represent that is to have an array with duplicate entries. It seems Ember is not letting me do that for relationships. How can I add a model more than once to a relationship ?

like image 919
jd. Avatar asked Jun 30 '15 23:06

jd.


2 Answers

It sounds like you actually need a line_items model with a quantity field. Just shoving more of the same item in your orders model isn't really a normalized solution.

I would recommend the following:

lineItem = DS.Model.extend({
    orders: DS.belongsTo('orders'),
    product: DS.belongsTo('products'),
    quantity: DS.attr('number'),
});

orders = DS.Model.extend({
    lineItems: DS.hasMany('lineItem', {async: true}),
    customerId: DS.belongsTo('customers'),
});

products = DS.Model.extend({
    title: DS.attr('string'),
    description: DS.attr('string'),
    cost: DS.attr('string'),
});

This would allow you to create multiple records in your lineItem model, that will have a unique ID but be bound to a specific order, (which would solve the issue of multiple orders having the same lineItem) for example, you could have:

{
    "lineItem" : 
        [
            {
                "id": 1,
                "orderId": 1,
                "product": 1,
                "quantity": 100,
            },
            {
                "id": 2,
                "orderId": 1,
                "product": 2,
                "quantity": 10,
            },
            {
                "id": 3,
                "orderId": 2,
                "product": 1,
                "quantity": 100,
            }
        ]
}

In this design you would remove the reference to lineItems from your json, as ember-data looks after the inverse relationship for you (if you aren't sideloading the relationship you will need to add async to your model). This will mean that if you need to change a line item, it will only affect one order, and if you need to change the order that a lineItem is related to you just do this on the lineItem model.

{
    "Orders" : 
        [
            {
                "id": 1,
                "customerId": 123456,
            },
            {
                "id": 2,
                "customerId": 123456,
            }
        ]
}
like image 78
Phil Hauser Avatar answered Sep 30 '22 18:09

Phil Hauser


They should have an id property, then they will be able to co-exist in the same array and be distinct items of the same product type - with the same name (all the same properties other than id).

Either that, or you have one record that represents a product type, and then have a quantity attribute to specify how many of each product there are..

like image 25
Loz Jackson Avatar answered Sep 30 '22 20:09

Loz Jackson