Skip to content

Commit

Permalink
Added Model.insert
Browse files Browse the repository at this point in the history
  • Loading branch information
assaf committed Nov 28, 2011
1 parent 0bfdc56 commit 1ec437b
Show file tree
Hide file tree
Showing 3 changed files with 182 additions and 6 deletions.
15 changes: 9 additions & 6 deletions lib/poutine/collection.coffee
Expand Up @@ -203,19 +203,22 @@ class Collection
# posts = connect().find("posts")
# posts.insert title: "New and exciting", (error, post)->
# console.log "Inserted #{post._id}"
insert: (document, options, callback)->
insert: (objects, options, callback)->
if !callback && typeof options == "function"
[options, callback] = [null, options]
multi = Array.isArray(objects)
objects = [objects] unless multi
documents = ((if Model.isModel(object) then object._ else object) for object in objects)
@_connect (error, collection, database)=>
return callback error if error
if callback
collection.insert document, options, (error, results)->
if Array.isArray(document)
callback error, results
collection.insert documents, options, (error, results)->
if multi
callback error, objects
else
callback error, results[0]
callback error, objects[0]
else
collection.insert document, options
collection.insert documents, options


# -- Implementation details --
Expand Down
17 changes: 17 additions & 0 deletions lib/poutine/model.coffee
Expand Up @@ -21,6 +21,12 @@ connect = require("./connect").connect
# User.where(name: "Assaf").one (error, user)->
# console.log "Loaded #{user.name}"
class Model
# Default constructor assigns defined fields from any object you pass, e.g.
# new User(name: "Assaf")
constructor: (document)->
if document
for name of @constructor.fields
@[name] = document[name]

# -- Schema --

Expand Down Expand Up @@ -96,6 +102,11 @@ class Model
assert setter, "Missing setter function"
@prototype.__defineSetter__ name, setter

# Returns true if we think the object is an instance of a model
@isModel: (instance)->
model = instance.constructor
return model.collection_name && model.fields


# -- Finders --

Expand Down Expand Up @@ -148,6 +159,12 @@ class Model
@lifecycle.addHook this, "afterLoad", hook


# -- Insert/update/remove --

@insert: (document, callback)->
connect().collection(this).insert document, callback


# Poutine uses these lifecycle methods to perform operations on models, but keeps them separate so we don't pollute the
# Model prototype with methods that are never used directly by actual model classes. Inheriting from a class that has
# hundreds of implementation methods is an anti-pattern we dislike.
Expand Down
156 changes: 156 additions & 0 deletions spec/model/insert_spec.coffee
@@ -0,0 +1,156 @@
{ assert, vows, connect, setup, Model } = require("../helpers")


class Post extends Model
@collection "posts"

@field "title", String
@field "author_id"
@field "category", String
@field "created_at", Date


vows.describe("Model insert").addBatch

# -- Model.insert --

"Model.insert":
topic: ->
setup @callback

"POJO":
"single":
"no callback":
topic: ->
result = Post.insert(title: "Insert 3.1")
return result || "nothing"
"should return nothing": (result)->
assert.equal result, "nothing"
"new document":
topic: ->
Post.find title: "Insert 3.1", @callback
"should exist in database": (posts)->
assert.equal posts[0].title, "Insert 3.1"

"with callback":
topic: ->
Post.insert title: "Insert 3.2", @callback
"should pass document to callback": (post)->
assert.equal post.title, "Insert 3.2"
"should pass a POJO to callback": (post)->
assert !(post instanceof Post)
"should set document ID": (post)->
assert post._id
"new document":
topic: (post)->
Post.find post._id, @callback
"should exist in database": (post)->
assert.equal post.title, "Insert 3.2"

"multiple":
"no callback":
topic: ->
result = Post.insert([{ title: "Insert 3.3", category: "foo" }, { title: "Insert 3.3", category: "bar" }])
return result || "nothing"
"should return nothing": (result)->
assert.equal result, "nothing"
"new documents":
topic: ->
Post.find title: "Insert 3.3", @callback
"should exist in database": (posts)->
assert.lengthOf posts, 2
categories = (post.category for post in posts).join(" ")
assert.equal categories, "foo bar"

"with callback":
topic: ->
Post.insert [{ title: "Insert 3.4", category: "foo" }, { title: "Insert 3.4", category: "bar" }], @callback
"should pass documents to callback": (posts)->
for post in posts
assert.equal post.title, "Insert 3.4"
"should pass POJOs to callback": (posts)->
for post in posts
assert !(post instanceof Post)
"should set document ID": (posts)->
for post in posts
assert post._id
"new documents":
topic: (posts)->
ids = (post._id for post in posts)
Post.find ids, @callback
"should exist in database": (posts)->
assert.lengthOf posts, 2
categories = (post.category for post in posts).join(" ")
assert.equal categories, "foo bar"


"Model":
"no callback":
topic: ->
post = new Post(title: "Insert 3.5")
result = Post.insert(post)
return result || "nothing"
"should return nothing": (result)->
assert.equal result, "nothing"
"new document":
topic: ->
Post.find title: "Insert 3.5", @callback
"should exist in database": (posts)->
assert.equal posts[0].title, "Insert 3.5"

"with callback":
topic: (post)->
post = new Post(title: "Insert 3.6")
Post.insert post, @callback
"should pass document to callback": (post)->
assert.equal post.title, "Insert 3.6"
"should pass a model to callback": (post)->
assert.instanceOf post, Post
"should set document ID": (post)->
assert post._id
"new document":
topic: (post)->
Post.find post._id, @callback
"should exist in database": (post)->
assert.equal post.title, "Insert 3.6"

"multiple":
"no callback":
topic: ->
posts = [new Post( title: "Insert 3.7", category: "foo" ), new Post( title: "Insert 3.7", category: "bar" )]
result = Post.insert(posts)
return result || "nothing"
"should return nothing": (result)->
assert.equal result, "nothing"
"new documents":
topic: ->
Post.find title: "Insert 3.7", @callback
"should exist in database": (posts)->
assert.lengthOf posts, 2
categories = (post.category for post in posts).join(" ")
assert.equal categories, "foo bar"

"with callback":
topic: ->
posts = [new Post( title: "Insert 3.8", category: "foo" ), new Post( title: "Insert 3.8", category: "bar" )]
Post.insert posts, @callback
"should pass documents to callback": (posts)->
for post in posts
assert.equal post.title, "Insert 3.8"
"should pass models to callback": (posts)->
for post in posts
assert.instanceOf post, Post
"should set document ID": (posts)->
for post in posts
assert post._id
"new documents":
topic: (posts)->
ids = (post._id for post in posts)
Post.find ids, @callback
"should exist in database": (posts)->
assert.lengthOf posts, 2
categories = (post.category for post in posts).join(" ")
assert.equal categories, "foo bar"


.export(module)

0 comments on commit 1ec437b

Please sign in to comment.