2

I have these models:

TravelClient.Tour = DS.Model.extend({
  title: DS.attr('string'),
  description: DS.attr('string'),
  seats: DS.attr('number'),
  takenSeats: DS.hasMany('TravelClient.TakenSeat', {embedded:'always'})

  TakenSeats: function() {
    console.log(this.get('takenSeats').toArray())
  }.property('takenSeats')
});

TravelClient.TakenSeat = DS.Model.extend({
  tour: DS.belongsTo('TravelClient.Tour'),
  number: DS.attr('number')
});

JSON looks like this:

{
  "tours": [
    {
      "id": "5110e8b5a8fefe71e0000197",
      "title": "qui deserunt dolores",
      "description": "Id velit nihil.",
      "seats": 12,
      "taken_seats": [
        {
          "id": "5110e8b5a8fefe71e0000196",
          "number": "5"
        },
        {
          "id": "5110e8b5a8feffffe0000196",
          "number": "2"
        }]
}

But yeah, when I do console.log(this.get('takenSeats').toArray() in Tour model's method, it returns Uncaught TypeError: Cannot call method '_create' of undefined, so, it seems that takenSeats did not load with parent model. What's wrong?

UPDATE

added tour_id to JSON, but now, when I want to use calculated property:

  freeSeats: function() {
    var seats = this.get('seats');
    var takenSeats = this.get('takenSeats');
    if (takenSeats) {
      return (seats - takenSeats.length);
    }
    else {
      return seats;
    }
  }.property('seats', 'takenSeats')

takenSeats is undefined.

UPDATE 2:

TravelClient.RESTSerializer = DS.RESTSerializer.extend({
  init: function() {
    this._super();

    this.map('TravelClient.Tour',{
      images:{embedded:'always'},
      options:{embedded:'always'},
      takenSeats:{embedded:'always'}
    });
  }
});

TravelClient.CUSTOMAdapter = DS.RESTAdapter.extend({
  bulkCommit: false,
  serializer: TravelClient.RESTSerializer.create(),
  url: "http://192.168.1.27:3000",    
  buildURL: function(record, suffix) {
    var s = this._super(record, suffix);
    return s + ".json";
  }
});

TravelClient.Store = DS.Store.extend({
  revision: 11,
  adapter: TravelClient.CUSTOMAdapter.create()
});

TravelClient.store = TravelClient.Store.create();
xamenrax
  • 1,724
  • 3
  • 27
  • 47

2 Answers2

1

the TakenSeats computed property is perceived as a class because it's capitalized. Next to that embedded loading has to configured differently. Like so: This way the tour object becomes dirty when a takenseat changes.

DS.RESTAdapter.map('TravelClient.Tour', {
    takenSeats: { embedded: 'always' },
});

Or: This way the tour doesn't become dirty.

DS.RESTAdapter.map('TravelClient.Tour', {
    takenSeats: { embedded: 'load' },
});

Do this before you initialize your Store and Adapter. This will make the computed property unnecessary. You can just do tour.get('takenSeats');

Oh and you don't have to specify that the type is embedded anymore. The id's in the taken_seats array that link back to the tour need to be called tour_id.

{
  "tours": [{
    "id": "5110e8b5a8fefe71e0000197",
    "taken_seats": [{
      "id": "5110e8b5a8fefe71e0000196",
      "tour_id": "5110e8b5a8fefe71e0000197"
      "number": "5"
    }]
  }]
}
albertjan
  • 7,739
  • 6
  • 44
  • 74
0

I had a similar problem to this. ember-model doesn't map through nested objects.

Your JSON output currently has all the data nested beneath the tours root.

If you have access to the API, then i suggest trying to remove the root, otherwise look into using your as the main object and then grabbing all the nested objects from there on down.

instead of this:

"tours": [{
    "id": "5110e8b5a8fefe71e0000197",
    "taken_seats": [{
      "id": "5110e8b5a8fefe71e0000196",
      "tour_id": "5110e8b5a8fefe71e0000197"
      "number": "5"
    }]
  }]

make it look like this:

  [{
    "id": "5110e8b5a8fefe71e0000197",
    "taken_seats": [{
      "id": "5110e8b5a8fefe71e0000196",
      "tour_id": "5110e8b5a8fefe71e0000197"
      "number": "5"
    }]
  }]

its possible my syntax is off, but this similar idea worked for me.

Blair Anderson
  • 19,463
  • 8
  • 77
  • 114