diff --git a/addon/orm/schema.js b/addon/orm/schema.js index aaaaf82e1..8b3a5e26b 100644 --- a/addon/orm/schema.js +++ b/addon/orm/schema.js @@ -133,6 +133,7 @@ export default class Schema { all: (attrs) => this.all(camelizedModelName, attrs), find: (attrs) => this.find(camelizedModelName, attrs), findBy: (attrs) => this.findBy(camelizedModelName, attrs), + findOrCreateBy: (attrs) => this.findOrCreateBy(camelizedModelName, attrs), where: (attrs) => this.where(camelizedModelName, attrs), none: (attrs) => this.none(camelizedModelName, attrs), first: (attrs) => this.first(camelizedModelName, attrs) @@ -246,7 +247,7 @@ export default class Schema { } /** - Returns the first model in the database that matches the key-value pairs in the `query` object. Note that a string comparison is used. + Returns the first model in the database that matches the key-value pairs in `attrs`. Note that a string comparison is used. ```js let post = blogPosts.findBy({ published: true }); @@ -261,9 +262,36 @@ export default class Schema { */ findBy(type, query) { let collection = this._collectionForType(type); - let records = collection.findBy(query); + let record = collection.findBy(query); - return this._hydrate(records, dasherize(type)); + return this._hydrate(record, dasherize(type)); + } + + /** + Returns the first model in the database that matches the key-value pairs in `attrs`, or creates a record with the attributes if one is not found. + + ```js + // Find the first published blog post, or create a new one. + let post = blogPosts.findBy({ published: true }); + ``` + + @method findOrCreateBy + @param type + @param attributeName + @public + */ + findOrCreateBy(type, attrs) { + let collection = this._collectionForType(type); + let record = collection.findBy(attrs); + let model; + + if (!record) { + model = this.create(type, attrs); + } else { + model = this._hydrate(record, dasherize(type)); + } + + return model; } /** @@ -300,7 +328,7 @@ export default class Schema { */ first(type) { let collection = this._collectionForType(type); - let [record] = collection; + let record = collection[0]; return this._hydrate(record, dasherize(type)); } diff --git a/tests/integration/orm/find-or-create-by-test.js b/tests/integration/orm/find-or-create-by-test.js new file mode 100644 index 000000000..6658f87b7 --- /dev/null +++ b/tests/integration/orm/find-or-create-by-test.js @@ -0,0 +1,55 @@ +import Schema from 'ember-cli-mirage/orm/schema'; +import Model from 'ember-cli-mirage/orm/model'; +import Db from 'ember-cli-mirage/db'; +import {module, test} from 'qunit'; + +module('Integration | ORM | #findOrCreateBy', function(hooks) { + hooks.beforeEach(function() { + let db = new Db({ users: [ + { id: 1, name: 'Link', good: true }, + { id: 2, name: 'Zelda', good: true }, + { id: 3, name: 'Ganon', good: false } + ] }); + + this.User = Model.extend(); + + this.schema = new Schema(db, { + user: this.User + }); + }); + + test('it returns the first model that matches the attrs', function(assert) { + let user = this.schema.users.findOrCreateBy({ good: true }); + + assert.ok(user instanceof this.User); + assert.deepEqual(user.attrs, { id: '1', name: 'Link', good: true }); + }); + + test('it creates a model if no existing model with the attrs is found', function(assert) { + assert.equal(this.schema.db.users.length, 3); + + let newUser = this.schema.users.findOrCreateBy({ name: 'Link', good: false }); + + assert.equal(this.schema.db.users.length, 4); + assert.ok(newUser instanceof this.User); + assert.deepEqual(newUser.attrs, { id: '4', name: 'Link', good: false }); + }); + + // test('it returns models that match using a query function', function(assert) { + // let users = schema.users.where(function(rec) { + // return !rec.good; + // }); + // + // assert.ok(users instanceof Collection, 'it returns a collection'); + // assert.equal(users.models.length, 1); + // assert.ok(users.models[0] instanceof User); + // assert.deepEqual(users.models[0].attrs, { id: '3', name: 'Ganon', good: false }); + // }); + + // test('it returns an empty collection if no models match a query', function(assert) { + // let users = schema.users.where({ name: 'Link', good: false }); + // + // assert.ok(users instanceof Collection, 'it returns a collection'); + // assert.equal(users.models.length, 0); + // }); +});