RelationalModel relation field at NULL after job's done
Asked Answered
K

3

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.

Keneth answered 29/3, 2014 at 2:37 Comment(2)
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.jsStoneware
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:"[email protected]" .... }. Nothing special is done on the server-side, pretty simple.Keneth
P
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.

Proven answered 29/3, 2014 at 23:49 Comment(3)
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 and a Second image showing User are well requested and sent by the API.Keneth
Do you see the same behavior when autoFetch is false?Proven
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 xDKeneth
P
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.

Proven answered 5/4, 2014 at 15:46 Comment(1)
Hi ! I tested this here : 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 ...Keneth
P
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
    }        
});
Proven answered 6/4, 2014 at 15:43 Comment(1)
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.Keneth

© 2022 - 2024 — McMap. All rights reserved.