Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Experimenting #20

Closed
pgherveou opened this issue Aug 15, 2011 · 8 comments
Closed

Experimenting #20

pgherveou opened this issue Aug 15, 2011 · 8 comments

Comments

@pgherveou
Copy link
Contributor

Hi I am experimenting on backbone relational, (looks great !)
I create the following in console

var Membership = Backbone.RelationalModel.extend({
    urlRoot: '/membership',
});

var User = Backbone.RelationalModel.extend({
    urlRoot: '/user',
    relations: [
        {
            type: Backbone.HasMany,
            key: 'memberships',
            relatedModel: 'Membership',
            collectionType: 'MembershipCollection',
            reverseRelation: {
                key: 'user'
            }
        }
    ]
});

var UserCollection = Backbone.Collection.extend({model:User});
var MembershipCollection = Backbone.Collection.extend({model:Membership});

// create a membership from a json hash
member = new Membership({
                "id": 4,
                "user": {
                    "id": 7,
                    "username": "paul",
                    "email": "paul@mail.com"
                }
            })

If I type member.get('user') it returns me the user object, I was expecting to receive a Model instance of it
Can you let me know what's wrong with this piece of code ?

Thks

@pgherveou
Copy link
Contributor Author

Actually it works if I reverse the relation writting a hasOne on Membership, but is there a way to make it work both side ?

@PaulUithol
Copy link
Owner

Yeah, you've stumbled over one nasty issue that I don't know how to solve (not sure it can be solved actually..).

If you define relations on a model (like you do on User), but don't actually create an instance of that model, the model's constructor function will never run, so initializeRelations will never get called, and the reverseRelation will never be set on Membership.

You can solve this by either creating a dummy user (new User()), or defining the complete relation (including the reverseRelation) on Membership.

Might be something to include as a warning in the docs..

@pgherveou
Copy link
Contributor Author

I have to dig into your code to get a better understanding of the relation binding,
but one stupid question why can't it be initialized from the User constructor ?

It works writing the relation the other way, I also had a many to many relationship I build with two hasOne to get this working, it does not do any harm does it? You are right I think it worth adding this tips to the doc

Thks for this excellent plugin anyway !

@PaulUithol
Copy link
Owner

It is. But if you never actually create a user (by calling new User()), the User constructor will never run.

@edwardmsmith
Copy link

I'm not sure if its intended process, but I've worked around this issue by not using reverseRelation at all, and defining each side of the relation in each model:

var Membership = Backbone.RelationalModel.extend({
    urlRoot: '/membership',
    relations: [
      {
        type: Backbone.HasOne,
        key: 'user',
        relatedModel: 'User'
      }
    ]
});

var User = Backbone.RelationalModel.extend({
    urlRoot: '/user',
    relations: [
      {
        type: Backbone.HasMany,
        key: 'memberships',
        relatedModel: 'Membership',
        collectionType: 'MembershipCollection',
      }
    ]
});

This seems to have cleaned up this problem for me - and it feels a little more elegant as well.

Using "reverseRelation" on both sides got me a bunch of warnings that relationships had already been defined.

Although, just bootstrapping up an instance of each model on app initialization, while a bit of a hack, isn't too onerous.

@PaulUithol
Copy link
Owner

Actually, I think that's actually the nicest & most reliable solution :)

@pgherveou
Copy link
Contributor Author

I just noticed that if you define relation as Edward suggest then in the above example
the relationship can't be access like that :

Backbone.Relational.store.find(User, 7).get("memberships").size() == 1 // return false

here is the full example runnable in console

window.Membership = Backbone.RelationalModel.extend({
    urlRoot: '/membership',
    relations: [
      {
        type: Backbone.HasOne,
        key: 'user',
        relatedModel: 'User'
      }
    ]
});

window.User = Backbone.RelationalModel.extend({
    urlRoot: '/user',
    relations: [
      {
        type: Backbone.HasMany,
        key: 'memberships',
        relatedModel: 'Membership',
        collectionType: 'MembershipCollection',
      }
    ]
});


window.UserCollection = Backbone.Collection.extend({model:User});
window.MembershipCollection = Backbone.Collection.extend({model:Membership});


window.member = new Membership({
                "id": 4,
                "user": {
                    "id": 7,
                    "username": "paul",
                    "email": "paul@mail.com"
                }
            })

console.log("memberships nb: " + Backbone.Relational.store.find(User, 7).get("memberships").size());

@PaulUithol
Copy link
Owner

Yeah, you're right; didn't realize that downside on time.

If you don't specify a reverseRelation, the relation can't know what attribute to monitor (and populate) on the opposing model; so in that case, you'll need to explicitly specify the other side of the relation, which kind of defeats the purpose.

Yet another option is to fully specify the relation + reverseRelation on both models; this way, they'll be set up the first time an instance of either of model is created. The downside to this is that you'll get a couple of warnings about duplicate relations being defined (and the code duplication of course).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants