1
votes

I searched everywhere but can't seem to find an answer for this simple problem here on SO.

Problem:

I have a hasMany relationship in a model that is loaded by the route in a findAll(). Payload looks fin according to many answers I've seen here, but I get "TypeError: Cannot read property 'replace' of undefined". More details below.

How can I get this hasMany relationship to work? I'm using asynch:false and sending the sideload as recommended.

Using: Ember 2.1.0, Ember-Data 2.1.0.

Stacktrace:

TypeError: Cannot read property 'replace' of undefined
    at Object.func (ember.debug.js:36026)
    at Object.Cache.get (ember.debug.js:13165)
    at decamelize (ember.debug.js:36068)
    at Object.func (ember.debug.js:35974)
    at Object.Cache.get (ember.debug.js:13165)
    at Object.dasherize (ember.debug.js:36072)
    at ember$data$lib$system$normalize$model$name$$normalizeModelName (normalize-model-name.js:13)
    at ember$data$lib$serializers$json$serializer$$default.extend.modelNameFromPayloadKey (json-api-serializer.js:267)
    at ember$data$lib$serializers$json$serializer$$default.extend._extractType (json-api-serializer.js:258)
    at ember$data$lib$serializers$json$serializer$$default.extend.normalize (json-api-serializer.js:290)

Route:

app/routes/search.js

export default Ember.Route.extend({

    model(params) {
        if(params.query){
            return this.store.findAll('search-result');
        }
        return null;
    },

    actions:{
        sendSearch: function(queryString){
            this.store.unloadAll('search-result');
            this.refresh();
        }
    }

});

Models:

app/models/search-result.js

import DS from 'ember-data';

export default DS.Model.extend({

  title:        DS.attr('string'),
  description:  DS.attr('string'),
  url:          DS.attr('string'),
  tags:         DS.hasMany('search-result-tag', {async:false})

});

app/models/search-result-tag.js

import DS from 'ember-data';

export default DS.Model.extend({

  name: DS.attr('string'), 

});

Adapter (for search-result)

import DS from 'ember-data';

export default DS.RESTAdapter.extend({

    host: 'http://localhost:8080',
    urlForFindRecord(id, modelName, snapshot) {
        let url = this._super(...arguments);
        let query = Ember.get(snapshot, 'adapterOptions.query');
        if (query) {
            url += '?' + Ember.$.param(query); // assumes no query params are present already
        }
        return url;
    },
    urlForFindAll(modelName) {

        var queryDict = {};
        location.search.substr(1).split("&").forEach(function(item) {queryDict[item.split("=")[0]] = item.split("=")[1]})

        let url = this._super(...arguments);
        let query = queryDict['query'];

        if (query) {
            url += '?query=' + query; // assumes no query params are present already
        }

        return url;
    }

});

Payload

{
  "search-result-tags": [
    {
      "name": "this-is-tag-#-0",
      "id": 0
    }
  ],
  "search-results": [
    {
      "description": "This is description for blabla2",
      "id": 0,
      "title": "Blabla 2",
      "url": "http://blablabla2.com",
      "tags": []
    },
    {
      "description": "This is description for blabla",
      "id": 1,
      "title": "Blabla",
      "url": "http://blabla.com",
      "tags": [
        0
      ]
    }
  ]
}
1
It looks like it's using the JSONAPISerializer. Have you set it to use the RESTSerializer?andorov
I'll try. I need to create a RESTSerializer as search-result.js and just extend the default one, right?Breno Inojosa
You probably want your ApplicationSerializer to extend DS.RESTSerializerandorov
yes, since your 3rd answer. please write an answer here and I'll accept it :)Breno Inojosa

1 Answers

2
votes

You need to use the RESTSerializer in addition to the RESTAdapter. So app/serializers/application.js would be -

import DS from 'ember-data';

export default DS.RESTSerializer.extend({
});

See the docs. You may need to override keyForAttribute, if you need to change cases / underscores of your keys.

Note that if you are using Rails API for the backend you want ActiveModelAdapter and ActiveModelSerializer, which are available as an addon.