Foreign key populated with an object
Asked Answered
D

2

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
            }
        ],
    });
);
Dipterocarpaceous answered 5/7, 2012 at 14:47 Comment(0)
T
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/

Taluk answered 10/7, 2012 at 13:1 Comment(7)
The question is: why the creator_id attribute is missing in tasks.models?Dipterocarpaceous
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 :)Taluk
Having creator_id missing is an issue when you try to save the related model because the backend expect to see the creator_id.Dipterocarpaceous
@AntoJs, were you able to try it?Taluk
I looked to your 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.Dipterocarpaceous
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...Taluk
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.Dipterocarpaceous
A
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.

Aholah answered 10/7, 2012 at 5:12 Comment(3)
Actually I am using requireJs to get the User Model. So I cannot include quotes. I will add more detail in my question.Dipterocarpaceous
Anyway what's about the message Relation= d ; no model, key or relatedModel (function (){a.apply(this,arguments)}, "creator", undefined) Dipterocarpaceous
Ok, between your comments in this answer and the other, I think I understand your requirements. Updated my answer with a working solution.Aholah

© 2022 - 2024 — McMap. All rights reserved.