You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

189 lines
4.8 KiB
CoffeeScript

Promise = require "bluebird"
util = require "util"
Record = require "./record"
module.exports = class Model
constructor: (@name, @options) ->
# FIXME: Validation! tableName
@_isInstance = false
@options.idAttribute ?= "id"
_getInstance: ->
if @_isInstance
return this
else
instance = Object.create(this)
instance._isInstance = true
instance._queryBuilder = @_YAORM.knex(@options.tableName)
return instance
_fromQuery: (qbFunc) ->
instance = @_getInstance()
qbFunc(instance._queryBuilder)
return instance
_where: (whereStatements) ->
@_fromQuery (queryBuilder) ->
queryBuilder.where whereStatements
_all: ->
# We don't need to add anything to the query here, since we want all the records.
@_getInstance()
_createResultHandler: (options = {}) ->
return (rows) =>
self = this
Promise.map rows, (row) =>
# FIXME: Can this be done with a JOIN, perhaps?
record = self._createRecord()
record.isNew = false
record._setData(row)
if not options.relations?
options.relations = []
else if not util.isArray(options.relations)
options.relations = [options.relations]
record._loadRelations(options.relations ? [], row)
.then (rows) ->
if (options.single ? false)
if rows.length > 0
return rows[0]
else
# FIXME: Error
else
if rows.length > 0 or (options.required ? true) == false
return rows
else
# FIXME: Error
_createResultHandlerSingle: (options = {}) ->
options.single = true
@_createResultHandler(options)
_createResultHandlerCount: (options = {}) ->
return (rows) =>
return rows[0].CNT
_createRecord: ->
record = new Record()
record._setModel(this)
return record
_populateRecord: (record, data) ->
record._setData(data)
_getRelations: (relations, data) ->
Promise.try =>
relationKeys = Object.keys(relations)
Promise.map relationKeys, (attribute) =>
# FIXME: Shallow-clone these options? Immutability etc.
options = relations[attribute]
switch options.type
when "hasOne" then @_getHasOne(options.modelName, options, data)
when "hasMany" then @_getHasMany(options.modelName, options, data)
when "belongsTo" then @_getBelongsTo(options.modelName, options, data)
.reduce ((obj, remoteRecord, i) ->
obj[relationKeys[i]] = remoteRecord
return obj
), {}
_getSimpleRelation: (modelName, options, data) ->
Promise.try =>
remoteModel = @_YAORM.model(modelName)
switch options.type
when "hasOne", "hasMany" then options.localKey ?= remoteModel.options.idAttribute
when "belongsTo" then options.remoteKey ?= remoteModel.options.idAttribute
whereStatements = {}
whereStatements[options.remoteKey] = data[options.localKey]
options.query ?= (->)
queryBuilder = remoteModel
._where whereStatements
._fromQuery(options.query)
.query()
if (options.single ? false)
queryBuilder
.limit 1
.then remoteModel._createResultHandlerSingle(options)
else
queryBuilder
.then remoteModel._createResultHandler(options)
# The logic regarding which is the localKey and which is the remoteKey, is handled in the YAORM instance.
_getHasOne: (modelName, options, data) ->
options.single = true
@_getSimpleRelation(modelName, options, data)
_getHasMany: (modelName, options, data) ->
@_getSimpleRelation(modelName, options, data)
_getBelongsTo: (modelName, options, data) ->
options.single = true
@_getSimpleRelation(modelName, options, data)
create: (data) ->
record = @_createRecord()
record.isNew = true
return record
query: ->
return @_queryBuilder
find: (id, options = {}) ->
whereStatements = {}
whereStatements[@options.idAttribute] = id
@getOneWhere(whereStatements, options)
getOneWhere: (whereStatements, options = {}) ->
@_where(whereStatements)
.query()
.limit(1)
.then(@_createResultHandlerSingle(options))
getAllWhere: (whereStatements, options = {}) ->
@_where(whereStatements)
.query()
.then(@_createResultHandler(options))
countWhere: (whereStatements, options = {}) ->
@_where(whereStatements)
.query()
.count("#{@options.idAttribute} as CNT")
.then(@_createResultHandlerCount(options))
getOneFromQuery: (qbFunc, options = {}) ->
@_fromQuery(qbFunc)
.query()
.limit(1)
.then(@_createResultHandlerSingle(options))
getAllFromQuery: (qbFunc, options = {}) ->
@_fromQuery(qbFunc)
.query()
.then(@_createResultHandler(options))
countFromQuery: (qbFunc, options = {}) ->
@_fromQuery(qbFunc)
.query()
.count("#{@options.idAttribute} as CNT")
.then(@_createResultHandlerCount(options))
getAll: (options = {}) ->
@_all()
.query()
.then(@_createResultHandler(options))
countAll: (options = {}) ->
@_all()
.query()
.count("#{@options.idAttribute} as CNT")
.then(@_createResultHandlerCount(options))