8

I got a wtf problem that I can't figure out. I explain :

I have a model named Product :

var Product = Backbone.RelationalModel.extend(
{
    urlRoot: Backbone.rootApiUrl + '/products',
    defaults: {
        id: '',
        name: '',
        description: '',
        current_price: '',
        categories: '',
        duration: '',
        shipping_cost: '',
        start_date: '',
        user_id: null,
        is_buy_it_now: ''
    },

    relation: [{
        type: Backbone.HasOne,
        key: 'user_id',
        relatedModel: User,
        autoFetch: true
    }]
});

My field user_id is a foreign key for one User (which is also a Model in Backbone) :

var User = Backbone.RelationalModel.extend(
{
    urlRoot: Backbone.rootApiUrl + '/users',
    defaults: {
        id: '',
        name: '',
        email: '',
        firstname: '',
        lastname: '',
        password: '',
        card_nb: '',
        cart_total: ''
    }
});

My fetch relations work perfectly in each separate model. But when i put a relation between the Product.user_id and my User model, a wtf error occurs.

I've tried everything possible : all the keys (keySource, keyDestination ........... with all values possibles). I've even put breakpoints into the Relation Lib to be able to watch what happened ... Nothing to say. Even StackOverflow doesn't know this bug :P (Or i badly searched)

The final problem is :

  • My product is correctly sent by the API and set in Backbone (OK).
  • The field user_id is first set at a number by the Product API response, and then put at NULL by Relational instead of being replaced by the object User (WHY ?)
  • When I watch my network debugger, Relational calls the API for the User object (it's all right here) with the user_id number (OK). The server response is good, with the right user in JSON (OK). But Relational doesn't bind this response object with the field user_id, which is now .... NULL (NOT OK).
    • So I got a User object lost (but I can console.log() it if I put a success function in my autoFetch), not correctly linked to his parent Product with the field user_id.

EDIT : a JSFiddle is available here http://jsfiddle.net/gjdass/WNWrm/ (Be careful, the API can be long to respond, about 10sec, it's normal).

Thanks in advance :/ Sorry for the time you may take for this.

Ahmet Emre Kilinc
  • 5,489
  • 12
  • 30
  • 42
gjdass
  • 146
  • 7
  • I think the only other question I have is what API are you using? I am assuming you are doing some shopping cart stuff? IS this like a shopify Call or some other products API or is the API you refer to backbone.js – Frank Tudor Mar 29 '14 at 03:25
  • Hi :) Thanks for answer. No, it's a pretty simple API self-made in Python (with flask). It's for a School practice actually. The API responds well - like : _{ username:"exemple", password:"*****", mail:"exemple@exemple.com" .... }_. Nothing special is done on the server-side, pretty simple. – gjdass Mar 29 '14 at 03:49

3 Answers3

1

Does it behave any differently if you remove the default value of user_id? I wonder if it's fetching the relation and then applying the default value of null.

You might also try setting Backbone.Relational.showWarnings to true if it isn't already, and check your console for any warnings.

Peter G
  • 1,613
  • 10
  • 10
  • Hi :) The warnings was already enabled, no warning on the page. I removed user_id from my defaults array, but user_id is still NULL after the fetching is done. I really don't understand this bug ... [Here a console result image](http://goo.gl/K0iwno) and a [Second image](http://goo.gl/adTjX9) showing User are well requested and sent by the API. – gjdass Mar 31 '14 at 21:41
  • Do you see the same behavior when `autoFetch` is `false`? – Peter G Mar 31 '14 at 22:35
  • Exactly the same yeah. It means it's not the autoFetch who sets the field at NULL after fetching the User. I'm going crazy xD – gjdass Mar 31 '14 at 23:25
0

Give this a shot:

    relations: [{
        type: Backbone.HasOne,
        key: 'id',
        keyDestination: 'user_id',
        includeInJSON: 'user_id',
        autoFetch: true,
        relatedModel: User
    }]

I couldn't make heads or tails of the backbone-relational documentation. Apparently key is supposed to reference the id of the related model, but it doesn't seem to do that in any of their examples. I wonder if their examples actually work? Anyway, I think this fixes your issue: setting key to the key from the related model and setting keyDestination and includeInJSON so it knows how to set and serialize the result into the product object.

Peter G
  • 1,613
  • 10
  • 10
  • Hi ! I tested this here : http://jsfiddle.net/gjdass/WNWrm/19/. It appears that in the global JSON of my Product Object, `user_id` is still `null`. But when i'm doing a `pruduct.get('user_id')`, it displays the id ..... I don't understand, it's the same object !! Anyway, even the number id is false cause Relational has to put the entire object `User` in this field, not just the id. I don't understand, and like you said, there doc is not right ... – gjdass Apr 05 '14 at 18:30
0

So if you look at the backbone relational documentation closely, you'll notice none of the examples they give are HasOne with a reverseRelation of HasMany. As such, it seems that functionality is untested (except by you!) and non-functioning. Try the relationship the other way:

var User = Backbone.RelationalModel.extend(
{

    urlRoot: 'http://noraj.fr:5000/users',
    defaults: {
        id: '',
        name: '',
        email: '',
        firstname: '',
        lastname: '',
        password: '',
        card_nb: '',
        cart_total: ''
    },

    relations: [{
        type: Backbone.HasMany,
        key: 'products',
        relatedModel: 'Product',
        reverseRelation: {
            key: 'id',
            keySource: 'user_id',
            keyDestination: 'user_id',
            includeInJSON: true
        }            
    }]            
});
// Product Model
var Product = Backbone.RelationalModel.extend(
{

    urlRoot: 'http://noraj.fr:5000/products',
    defaults: {
        id: '',
        name: '',
        description: '',
        current_price: '',
        categories: '',
        duration: '',
        shipping_cost: '',
        start_date: '',
        is_buy_it_now: '',
        user_id: null
    }        
});
Peter G
  • 1,613
  • 10
  • 10
  • Hi. There is something i don't understand here. The relation is reversed, I'm ok with that, but when I want to display a product list to my client, with this code, i have to ask users instead of products. It's not logic is it ? If i want to display a product list, I'm supposed to call `http://noraj.fr:5000/products`, not `/users`. Or I don't understand something here (it's possible :P ). I tested this on JSFiddle. The fact is that when i call `http://noraj.fr:5000/products` to get my products, the `/users` API is not called anymore. The `user_id` is a number, but there is no fetch done. – gjdass Apr 06 '14 at 22:53