Skip to content

Commit 44916c4

Browse files
author
Pete Schlette
committed
JJModels now return a Deferred object that resolves when every dependent model has finished saving (instead of when the first model finishes saving). Update README with information about dependency on jQuery and changes to save().
1 parent 4ab0382 commit 44916c4

File tree

4 files changed

+48
-27
lines changed

4 files changed

+48
-27
lines changed

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,11 @@ Backbone JJRelational has been tested with Backbone 1.0.0 and Underscore 1.5.0
3838
<a name="installation" />
3939
## Installation
4040

41-
Backbone JJRelational depends - who would have thought - on [Backbone.JS](https://github.com/documentcloud/backbone) and [Underscore.JS](https://github.com/documentcloud/underscore).
42-
Simply include backbone.JJRelational.js right after Underscore and Backbone.
41+
Backbone JJRelational depends - who would have thought - on [Backbone.JS](https://github.com/documentcloud/backbone), [Underscore.JS](https://github.com/documentcloud/underscore) and [jQuery](https://github.com/jquery/jquery).
42+
Simply include backbone.JJRelational.js right after jQuery, Underscore and Backbone.
4343

4444
```html
45+
<script type="text/javascript" src="jquery.js"></script>
4546
<script type="text/javascript" src="underscore.js"></script>
4647
<script type="text/javascript" src="backbone.js"></script>
4748
<script type="text/javascript" src="backbone.JJRelational.js"></script>
@@ -313,6 +314,8 @@ When you call `save` on a `Backbone.JJRelationalModel`, it will walk through tha
313314

314315
Assume that a Store `has_many` Products, and Product `has_one` Store. You call `store.save()` ... So the Store will save itself first. After this completes, the Product's `save` will be called.
315316

317+
The Deferred object returned by `save` won't be resolved until all of the model's dependent models have finished saving too.
318+
316319
It should be noted that these related models will only be saved before/after if the model `isNew()`. If these are existing models, then you should save them each yourself individually.
317320

318321
You should also be aware that `save` will inevitably call `set()` on the response returned from the server, and so the usual backbone set options apply. Please read the backbone docs on how to use the `add`, `remove`, and `merge` options. In some cases, you'll probably want to pass these to `save`, which will in turn pass them through to `set`.

backbone.JJRelational.coffee

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -347,16 +347,26 @@ do () ->
347347

348348
if options.parse is undefined then options.parse = true
349349

350+
# Set up chain of deferreds to save each 'after' model.
351+
# If we encounter a model that's not new, we'll simply return a Deferred that's already resolved as a sort of no-op.
352+
# afterSuccess is resolved in the success handler of the model to kick off this process.
353+
afterSuccess = new Backbone.$.Deferred();
354+
355+
latestSuccess = afterSuccess;
356+
generateSuccessHandler = (model) =>
357+
() =>
358+
if model.isNew()
359+
return model.save({}, _.extend({}, origOptions))
360+
else
361+
d = new Backbone.$.Deferred()
362+
d.resolve()
363+
return d
364+
365+
for relModel in relModelsToSaveAfter
366+
latestSuccess = latestSuccess.then generateSuccessHandler(relModel)
367+
350368
options.success = (resp, status, xhr) =>
351-
# we're in the actualSave success function, so now let's invoke a save on our "after" models
352-
# the success callback we're going to pass is this function, so the next model in the relModelsToSaveAfter list
353-
# won't be saved until the previous model has finished saving itself and all of its before/after dependencies
354-
# we could probably analyze this dependency graph more to be more performant...maybe someday.
355-
saveRelModelsAfterSuccess = =>
356-
if relModelsToSaveAfter.length > 0
357-
relModel = relModelsToSaveAfter.shift()
358-
if relModel.isNew() then relModel.save({}, _.extend({}, origOptions, {success: saveRelModelsAfterSuccess}))
359-
saveRelModelsAfterSuccess()
369+
afterSuccess.resolve()
360370

361371
# Ensure attribtues are restored during synchronous saves
362372
@attributes = attributes
@@ -379,7 +389,8 @@ do () ->
379389
# Restore attributes
380390
if attrs and options.wait then @.attributes = attributes
381391

382-
xhr
392+
# Yield a Deferred that will be resolved when every model has been updated
393+
latestSuccess
383394

384395
# Okay, so here's actually happening it. When we're saving - and a model in a relation is not yet saved
385396
# we have to save the related model first. Only then can we save our actual model.

backbone.JJRelational.js

Lines changed: 21 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

backbone.JJRelational.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)