Relationship id return to server a String and not a Int!


#1

Hello!

Im a new ember-data user, this is too interesting (although documentation feels very dispersed yet), and I have a problem now. Im trying to port an ember project from jQuery to ember-data, and my model have a common relationship like this:

//entity
export default DS.Model.extend({
  name: DS.attr('string'),
});
    
//user
export default DS.Model.extend({
  email: DS.attr('string'),
  entity: DS.belongsTo('entity',{ async: true }),
});

Now, when i create a new user, all is okay in client side ( using by example this.store.peekRecord('entity',1) to choose the entity before this.store.createRecord), but on save() this fails because entity attr arrived to server like a String and not as Integer ("entity":"1").

I read in https://github.com/rykov/ember-data/blob/master/BREAKING_CHANGES.md (revision 6), this is the default behaviour, but i dont want this.

Thanks in advance


#2

Okay, I tried it on my own using a serializer object:

export default DS.RESTSerializer.extend({
    serialize: function(snapshot, options) {
        var json = this._super(snapshot, options);
        json.entity = parseInt(json.entity);
        return json;
    }
});

However, I do not know if this is the best solution … should also be noted that the documentation of code seems out of date, since the id displayed as numbers and not as strings.

:wink:


#3

Ran into this problem when using Ember w/ Yesod, my solution was to modify the application serializer to call parseInt for all relationships using serializeBelongsTo and seriailizeHasMany. This way you do not have to write a serializer for each model, or a parseInt call for every attribute.

import DS from 'ember-data';

export default DS.RESTSerializer.extend({
  serializeBelongsTo: function(record, json, relationship) {
    this._super(record, json, relationship);
    var key = relationship.key;
    var json_key = this.keyForRelationship ? this.keyForRelationship(key, "belongsTo") : key;
    json[json_key] = parseInt(json[json_key]);
  },
  serializeHasMany: function(record, json, relationship) {
    this._super(record, json, relationship);
    var key = relationship.key;
    var json_key = this.keyForRelationship ? this.keyForRelationship(key, "hasMany") : key;
    json[json_key] = parseInt(json[json_key]);
  }
});

#4

I really liked your response, but I think it needs a small improvement - one needs to iterate over hasMany attribute to collect all values (following code is written in CoffeeScript):

serializeHasMany: (snapshot, json, relationship) ->
  @_super snapshot, json, relationship
  key = @keyForRelationship relationship.key, "hasMany" # with provided keyForRelationship() implementation
  for value, index in json[key]
    json[key][index] = parseInt value

#5

Thanks, quite a bit late, but I ended up with this:

import DS from 'ember-data';

export default DS.RESTSerializer.extend({
  serializeBelongsTo: function(record, json, relationship) {
    this._super(record, json, relationship);
    var key = relationship.key;
    var json_key = this.keyForRelationship ? this.keyForRelationship(key, "belongsTo") : key;
    json[json_key] = parseInt(json[json_key]);
  },
  serializeHasMany: function(record, json, relationship) {
    this._super(record, json, relationship);
    var key = relationship.key;
    var json_key = this.keyForRelationship ? this.keyForRelationship(key, "hasMany") : key;
    if (json_key in json) {
      json[json_key] = json[json_key].map((item) => {
        parseInt(json[json_key]);
      });
    }
  }
});