Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

backbone.js - handling model relationships in a RESTful way

I'm using backbone.js

For example, let's suppose we have a "products" model and a "categories" model which have a many-to-many relationship. In one of my views, say I need to retrieve a list of all categories and know whether or not each one is related to the current product model.

Do I set up a "category" collection and have it be a property of my model and somehow give it access to the id of the model so that when it is fetched, it only gets the categories that are related? And then I could fetch all categories and cross examine them to see which ones are related while still having the ones which are not?

I have no idea what the best way to do this would be. I'm used to using an ORM which makes it easy on the server-side.

like image 746
Matthew Avatar asked Aug 25 '11 23:08

Matthew


3 Answers

Check out backbone-relational.

like image 74
Sam Dolan Avatar answered Oct 19 '22 11:10

Sam Dolan


There is a simple & customizable solution for it, although it may not be as robust as backbone-relational.

Backbone.ModelWithRelationship = Backbone.Model.extend({
  mappings: {},

  set: function(attributes, options) {
    _.each(this.mappings, function(constructor, key) {
      var RelationshipClass = stringToFunction(constructor);
      var model = new RelationshipClass();

      /* New relational model */
      if (!this.attributes[key]) {  
        this.attributes[key] = (model instanceof Backbone.Collection) ? model : null;
      }

      /* Update relational model */
      if (attributes[key] && !(attributes[key] instanceof Backbone.Model || attributes[key] instanceof Backbone.Collection)) {
        if (model instanceof Backbone.Model) {
          this.attributes[key] = model;
          this.attributes[key].set(attributes[key], options);           
        } else if (model instanceof Backbone.Collection) {
          this.attributes[key].reset(attributes[key], options);         
        }

        delete attributes[key];
      } 
    }, this);

    return Backbone.Model.prototype.set.call(this, attributes, options);
  }
});

You can declare the mapping just by creating a subclass of Backbone.ModelWithRelationship.

Models.Post = Backbone.ModelWithRelationship.extend({
  mappings: {
    'comments': 'Collection.CommentCollection',
    'user': 'Models.User'
  }
});
like image 33
mateusmaso Avatar answered Oct 19 '22 09:10

mateusmaso


http://pathable.github.com/supermodel/ is fantastic. It let's you do stuff like:

Post.has().many('comments', {
  collection: Comments,
  inverse: 'post'
});

Comment.has().one('post', {
  model: Post,
  inverse: 'comments'
});

var post = Post.create({
  id: 1,
  comments: [{id: 2}, {id: 3}, {id: 4}]
});

post.comments().length; // 3
var comment = Comment.create({id: 5, post_id: 1});
post.comments().length; // 4
comment.post() === post; // true :D
like image 39
PETER BROWN Avatar answered Oct 19 '22 09:10

PETER BROWN