2
votes

Ok, so I'm new to Ember so bear with me.

I have an Ember application that is communicating with an API that does not adhere to JSONAPI standards, thus I have begun writing my own serializers in order to use Ember Data. However I am finding that when I make multiple requests to the same resource, the data is having trouble writing to the store. Consecutive requests to the same resource always responds with the following error:

TypeError: Cannot convert object to primitive value

Which from my limited understanding, implies that the data I am sending to the store is being treated like a string.

In my Application route I have written a findAll to my model 'listing-item' like so:

model: function() {
  return this.store.findAll('listing-item');
},

In a nested 'user' route, when I do any type of request for the listing-item data that returns an array response (query, findAll) for the listing-item data, I get:

TypeError: Cannot convert object to primitive value

at EmptyObject.SETTER_FUNCTION [as title] (ember.debug.js:20672)
at assign (<anonymous>)
at InternalModel.setupData (internal-model.js:244)
at Class._load (store.js:1728)
at Class._pushInternalModel (store.js:2055)
at Class._push (store.js:1995)
at finders.js:141
at Backburner.run (ember.debug.js:720)
at Class._adapterRun (store.js:2253)
at finders.js:139

(Title is a field in my listing item model).

As I mentioned earlier, my API does not adhere to JSONAPI standards, so I've written a listing-item serializer like so:

import DS from 'ember-data';

export default DS.RESTSerializer.extend({

  normalizeArrayResponse(store, primaryModelClass, payload) {

    payload.data = [];
    payload.listing_item._data.forEach(this.formatListingItemArray, payload.data);
    delete payload.listing_item;

    return payload;
  },

  formatListingItemArray(listingItem) {
    this.push({
      type: "listing-item",
      id: listingItem.id,
      attributes: {
        title: listingItem.title,
        description: listingItem.description,
        buy_now_price: listingItem.buy_now_price,
        created_at: listingItem.created_at,
        category_id: listingItem.category_id,
        subcategory_id: listingItem.subcategory_id,
        identity_id: listingItem.identity_id,
        listing_number: listingItem.listing_number,
        brand_new: listingItem.brand_new,
        sold: listingItem.sold,
      },
    });
  },

});

So I suppose my question is, what is Ember Data doing with my data object for this error to occur, and what might I be doing wrong in formatting my data for Ember data to consume.

UPDATES:

It appears as though only the top 3 fields are causing this error to occur. If I comment out the attributes 'title', 'description' and 'buy_now_price' in my serializer, I don't get this error. Also, it appears this only occurs when I navigate to the route, If I am in the /user route when the application loads, both requests work as expected.

Ok, so I've been crawling through ember-data code and found that in the internal-model.js file there is a setup function that looks at the current attributes in the store and compares them to the data being passed from the serializer. It then does an assign() to copy the serializers new data over to the stores object. However for some reason it seems that my stores object has a set of 'getter' and 'setter' function that come back from the store for the problematic fields (title, description and buy_now_price). What I need to know now is why are these functions coming along for the ride and what have I done to cause this?

Picture of getters/setters on ember-data object

Thanks in advance, let me know if there's any more information I need to provide in order to give better context.

1

1 Answers

0
votes

So I found the solution to my problem for anyone that experiences a similar issue.

The symptom was as stated above, it seemed as though ember-data was returning getter and setter functions back from the store and having problems placing my new values in their stead. However the clue was that it was only the fields that I was rendering in my template.

The problem seems to be that I was using an Ember Concurrency task to perform the loading of my data, then passing the task straight in to an internal component from the model template. Something like this (not tested code):

The WRONG pattern (one I was using to experience the issue).

//route file - application.js
export default Ember.Route.extend({

  model: function() {
    return {
      listings: this.get('getListings').perform(),
    };
  },      

  getListings: task(function * () {
    return yield this.store.findAll('listing-item');
  }),

})


//application template - application.hbs
{{listing-index listings=model.listings}}


//listing index component template.hbs
{{#if listings.value}}
  {{#each listings.value.content as |listing|}}
    {{listing._data.title}}
    {{listing._data.description}}
    {{listing._data.buy_now_price}}
  {{/each}}
{{/if}}

The CORRECT pattern seems to be as thus:

//route file - application.js

export default Ember.Route.extend({

  model: function() {
    return {
      listings: this.get('getListings').perform(),
    };
  },      

  getListings: task(function * () {
    return yield this.store.findAll('listing-item');
  }),

})


//application template - application.hbs
{{#if listings.value}}
  {{listing-index listings=model.listings.value}}
{{/if}}


//listing index component template.hbs   
{{#each listings as |listing|}}
  {{listing.title}}
  {{listing.description}}
  {{listing.buy_now_price}}
{{/each}}

So the problem seems to lie in this pattern of passing the task rather than the content of the task in to my component. When I looped over the listings in the model template then passed the listings straight in to the component, it seemed to have solved my issues. I gather this is something to do with the use of these _data properties. A further explanation would be appreciated but i'll mark this as resolved for now.