Skip to content

Eager-load with a parent-child model associations? #546

Closed
JohnPostlethwait opened this Issue Feb 12, 2014 · 9 comments

3 participants

@JohnPostlethwait

I have a case where I have a model, and this model can be the "parent" of other items of that same model. (Categories and sub-categories) I want to eager-load these subcategories when I load the initial categories. I cannot seem to figure out how to make this work though...

Here is the model definition I have mostly got working:

var Category = function () {
    this.property('name', 'string', { required: true });
    this.property('description', 'text');
    this.property('category_id', 'int');

    this.belongsTo('Category');
    this.hasMany('Categories');
};

When I try and use it like this, though, I never have the categories pre-loaded:

geddy.model.Category.all({}, { includes: ['categories'] }, function (err, categories) {
    if (err) throw err;

    categories.forEach(function (category) {
        console.log(category.categories); // undefined

        category.getCategories(function (err, subcategories) {
            console.log(subcategories); // This gives me what I want...
        });
    });

I'm not sure what the correct way to eager-load a self-association is?

@mde
mde commented Feb 12, 2014

This is what we've been calling "reflexive" associations, done using a named through-association There are some examples in the tests:

https://github.com/geddy/model/blob/master/test/integration/adapters/shared.js#L926
https://github.com/geddy/model/blob/master/test/integration/adapters/sql/eager_assn.js#L149

Hope that helps.

@JohnPostlethwait

Fantastic - thanks a ton!

@JohnPostlethwait

So, after playing with this and looking at the examples, it seems those work because there is a model they can be joined through. I can't seem to make the through association go through itself, I am always getting: Error: No inverse found for this through-association.

Any way to do this without porting my data to a join table? (I'm working off of a really old Rails database where this worked in ActiveRecord.)

@mde
mde commented Feb 13, 2014

If it's many-to-many, it has to have a of join model. Or are you saying this is many-to-one?

@JohnPostlethwait

It's a many-to-one. A category can only "belongTo" one parent category, thus making it a sub-category of that parent.

@mde
mde commented Feb 13, 2014

We used to have a test for that, but it looks like it got lost in a large refactor. I've added one for this:

geddy/model@f745064

The only thing is that right now there's no way to specify the inverse 'belongsTo' for a 'hasMany'/'hasOne' (or vice versa). Our code does try to figure out an inverse when it can by looking at the model used in the association, but this means it doesn't work with named associations, which you pretty much have to use with reflexives.

Specifying the inverses is a feature that will probably be worked on for the next release. If you'd like to take a stab at it, I'll be happy to help.

@xreader
xreader commented Feb 14, 2014

Is there an example for reflexive associations similar to this https://github.com/geddy/model/blob/master/test/integration/adapters/shared.js#L926 but with child to parent associations? Child can have one parent and parent can have many children?
Update: i don't saw last comment

@mde
mde commented Feb 15, 2014

Let me know is this works out for you.

@JohnPostlethwait

This works for me!

I poked around the association code for how I might be able to implement the inverse lookup, but didn't get much further than simply reading how it all worked. I'll let you know if I have any questions when I have more time to look at it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.