Skip to content

Instantly share code, notes, and snippets.

@ollieglass
Created October 17, 2013 22:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ollieglass/7033319 to your computer and use it in GitHub Desktop.
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.
<!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