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

autoFetch does't work when cache is true for a model #339

Closed
mkMoSs opened this issue Sep 16, 2013 · 7 comments
Closed

autoFetch does't work when cache is true for a model #339

mkMoSs opened this issue Sep 16, 2013 · 7 comments

Comments

@mkMoSs
Copy link

mkMoSs commented Sep 16, 2013

var Reward = db.define('reward', {
        description: { type: 'text'},
        value: { type: 'money'}
    },
    { autoSave: true, autoFetch: true, autoFetchLimit: 3 }
);
var RewardType = db.define('rewardtype', {
        title: { type: 'text', size: 100}
    },
    { autoSave: true }
);

Reward.hasOne('type', RewardType, {reverse: 'rewards' });

In this example Reward has one to many relationships with RewardType when cache is left default (true) Reward.get(...) returns undefined for property "type" while type_id has a value.

When setting cache: false to both models, the 'type' property gets populated as expected using autofetch.

Is this a bug or is it normal behaviour? Spend hours trying to figure why autoFetch wasn't working...

@dresende
Copy link
Owner

cache is something hard to do in this situations, but we still have some work to do on this. What cache means on ORM is Singleton pattern, meaning: when fetching a record that was previously fetched (it uses table+ids to know that), return the same JS object instance.

This behaviour is seen when you fetch the same record more than one time and keep references to them. They will be the same JS object which means that if you change a property, all references change (because they are one).

On associations this is still not working properly. The code is somehow "caching" certain records when it doesn't have all data and then when you look for the record (using .find()) it uses the bad cached item. We have to track and solve this.

@mkMoSs
Copy link
Author

mkMoSs commented Sep 16, 2013

To give more details on how it happens here's the full code

db.defineType('money', { datastoreType: function(prop) { return 'decimal(19,2)' }}); //mysql specific

var Achievement = db.define('achievement', {
        title: { type: 'text', size: 100},
        description: { type: 'text'},
        isLocked: { type: 'boolean', defaultValue: false},
        isCompleted: { type: 'boolean', defaultValue: false}
    },
    { autoSave: true, autoFetch: true, autoFetchLimit: 3 } 
);
var Reward = db.define('reward', {
        description: { type: 'text'},
        value: { type: 'money'}
    },
    { autoSave: true, autoFetch: true, autoFetchLimit: 3 }
);
var RewardType = db.define('rewardtype', {
        title: { type: 'text', size: 100}
    },
    { autoSave: true }
);

Reward.hasOne('type', RewardType, {reverse: 'rewards' });
Achievement.hasMany('rewards', Reward);

db.on("connect", function(err) {
    if(err) { console.log("DB connect error:", err); }
    console.log("DB Connected!");

    db.drop(function() {
        db.sync(function() {
            RewardType.create([{title: 'xp'}, {title: 'balance'},{title: 'unlock'}], function(){
                Reward.create({description: '+100', value: 100}, function(){
                    Achievement.create({ title: 'First Steps', description: 'Blah blah'},function(err, ac){
                        Reward.get(1, function(err, reward) {
                            RewardType.get(1, function(err, rewType) {
                                reward.setType(rewType, function(err){
                                    Reward.get(1, function(err, nw){
                                        console.log(nw);
                                    });
                                });
                            });

                            ac.setRewards([ac]);
                        });
                    });
                });
            });
        });

    });
});

As you might notice, I drop everything and recreate them again initially.
Outputting to console the fetched reward in the end gives:

DB Connected!
{ description: [Getter/Setter],
  value: [Getter/Setter],
  id: [Getter/Setter],
  type_id: [Getter/Setter],
  type: undefined }

type is undefined which is the problem. After turning off cache in the models:

DB Connected!
{ description: [Getter/Setter],
  value: [Getter/Setter],
  id: [Getter/Setter],
  type_id: [Getter/Setter],
  type: { title: [Getter/Setter], id: [Getter/Setter] } }

works as expected

@mkMoSs
Copy link
Author

mkMoSs commented Sep 16, 2013

I would suggest, until you are able to resolve the problem with caching and associations, to have cache: false by default as opposed being true that it is now.
It would save people from a lot of confusion (on why autoFetch doesn't work primarily)

@dresende
Copy link
Owner

I don't want to change the default behaviour for now. I think I found the problem behind this. I'm fixing this for each association type.

@dresende
Copy link
Owner

If it doesn't work (the latest commit), please reopen.

@twk-b
Copy link

twk-b commented Sep 22, 2014

Seems like this is related to #490. I have this problem in versions 2.1.13 to 2.1.19. I have played around with caching settings, but after reading a variety of tickets I will try looking into that deeper today.

@iceNuts
Copy link

iceNuts commented Oct 25, 2015

Hi there,

I am wondering what is the best solution yet, I have the same problem and it has been a year, hope there is some official way to do this.

Thanks.

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

No branches or pull requests

4 participants