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

Models that extend Spine.Ajax don't attempt to find out resource is available remotely before failing #37

Closed
csaunders opened this issue Jun 1, 2011 · 13 comments

Comments

@csaunders
Copy link
Contributor

There may be a situation where an API only returns a limited subset of all of it's data. Calling Model.find when the Model extends Spine.Ajax should see if the API has the resource before throwing the exception that the record doesn't exist.

@jasonroelofs
Copy link

To expand on this, there's no way to directly pull information for a specific object via Ajax.

If I want to do /resources/14 I found I have to do the following:

Spine.Ajax.ajaxSync(Resource.init({id: $("#access_hash").val()}), "read");

And I had to patch spine.ajax.js (adding method === "read"):

if (method === "create" || method === "update" || method === "read") {

Where "#access_hash" is a hidden field including the id of the object I'm trying to find, rendered to the page.

@fwielstra
Copy link

+1, I found it counter-intuitive to see Model.find() not working if it wasn't populated (and its implementation being a simple array lookup). It would be pleasant if this issue could be fixed, or instructions to how to get an ajax model to populate itself when you call find() with a specific ID.

Preferably sooner or later; we're trying to build a prototype of a neat application, and we'd have to switch to Backbone or some other JS library that does do this if I can't get it to work soon.

@csaunders
Copy link
Contributor Author

I had the same issue and implemented this, I just haven't taken the time to put it together (or test it enough). Hope it helps a bit:
https://gist.github.com/1031521

@maccman
Copy link
Member

maccman commented Jun 20, 2011

The trouble is, this goes against Spine's philosophy somewhat, in that you should have a non-blocking interface. i.e. you should load all data you'll need locally before accessing it. Additionally it shouldn't be assumed Ajax is being used, or even that data is remote. For now, I'd do something like this:

  Model.extend({
    findRemote: function(id, callback) {
      $.getJSON(this.url(id), function(res){
        callback(this.fromJSON(res))
      })
    }
  })

  Model.include({
    getStuff: function(cb){
      $.getJSON(this.url('stuff'), cb)
    }
  })

@maccman maccman closed this as completed Jun 20, 2011
@jasonroelofs
Copy link

While I agree with your statement, there is a bug in the library somewhere. It is currently impossible without hacking something to get the initial state of an existing model into Spine's memory store.

Even if you have all the information you need rendered to the page, you have to ensure Ajax is turned off on the Model before trying to load that information into javascript memory because otherwise spine.ajax.js will send a POST request to create a new resource with that information.

So you're stuck with either a hack like we've described above, or making sure that you explicitly do

function readyForAjax() {     
    Resource.extend(Spine.Model.Ajax);
}

and only calling that once you've loaded the information from the page and called either Resource.create() or Resource.save() to put the information in Spine's model memory and only there. Either way this feels like something Spine should be able to handle itself, and it's something every single real-world app will need to do.

@maccman
Copy link
Member

maccman commented Jun 20, 2011

Sorry, I'm being a bit slow. Can't you load records in using Model.fetch() ?

@csaunders
Copy link
Contributor Author

Fetching blows any data already in memory away.

@maccman maccman reopened this Jun 20, 2011
@maccman
Copy link
Member

maccman commented Jun 20, 2011

Ok, how about we make fetch() append data by default, with an optional option to do a full refresh?

@jasonroelofs
Copy link

In my situation I really can't render all the required information to the page and load from there. I give the page the basic information for accessing the parent object, then need to query the server for everything related to that object for rendering to the page. Once I get that information then I can initialize the app and go to work but this is where Spine / Ajax get in the way a little bit, because I need to make sure that as the data is loading, Spine.Ajax doesn't erroneously think this is a new model and queue up a POST Ajax request for that information I just loaded when I fill up Spine's model memory.

It feels to me, and it may be a lack of understanding on my part, that Spine supports creating a new resource really well, but editing an existing resource is lacking somewhat. I need to get the data of the existing resource from the server before the app can start/continue working.

@jasonroelofs
Copy link

Ok talking with Alex my issue was confusion and the sparse documentation of how to work with Spine.Ajax. With my urls set up right, and a bind on "refresh", Resource.fetch() will get the information I need and I'll know when it's loaded into memory.

@csaunders
Copy link
Contributor Author

The current way spine fetch works (as I understand it) is you can pass in a single variable, this being a callback or options. I was thinking that this option might end up overloading the fetch function too much.

So instead there could be a separate function or you can pass in a hash that could contain a callback and/or options. Personally I like having the hash or a multi-argument function instead of a new one.

So yeah, I think passing in an option as to whether you would like to append or replace the current data when fetching would be great.

@maccman
Copy link
Member

maccman commented Jul 17, 2011

replace() now takes an option to optionally blow away existing records. Also Spine.Ajax has be re-factored, which gives much more scope for custom calls and should address all the concerns above (see CS branch).

@maccman maccman closed this as completed Jul 17, 2011
@maca
Copy link
Contributor

maca commented Feb 23, 2012

doing Model.first().ajax().reload() and Model.fetch({id : 1}) seem perfectly allright to me :)

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

5 participants