1
votes

I'm using Ember 1.13.2 and Ember-data 1.13.4

I'm trying to find the out the type of relationship that a model has. Take the following example model.

// my post model
export default DS.Model.extend({
  author: DS.belongsTo('author'),
  comments: DS.hasMany('comment')
});

How can I check in my code if comments is a hasMany or belongsTo relationship?

At the moment I have worked out two solutions that work, but they feel a bit messy to me and I'm sure there must be a better way.

one way that works is this

var relationship = post.get(relationshipName); // relationshipName = 'comments'

if ( relationship.constructor.toString().indexOf('Array') !== -1 ) {
    relationshipType = 'hasMany';
}
else if ( relationship.constructor.toString().indexOf('Object') !== -1 ) {
    relationshipType = 'belongsTo';
}

another way that works

var relationship = post.get(relationshipName); // relationshipName = 'comments'

if (relationship.get('@each')) {
    relationshipType = 'hasMany';
}
else {
    relationshipType = 'belongsTo';
}

they both work, but they both feel a bit clunky to me and I don't know how reliable they are.

So the question is, which is the more reliable method?.. or is there a better way?

3
When accessing the relationship with post.get('comments') you are given the values - not a special relationship object. Depending on your code I'd suggest moving the code to the post model itself, like: post.doSomethingWithAllBelongsTo() and add that method to your post model. There you can access all relationships of that model with this.eachRelationship, where you can access the kind.enspandi

3 Answers

3
votes

I think you are looking for Model.eachRelationship example:

model.eachRelationship(function(name, descriptor) {
  if (descriptor.kind === 'hasMany') {
      //do something here
  }
});
2
votes

You could check the fields for that.

import Post from '../models/post'

Ember.get(Post, 'fields').get('comments'); // hasMany

Or if you have an instance of a model you can check off the constructor:

Ember.get(post.constructor, 'fields').get('comments'); // hasMany
0
votes

As hasMany returns instance of DS.ManyArray and belongsTo returns DS.Model you can check via instanceof:

var something = post.get(relationshipName); // relationshipName = 'comments'
var relationshipType = 'belongsTo';
if(something instanceof DS.ManyArray) {
  relationshipType = 'hasMany';
}

Going further you can use the following code to determine if the field is not a model at all (i.e. computed property):

var something = post.get(name);
var propertyType = 'unknown';
if(something instanceof DS.ManyArray) {
  propertyType = 'relationship:hasMany';
} else if(something instanceof DS.Model) {
  propertyType= 'relationship:belongsTo';
} else if(/*whatever you want*/) {
  propertyType = /*whatever you want*/;
} else {
  propertyType = 'unknown';
}

Another way, if you don't want to import DS for any reason is to check for 'relationship' property:

var something = post.get(relationshipName); // relationshipName = 'comments'
var relationshipType = relationship.hasOwnProperty('relationship') ? 'hasMany' : 'belongsTo';

This one is OK only if you're sure that "something" is relationship, because it would give you false-positive if "something" is just a model, computed property etc.