2

We're using Ember.Data rev 11. Our relationships are like so:

Social.Account = DS.Model.extend({
    name: DS.attr("string"),
    username: DS.attr("string"),
    messages: DS.hasMany("Social.Message"),
});

Social.Message = DS.Model.extend({
    text: DS.attr("string"),
    created: DS.attr("date"),
    account: DS.belongsTo("Social.Account"),
    posts: DS.hasMany("Social.Post")
});

Social.Post = DS.Model.extend({
    text: DS.attr("string"),
    created: DS.attr("date"),
    message: DS.belongsTo("Social.Message"),
});

A user creates a Message which can then be sent to multiple social media accounts, each of which results in a Post. On submit a Message and Post record are created, but we information in the Post record that we get back from Twitter. The code we're currently using looks like this:

saveMessage: function(text){
    var acct = Social.Account.find(this.get("id")),
        msg = Social.store.createRecord(
                    Social.Message,
                    {
                        text: text,
                        account: acct,
                        created: new Date()
                    }
                );

    acct.get("messages").addObject(msg);
    Social.store.commit();

    msg.addObserver('id', this, function(){
        var timeoutID = window.setTimeout(function(){
            msg.reload();
            console.log('reloading');
        }, 5000);
    });

}

As soon as I hit submit the Message and Post both load in the UI. Problem is that the Post is missing he native_url property, which can only be gotten after the http request to Twitter is made. The weird thing is that if I replace the contents of the addObserver call with an alert window, the native_url value pops into place. I'mt not sure why but it does.

Anyway, so my question is what do I have to do to get the Post object to update with data from the server, AND update the UI with that new data.

MilkyWayJoe
  • 9,082
  • 2
  • 38
  • 53
commadelimited
  • 5,656
  • 6
  • 41
  • 77
  • In the alert that you mentioned, what are you alerting anything related to your object or random text? and does it happen *every* time you call `alert`? – MilkyWayJoe Mar 05 '13 at 23:55
  • Just did alert('42'). And yes, everytime the alert fires, the text shows up as updated. But when the alert is commented out, or a put a console.log statement in there nothing happens. – commadelimited Mar 06 '13 at 14:55
  • Just tested it out again. This time I commented out the `msg.addObserver` method and replaced it with an alert. When I added a message and hit submit the message showed up with the information from Twitter displayed. When I commented out the alert the information from Twitter was not there. – commadelimited Mar 06 '13 at 14:59
  • I haven't seen this before. It seems like the observer goes to sleep then wakes up when there's a blocking event – MilkyWayJoe Mar 06 '13 at 15:26
  • Bug you think? 5 seconds of setTimeout is pretty high when I know the data comes back within a second because of the alert. – commadelimited Mar 06 '13 at 15:29
  • I can't really tell, but it could be a bug – MilkyWayJoe Mar 06 '13 at 15:32

1 Answers1

2

I can't guarantee that this is the solution without seeing all of you code. But one thing you should do is not rely on setTimeout for Ember callbacks. Instead, use Ember.run.later.

Ember.run.later(this, function() {
    this.reload();
    console.log('reloading');
}, 5000);

Anything that happens asynchronously outside of Ember should be wrapped in a RunLoop. So, in the event that your callback is part of a plugin or something else along those lines, you can also wrap it all in Ember.run.

Peter Wagenet
  • 4,976
  • 22
  • 26
  • Actually I just checked the Network panel in Dev Tools. When `this.reload()` fires it makes a call to update the Message object, but the content I need is located on the Post object. Given the msg object in my post, how would I tell Ember to update the Post object located within the Message object? – commadelimited Mar 07 '13 at 23:06
  • 1
    It looks like message has many posts so you'd either have to find a way to only reload the specific post or you'd have to reload all of them, i.e. `msg.get('posts').forEach(function(p){ p.reload(); })`. – Peter Wagenet Mar 07 '13 at 23:14
  • Ill bet that will do it. Even though the actual relationship is many, in this instance there wi only be one post per message. Ill test it out tomorrow morning and let you know. – commadelimited Mar 07 '13 at 23:31
  • And that did it Peter. SO won't seem to let me give you the bounty but as soon as I can do it, it's yours. – commadelimited Mar 08 '13 at 14:39
  • Note that unless you're using Ember master that's less than a week old, you'll still want to wrap your `Ember.run.later` callback instead `Ember.run`; before this recent change, there was no guarantee that `Ember.run.later` callbacks would run within a run loop. – Alexander Wallace Matchneer Mar 08 '13 at 20:02