Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Backbone Relational not setting reverse relations properly?

I'm trying to use Backbone.Relational to set up some associations in my app.

Basically I have Backbone Search and Service models. A Search has a ServiceList collection which contains many services.

However, I don't seem to be able to access the parent Search from within the Service initializer. When I try to log the parent search I get null. Can anyone see what I'm doing wrong?

My Search model is set up like so (code might have syntax errors, I'm translating from coffeescript on the fly):

var Search = new Backbone.RelationalModel({
  urlRoot: '/searches',

  relations: [{
    type: Backbone.HasMany,
    key: 'services',
    relatedModel: 'Service',
    collectionType: 'ServiceList',
    reverseRelation: {
      key: 'search'
    }
  }],

  initialize: function(options) {
    // => Search "has services:", ServiceList
    console.log this, "has services:", @get('services');
  }
});


var Service = new Backbone.RelationalModel
  initialize: function() {
    // => Service "in" null
    console.log this, "in", @get('search');
  }
});

Or if you prefer CoffeeScript:

class Search extends Backbone.RelationalModel
  urlRoot: '/searches'

  relations: [
    type: Backbone.HasMany
    key: 'services'
    relatedModel: 'Service'
    collectionType: 'ServiceList'
    reverseRelation:
      key: 'search'
  ]

  initialize: (options) ->
    // => Search "has services:", ServiceList
    console.log this, "has services:", @get('services')



class Service extends Backbone.RelationalModel
  initialize: ->
    // => Service "in" null
    console.log this, "in", @get('search')
like image 294
David Tuite Avatar asked Dec 28 '22 03:12

David Tuite


1 Answers

Short Answer

You simply don't have access to the reverse relation's value in the Service's initialize method.

The value for the reverse relation is set after the initialize has completed.

Longer Answer

Assuming this javascript:

Search = Backbone.RelationalModel.extend({
  urlRoot: '/searches',

  relations: [{
    type: Backbone.HasMany,
    key: 'services',
    relatedModel: 'Service',
    reverseRelation: {
      key: 'search'
    }
  }],

  initialize: function(options) {
    console.log(this, "has services:", this.get('services'));
  }
});


Service = Backbone.RelationalModel.extend({
  initialize: function() {
    console.log(this, "in", this.get('search'));
  }
});

When you create a new Search model with related Services:

s1 = new Search({name:"Some Search",services:[{name:"service1"},{name:"service2"}]});

What's going to happen is:

new Service model created (for service1) - name set to "service1"
  (but, since what got passed to the model for properties is {name:"service1"}
   you can see how this model cannot know its reverse relation yet.)
new Service model created (for service2) - name set to "service2"
  (same as above)
new Search model created (for 'some search')
  name set to 'some search'
  service1 Service model added to Search.services
    (triggers 'update:search' event on Service1 model)
  service2 Service model added to Search services
    (triggers 'update:search' event on Service2 model)

It isn't until the service1 and service2 Service models are added to the Search.services collection that the reverse relations on service1.search and service2.search are set.

Here's a JS fiddle that shows the order of operations in the console: http://jsfiddle.net/MNh7N/6/

like image 110
Edward M Smith Avatar answered Feb 15 '23 14:02

Edward M Smith