Created
October 17, 2013 22:20
-
-
Save ollieglass/7033319 to your computer and use it in GitHub Desktop.
Bulk find or create with ember.js This would be simple to do synchronously (foreach... continue if exists). But working with the asynchronous store creates lots of overhead.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset=utf-8 /> | |
<title>JS Bin</title> | |
<script src="http://code.jquery.com/jquery-2.0.2.js"></script> | |
<script src="http://builds.emberjs.com/handlebars-1.0.0.js"></script> | |
<script src="http://builds.emberjs.com/ember-latest.js"></script> | |
<script src="http://builds.emberjs.com/beta/ember-data.js"></script> | |
<script src="https://rawgithub.com/rpflorence/ember-localstorage-adapter/master/localstorage_adapter.js"></script> | |
</head> | |
<body> | |
<script type="text/x-handlebars" data-template-name="application"> | |
<h1>ember-latest jsbin</h1> | |
{{outlet}} | |
</script> | |
<script type="text/x-handlebars" data-template-name="index"> | |
<h2>Index Content:</h2> | |
<ul> | |
{{#each weeks}} | |
<li>{{w.weekOfYear}}</li> | |
{{/each}} | |
</ul> | |
</script> | |
<script> | |
App = Ember.Application.create({}); | |
App.LSAdapter = DS.LSAdapter.extend({ | |
namespace: 'whitespace' | |
}); | |
App.Store = DS.Store.extend({ | |
adapter: App.LSAdapter | |
}); | |
App.Fruit = DS.Model.extend({ | |
name: DS.attr("string") | |
}); | |
App.IndexRoute = Ember.Route.extend({ | |
createIfNotExistTaskCounter: 0, // store number of items waiting to be processed | |
createIfNotExistQueue: [], // store a list of the items being added, to prevent duplicate adds | |
setupController: function(controller) { | |
/* This is a simplified version of a real task I'm trying to acomplish. The code adds a list of objects to the store, only creating them if they don't exist. After the list has been processed, the contents of the store are shown. | |
To achieve this end I've used a counter and a queue to keep track of the operations' state. Is there a simpler way to do this? These overheads seem excessive for such a straightforward bulk insert operation. | |
*/ | |
var fruitToStore = ["apple", "pear", "banana", "apple"], | |
store = this.get('store'); | |
this.set('createIfNotExistTaskCounter', fruitToStore.length); | |
for(var i=0; i<fruitToStore.length; i++) { | |
this.createIfNotExist(fruitToStore[i]); | |
} | |
}, | |
createListener: function() { | |
if(this.get('createIfNotExistTaskCounter') !== 0) return; | |
this.get('store').find('fruit').then(function(results) { | |
// should only print three fruits, one of each type | |
for (var i = 0; i < results.content.length; i++) { | |
console.log(results.content[i].get('name')); | |
}; | |
}); | |
}.observes('createIfNotExistTaskCounter'), | |
createIfNotExist: function(f) { | |
var store = this.get('store'), | |
queue = this.get('createIfNotExistQueue'), | |
that = this; | |
// prevent duplicate records being created by adding every (distinct) item to a queue | |
// the queue is used because there seems to be no way to tell if an item is already (asynchonously) being found / created / saved | |
if(queue.indexOf(f) !== -1) { | |
that.decrementProperty('createIfNotExistTaskCounter'); | |
return; | |
} | |
queue.push(f); | |
// find or create | |
store.find('fruit', {name: f}).then(function(results) { | |
// found... | |
if(results.get('length') !== 0) { | |
that.decrementProperty('createIfNotExistTaskCounter'); | |
return; | |
} | |
// ...else create | |
var fruit = store.createRecord('fruit', {name: f}); | |
fruit.save().then(function() { | |
that.decrementProperty('createIfNotExistTaskCounter'); | |
}, function() { | |
console.log("save failed!"); | |
}); | |
}); | |
} | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment