Skip to content

Commit

Permalink
Add Table#create
Browse files Browse the repository at this point in the history
  • Loading branch information
maxbrunsfeld committed Dec 27, 2012
1 parent ee811e0 commit a4da850
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 18 deletions.
1 change: 1 addition & 0 deletions lib/server/index.coffee
Expand Up @@ -2,4 +2,5 @@ Monarch = require './core'
Monarch.Db = require "./db"
Monarch.resourceUrlSeparator = '_'
require('./relations/relation')(Monarch.Relations.Relation)
require('./relations/table')(Monarch.Relations.Table)
module.exports = Monarch
3 changes: 0 additions & 3 deletions lib/server/relations/relation.coffee
Expand Up @@ -11,9 +11,6 @@ module.exports = (Relation) ->
toSql: ->
(new SelectBuilder).visit(this).toSql()

toInsertSql: (args...) ->
(new InsertBuilder).visit(this, args...).toSql()

all: (f) ->
self = this
Connection.query @toSql(), (err, result) ->
Expand Down
13 changes: 13 additions & 0 deletions lib/server/relations/table.coffee
@@ -0,0 +1,13 @@
{ reopen } = require("../core").Util
InsertBuilder = require "../sql/insert_builder"
Connection = require "../db/connection"

module.exports = (Table) ->

reopen Table, ->
toInsertSql: (args...) ->
(new InsertBuilder).visit(this, args...).toSql()

create: (args..., f) ->
Connection.query(@toInsertSql(args...), f)

27 changes: 14 additions & 13 deletions lib/server/sql/insert_builder.coffee
Expand Up @@ -6,22 +6,23 @@ QueryBuilder = require "./query_builder"
module.exports = class InsertBuilder extends QueryBuilder
visit_Relations_Table: (table, hashes) ->
hashes = [hashes] unless _.isArray(hashes)
columnNames = _.keys(hashes[0])
columnNames = _.union((_.keys(hash) for hash in hashes)...)
valueLists = for hash in hashes
hash[columnName] for columnName in columnNames
for columnName in columnNames
hash[columnName] ? null

new Nodes.Insert(
@buildTable(table)
@buildColumns(columnNames),
@visitValueLists(valueLists))
buildTable(table)
buildColumns(columnNames),
visitValueLists.call(this, valueLists))

buildTable: (table) ->
new Nodes.Table(table.resourceName())
buildTable = (table) ->
new Nodes.Table(table.resourceName())

buildColumns: (columnNames) ->
for name in columnNames
new Nodes.InsertColumn(underscore(name))
buildColumns = (columnNames) ->
for name in columnNames
new Nodes.InsertColumn(underscore(name))

visitValueLists: (valueLists) ->
for list in valueLists
@visit(value) for value in list
visitValueLists = (valueLists) ->
for list in valueLists
@visit(value) for value in list
2 changes: 1 addition & 1 deletion lib/server/sql/nodes/insert.coffee
Expand Up @@ -17,7 +17,7 @@ module.exports = class Insert
lists = for valueList in @valueLists
sqlValueList = (@sqlize(value) for value in valueList)
parenthesizedList(sqlValueList)
lists.join(' ')
lists.join(', ')

sqlize: (value) ->
value
Expand Down
39 changes: 39 additions & 0 deletions spec/server/relations/table_spec.coffee
@@ -0,0 +1,39 @@
{ Monarch, async, pg } = require "../spec_helper"

describe "Relations.Table", ->
class Blog extends Monarch.Record
@extended(this)
@columns
public: 'boolean'
title: 'string'
authorId: 'integer'

blogs = Blog.table

beforeEach (done) ->
Monarch.Db.Connection.query("TRUNCATE TABLE blogs;", done)

describe "#create", ->
describe "when a single attribute hash is passed", ->
it "inserts a record with the given attributes", (done) ->
blogs.create { public: true, title: "New Blog 1", authorId: 11 }, ->
blogs.find { title: "New Blog 1" }, (err, record) ->
expect(record.public()).toBeTruthy()
expect(record.authorId()).toBe(11)
done()

describe "when an array of attribute hashes is passed", ->
it "inserts a record with each set of attributes", (done) ->
hashes = [
{ id: 1, public: true, title: "New Blog 1", authorId: 11 }
{ id: 2, public: true, title: "New Blog 2", authorId: 12 }
]

blogs.create hashes, ->
blogs.all (err, records) ->
expect(records).toEqualRecords(Blog, [
{ id: 1, public: true, title: "New Blog 1", authorId: 11 }
{ id: 2, public: true, title: "New Blog 2", authorId: 12 }
])
done()

29 changes: 28 additions & 1 deletion spec/server/sql/insert_builder_spec.coffee
Expand Up @@ -12,10 +12,37 @@ describe "InsertBuilder", ->

describe "when passed a single hash of attributes", ->
it "creates an insert statement with a single list of values", ->
sql = blogs.toInsertSql(public: true, title: 'Blog1', authorId: 5)
sql = blogs.toInsertSql({ public: true, title: 'Blog1', authorId: 5 })
expect(sql).toBeLikeQuery("""
INSERT INTO "blogs"
("public", "title", "author_id")
VALUES
(true, 'Blog1', 5)
""")

describe "when passed multiple hashes of attributes", ->
it "creates an insert statement with a single list of values", ->
sql = blogs.toInsertSql([
{ public: true, title: 'Blog1', authorId: 11 }
{ public: false, title: 'Blog2', authorId: 12 }
])
expect(sql).toBeLikeQuery("""
INSERT INTO "blogs"
("public", "title", "author_id")
VALUES
(true, 'Blog1', 11),
(false, 'Blog2', 12)
""")

it "fills in null values if attributes are missing from some hashes", ->
sql = blogs.toInsertSql([
{ public: true, title: 'Blog1' }
{ title: 'Blog2', authorId: 12 }
])
expect(sql).toBeLikeQuery("""
INSERT INTO "blogs"
("public", "title", "author_id")
VALUES
(true, 'Blog1', NULL),
(NULL, 'Blog2', 12)
""")

0 comments on commit a4da850

Please sign in to comment.