9

I would like to make a relation between two models User and Task using backbone-relational.

The relation between the two models is the following:

taskModel.creator_id = userModel.id   

// TaskModel
var TaskModel = Backbone.RelationalModel.extend({

    relations: [
        {
            type: Backbone.HasOne,
            key: 'creator',
            keySource: 'creator_id',
            relatedModel: Users
        }
    ],

    // some code
});

// Task collection
var TaskCollection = Backbone.Collection.extend({

    model: TaskModel,

    // some code

});

// User Model
var User = Backbone.RelationalModel.extend({
    // some code
});

Actually the problem is in the collection.models, please see the attached images:

Please check this jsfiddle: http://jsfiddle.net/2bsE9/5/

var user = new User(),
    task = new Task(),
    tasks = new Tasks();

task.fetch();
user.fetch();
tasks.fetch();

console.log(user.attributes, task.attributes, tasks.models);

enter image description here

P.S.:

Actually I am using requireJs to get the UserModel, so I cannot include quotes in relatedModel value.

define([
    'models/user',
    'backbone',
    'relationalModel'
], function (User) {
    "use strict";

    var Task = Backbone.RelationalModel.extend({
        relations: [
            {
                type: Backbone.HasOne,
                key: 'creator',
                keySource: 'creator_id',
                relatedModel: User
            }
        ],
    });
);
antonjs
  • 14,060
  • 14
  • 65
  • 91

2 Answers2

4

Edit 2:

http://jsfiddle.net/2bsE9/13/

I updated the jsfiddle to reflect the changes I suggested below. As long as you are calling toJSON on your task, what gets to the server is a json object with the creator_id property set to the actual id of the user. The keyDestination here is redundant as the documentation states it is set automatically if you use keySource.

Edit:

https://github.com/PaulUithol/Backbone-relational#keysource

https://github.com/PaulUithol/Backbone-relational#keydestination

https://github.com/PaulUithol/Backbone-relational#includeinjson

The combination of the three above might solve your issue.

var Task = Backbone.RelationalModel.extend({
    relations: [
        {
            type: Backbone.HasOne,
            // The User object can be accessed under the property 'creator'
            key: 'creator',
            // The User object will be fetched using the value supplied under the property 'creator_id'
            keySource: 'creator_id',
            // The User object will be serialized to the property 'creator_id'
            keyDestination: 'creator_id',
            // Only the '_id' property of the User object will be serialized
            includeInJSON: Backbone.Model.prototype.idAttribute,


            relatedModel: User
        }
    ],
});

The documentation also states that the property specified by keySource or keyDestination should not be used by your code. The property cannot be accessed as an attribute.

Please try this and comment if that fixes your issue.

Btw, here is a nice blog post that uses backbone-relational end to end. http://antoviaque.org/docs/tutorials/backbone-relational-tutorial/

Amith George
  • 5,806
  • 2
  • 35
  • 53
  • The question is: why the `creator_id` attribute is missing in `tasks.models`? – antonjs Jul 10 '12 at 13:20
  • Is the missing creator_id causing issues? Are you unable to modify a task and push the changes back? I am trying to understand if you are just curious or is there a definite problem. If there is an issue, maybe we can try solving that... If not, well, we can wait for someone who knows more :) – Amith George Jul 10 '12 at 13:27
  • Having creator_id missing is an issue when you try to save the related model because the backend expect to see the creator_id. – antonjs Jul 10 '12 at 13:51
  • @AntoJs, were you able to try it? – Amith George Jul 11 '12 at 14:19
  • I looked to your http://jsfiddle.net/2bsE9/13/ and it works. In my localHost using requireJs does not. I am trying to figure out what is the problem because in jsfiddle will be difficult to reproduce it. – antonjs Jul 11 '12 at 15:01
  • Am curious, why accept this answer and award a bounty to another? I know this is allowed as per the bounty system and they have their own reasons for having implemented it. That said, am not sure what to make of it. Are you saying that while this answer works, you would rather do what the other answer suggests? If that really is how you feel, then you ought to mark that as the answer... – Amith George Jul 13 '12 at 08:46
  • I am sorry. Actually I don't know why I awarded a bounty to Tanzeeb Khalili. Because I want to award you. Unfortunately I don't know how to cancel the bounty to Tanzeeb Khalili. – antonjs Jul 13 '12 at 13:57
0

Edit

Updated jsfiddle

The problem is that Backbone-Relational explicitly deletes the keySource to 'prevent leaky abstractions'. It has a hardcoded call to unset on the attribute, in Backbone-Relational:

// Explicitly clear 'keySource', to prevent a leaky abstraction if 'keySource' differs from 'key'.
if ( this.key !== this.keySource ) {
    this.instance.unset( this.keySource, { silent: true } );
}

You will need to overwrite the unset method in your Task model:

var Task = Backbone.RelationalModel.extend({
    urlRoot: ' ',

    relations: [
        {
            type: Backbone.HasOne,
            key: 'creator',
            relatedModel: User,
            keySource: 'creator_id'
        }
    ],

    unset: function(attr, options) {
        if (attr == 'creator_id') {
          return false;
        }

        // Original unset from Backbone.Model:
        (options || (options = {})).unset = true;
        return this.set(attr, null, options);
     },

    sync: function (method, model, options) {
        options.success({
            id: 1,
            name: 'barTask',
            creator_id: 1
        });
    }
});

Obvious problems with this approach are that you will need to modify your code if either Backbone changes its Backbone.Model.unset method or Backbone-Relational changes its keySource behavior.

Tanzeeb Khalili
  • 7,324
  • 2
  • 23
  • 27
  • Actually I am using requireJs to get the User Model. So I cannot include quotes. I will add more detail in my question. – antonjs Jul 10 '12 at 11:42
  • Anyway what's about the message `Relation= d ; no model, key or relatedModel (function (){a.apply(this,arguments)}, "creator", undefined) ` – antonjs Jul 10 '12 at 11:49
  • Ok, between your comments in this answer and the other, I think I understand your requirements. Updated my answer with a working solution. – Tanzeeb Khalili Jul 12 '12 at 07:38