ember-pouch: Bidirectional hasMany relationships are not loadable/saveable from the many side

The default behavior of DS.JSONSerializer is to not serialize the many side of bidirectional hasMany relationships. See emberjs/data#2494 for links to discussion about this.

The upshot for ember-pouch is that the contents of a bidirectional hasMany relationship isn’t saved or loaded when working from the many side. E.g., say you have these models:

// app/models/person.js
export default DS.Model.extend({
  sandwiches: DS.hasMany('sandwich', { inverse: 'owner' })
});

// app/models/sandwich.js
export default DS.Model.extend({
  owner: DS.belongsTo('person')
});

In this case you won’t be able to load or save a person’s sandwiches from the person. (You will be able to if you remove owner from sandwich, though.)

The workaround for this that other similar adapters use (ember-localstorage-adapter, ember-indexeddb-adapter) is to provide a serializer which forces these associations to be serialized on the hasMany side (as well as the belongsTo side). I’m doing this now in my own application to work around this issue.

Unfortunately this requires copying a bunch of code from JSONSerializer (hence emberjs/data#2494). It also duplicates the information about the relationship, requiring both sides to be saved manually whenever the relationship changes.

I’m not sure if there’s a practical better solution. It appears that the ember-data solution is to have the server use different serializations for reads vs. writes, but that doesn’t work for a local database. One idea I had was that the adapter could look up the IDs for the hasMany relationship dynamically — since all the data is local this might work, but it also might be complex to get right.

About this issue

  • Original URL
  • State: closed
  • Created 10 years ago
  • Comments: 33 (8 by maintainers)

Commits related to this issue

Most upvoted comments

@MSchmidt I got this to work by adding an application serializer that extends ember-pouch’s serializer:

//  app/serializers/application.js
import Ember from 'ember';
import { Serializer } from 'ember-pouch';

export default Serializer.extend({
  _shouldSerializeHasMany: function() { return true; }
});

Now the ids for the manyToOne relationship are stored on the hasMany side as well.

Here is the private method we are overriding https://github.com/emberjs/data/blob/v2.2.1/packages/ember-data/lib/serializers/json-serializer.js#L814-L830

Ember: 2.2.0 Ember Data: 2.2.1

@openhouse thanks a lot! It’s a lifesaver!

@openhouse could you open a PR? If your method is successful, it should be added to the repo. 😃

@openhouse thanks for your simple solution!