backbone.js - handling model relationships in a RE

2019-02-04 15:06发布

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.

4条回答
beautiful°
2楼-- · 2019-02-04 15:32

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'
  }
});
查看更多
我只想做你的唯一
3楼-- · 2019-02-04 15:34

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
查看更多
forever°为你锁心
5楼-- · 2019-02-04 15:45

Assuming you are using a join table on the backend:

Create a collection and model containing all the rows on your join table and add the following methods to the collection: productsByCategory and categoriesByProduct (using [join collection].where(...).)

Having data in Backbone mirroring your data in the backend seems to help keep things simple and you won't have to do anything complicated when setting URLs.

查看更多
登录 后发表回答