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
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))
|