Skip to content

Commit 4a6937f

Browse files
committed
Merge pull request #39 from pschlette/save-resolves-when-all-dependents-resolve
JJModels now return a Deferred object that resolves when every dependent...
2 parents 4ab0382 + 44916c4 commit 4a6937f

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)