Skip to content
Browse files

Move schema definition into its own class

  • Loading branch information...
1 parent e110703 commit 4a5bc346269f388eea0bba7cfdb179696a5812e6 @wdavidw committed Mar 3, 2012
Showing with 631 additions and 547 deletions.
  1. +3 −3 index.js
  2. +12 −13 lib/Client.coffee
  3. +109 −259 lib/Records.coffee
  4. +200 −0 lib/Schema.coffee
  5. +0 −23 test/Client.coffee
  6. +11 −8 test/all.coffee
  7. +9 −8 test/count.coffee
  8. +20 −17 test/create.coffee
  9. +12 −9 test/create_validation.coffee
  10. +0 −60 test/define.coffee
  11. +22 −19 test/exists.coffee
  12. +21 −18 test/get.coffee
  13. +27 −0 test/hash.coffee
  14. +46 −43 test/id.coffee
  15. +23 −27 test/list.coffee
  16. +10 −9 test/remove.coffee
  17. +74 −0 test/schema.coffee
  18. +32 −31 test/update.coffee
View
6 index.js
@@ -3,12 +3,12 @@ require('coffee-script');
var Client = require('./lib/Client');
-var Records = require('./lib/Records');
-
module.exports = function(options){
return new Client(options);
};
module.exports.Client = Client;
-module.exports.Records = Records;
+module.exports.Records = require('./lib/Records');
+
+module.exports.Schema = require('./lib/Schema');
View
25 lib/Client.coffee
@@ -1,34 +1,33 @@
-crypto = require('crypto')
-redis = require('redis')
-Records = require('./Records')
+redis = require 'redis'
+Schema = require './Schema'
+Records = require './Records'
module.exports = class Client
constructor: (options = {}) ->
@options = options
@name = options.name or 'ron'
- @records = []
+ @schemas = {}
+ @records = {}
if @options.redis
@redis = @options.redis
else
@redis = redis.createClient options.redis_port ? 6379, options.redis_host ? '127.0.0.1'
@redis.auth options.redis_password if options.redis_password?
@redis.select options.redis_database if options.redis_database?
- define: (options) ->
+ schema: (options) ->
name = if typeof options is 'string' then options else options.name
- @records[name] = new Records @, options
+ @schemas[name] = new Schema @, options
+ @records[name] = new Records @, @schemas[name]
+ @schemas[name]
- get: (type) ->
- @records[type]
+ get: (name) ->
+ @records[name]
quit: (callback) ->
@redis.quit (err, status) ->
return unless callback
return callback err if err
- callback null, status if callback
-
- hash: (key) ->
- key = "#{key}" if typeof key is 'number'
- return if key? then crypto.createHash('sha1').update(key).digest('hex') else 'null'
+ callback null, status if callback
View
368 lib/Records.coffee
@@ -39,232 +39,74 @@ match the indexed value.
###
module.exports = class Records
- # redis = null
- _ron = null
-
- constructor: (ron, options) ->
- _ron = ron
+ constructor: (ron, schema) ->
@redis = ron.redis
- options = {name: options} if typeof options is 'string'
- @name = options.name
- @schema =
- db: ron.name
- name: options.name
- properties: {}
- identifier: null
- index: {}
- unique: {}
- email: {}
-
- ###
- Retrieve/define a new property
- ------------------------------
- Define a new property or overwrite the definition of an
- existing property. If no schema is provide, return the
- property information.
-
- Calling this function with only the property argument will return the schema
- information associated with the property.
-
- It is possible to define a new property without any schema information by
- providing an empty object.
-
- Example:
- User.property 'id', identifier: true
- User.property 'username', unique: true
- User.property 'email', { index: true, email: true }
- User.property 'name', {}
-
- ###
- property: (property, schema) ->
- if schema?
- schema ?= {}
- schema.name = property
- @schema.properties[property] = schema
- @identifier property if schema.identifier
- @index property if schema.index
- @unique property if schema.unique
- @email property if schema.email
- @
- else
- @schema.properties[property]
-
- ###
- Cast record values to their correct type
- ----------------------------------------
- Traverse all the record properties and update
- values with correct types.
- ###
- type: (records) ->
- s = @schema
- isArray = Array.isArray records
- records = [records] if ! isArray
- for record, i in records
- continue unless record?
- if typeof record is 'object'
- for property, value of record
- if s.properties[property]?.type is 'int' and value?
- record[property] = parseInt value, 10
- else if typeof record is 'number' or typeof record is 'string'
- records[i] = parseInt record
-
- ###
- Define a property as an identifier
- ----------------------------------
- An identifier is a property which uniquely define a record.
- Internaly, those type of property are stored in set.
-
- Calling this function without any argument will return the identifier if any.
- ###
- identifier: (property) ->
- # Set the property
- if property?
- @schema.properties[property] = {} unless @schema.properties[property]?
- @schema.properties[property].type = 'int'
- @schema.properties[property].identifier = true
- @schema.identifier = property
- @
- # Get the property
- else
- @schema.identifier
-
- ###
- Define a property as indexable or return all index properties
- -------------------------------------------------------------
- An indexed property allow records access by its property value. For example,
- when using the `list` function, the search can be filtered such as returned
- records match one or multiple values.
-
- Calling this function without any argument will return an array with all the
- indexed properties.
-
- Example:
- User.index 'email'
- User.list { filter: { email: 'my@email.com' } }, (err, users) ->
- console.log 'This user has the following accounts:'
- for user in user
- console.log "- #{user.username}"
- ###
- index: (property) ->
- # Set the property
- if property?
- @schema.properties[property] = {} unless @schema.properties[property]?
- @schema.properties[property].index = true
- @schema.index[property] = true
- @
- # Get the property
- else
- Object.keys(@schema.index)
-
- ###
- Define a property as unique
- ---------------------------
- An unique property is similar to a unique one but,... unique. In addition for
- being filterable, it could also be used as an identifer to access a record.
-
- Calling this function without any argument will return an arrya with all the
- unique properties.
-
- Example:
- User.unique 'username'
- User.get { username: 'me' }, (err, user) ->
- console.log "This is #{user.username}"
- ###
- unique: (property) ->
- # Set the property
- if property?
- @schema.properties[property] = {} unless @schema.properties[property]?
- @schema.properties[property].unique = true
- @schema.unique[property] = true
- @
- # Get the property
- else
- Object.keys(@schema.unique)
-
- ###
- Define property as en email
- ---------------------------
- Check that a property validate as an email
-
- Calling this function without any argument will return all the email
- properties.
-
- Example:
- User.unique 'username'
- User.get { username: 'me' }, (err, user) ->
- console.log "This is #{user.username}"
- ###
- email: (property) ->
- # Set the property
- if property?
- @schema.properties[property] = {} unless @schema.properties[property]?
- @schema.properties[property].email = true
- @schema.email[property] = true
- @
- # Get the property
- else
- @schema.email
+ @schema = schema
###
Return all records
------------------
Similar to the find method with far less options and a faster implementation.
###
all: (callback) ->
- {redis} = @
- s = @schema
- redis.smembers "#{s.db}:#{s.name}_#{s.identifier}", (err, recordIds) ->
+ {redis, schema} = @
+ {db, name, identifier} = schema.data
+ redis.smembers "#{db}:#{name}_#{identifier}", (err, recordIds) ->
multi = redis.multi()
for recordId in recordIds
- multi.hgetall "#{s.db}:#{s.name}:#{recordId}"
+ multi.hgetall "#{db}:#{name}:#{recordId}"
multi.exec (err, records) ->
return callback err if err
callback null, records
###
- Clear all the records and return the number of removed records
+ Clear all the records
+ ---------------------
+ Remove all the records and the references poiting to them. On
+ success, the number of removed records is provided in the callback.
###
clear: (callback) ->
- {redis} = @
- s = @schema
+ {redis, schema} = @
+ {hash} = schema
+ {db, name, identifier, index, unique} = schema.data
cmds = []
count = 0
multi = redis.multi()
# Grab index values for later removal
indexSort = []
- indexProperties = Object.keys(s.index)
+ indexProperties = Object.keys(index)
if indexProperties
- indexSort.push "#{s.db}:#{s.name}_#{s.identifier}"
+ indexSort.push "#{db}:#{name}_#{identifier}"
for property in indexProperties
indexSort.push 'get'
- indexSort.push "#{s.db}:#{s.name}:*->#{property}"
+ indexSort.push "#{db}:#{name}:*->#{property}"
# Delete null index
- cmds.push ['del', "#{s.db}:#{s.name}_#{property}:null"]
+ cmds.push ['del', "#{db}:#{name}_#{property}:null"]
indexSort.push (err, values) ->
if values.length
for i in [0 ... values.length] by indexProperties.length
for property, j in indexProperties
- value = _ron.hash values[i + j]
- cmds.push ['del', "#{s.db}:#{s.name}_#{property}:#{value}"]
+ value = hash values[i + j]
+ cmds.push ['del', "#{db}:#{name}_#{property}:#{value}"]
multi.sort indexSort...
# Grab record identifiers
- multi.smembers "#{s.db}:#{s.name}_#{s.identifier}", (err, recordIds) ->
+ multi.smembers "#{db}:#{name}_#{identifier}", (err, recordIds) ->
return callback err if err
# Return count in final callback
count = recordIds.length
# delete objects
for recordId in recordIds
- cmds.push ['del', "#{s.db}:#{s.name}:#{recordId}"]
+ cmds.push ['del', "#{db}:#{name}:#{recordId}"]
# Incremental counter
- cmds.push ['del', "#{s.db}:#{s.name}_incr"]
+ cmds.push ['del', "#{db}:#{name}_incr"]
# Identifier index
- cmds.push ['del', "#{s.db}:#{s.name}_#{s.identifier}"]
+ cmds.push ['del', "#{db}:#{name}_#{identifier}"]
# Unique indexes
- for property of s.unique
- cmds.push ['del', "#{s.db}:#{s.name}_#{property}"]
+ for property of unique
+ cmds.push ['del', "#{db}:#{name}_#{property}"]
# Index of values
- for property of s.index
- cmds.push ['del', "#{s.db}:#{s.name}_#{property}"]
+ for property of index
+ cmds.push ['del', "#{db}:#{name}_#{property}"]
multi.exec (err, results) ->
return callback err if err
multi = redis.multi cmds
@@ -276,24 +118,25 @@ module.exports = class Records
Count the number of records present in the database.
###
count: (callback) ->
- s = @schema
- @redis.scard "#{s.db}:#{s.name}_#{s.identifier}", (err, count) ->
+ {redis, schema} = @
+ {db, name, identifier} = schema.data
+ @redis.scard "#{db}:#{name}_#{identifier}", (err, count) ->
return callback err if err
callback null, count
###
Create a new record.
###
create: (records, callback) ->
- {redis} = @
- $ = @
- s = @schema
+ {redis, schema} = @
+ {hash} = schema
+ {db, name, properties, identifier, index, unique} = schema.data
isArray = Array.isArray records
records = [records] if ! isArray
# Sanitize records
for record in records
# Apply property definitions
- for property, def of s.properties
+ for property, def of properties
# Validation check
if def.required and not record[property]?
return callback new Error "Required property #{property}"
@@ -306,28 +149,28 @@ module.exports = class Records
return callback new Error "Record #{recordId} already exists" if recordId?
multi = redis.multi()
# Generate new identifiers
- multi.incr "#{s.db}:#{s.name}_incr" for x in records
+ multi.incr "#{db}:#{name}_incr" for x in records
multi.exec (err, recordIds) ->
return callback err if err
multi = redis.multi()
for record, i in records
- record[s.identifier] = recordId = recordIds[i]
- multi.sadd "#{s.db}:#{s.name}_#{s.identifier}", recordId
+ record[identifier] = recordId = recordIds[i]
+ multi.sadd "#{db}:#{name}_#{identifier}", recordId
# Deal with Unique
- for property of s.unique
- multi.hset "#{s.db}:#{s.name}_#{property}", record[property], recordId if record[property]
+ for property of unique
+ multi.hset "#{db}:#{name}_#{property}", record[property], recordId if record[property]
# Deal with Index
- for property of s.index
+ for property of index
value = record[property]
- value = _ron.hash value
- multi.sadd "#{s.db}:#{s.name}_#{property}:#{value}", recordId
+ value = hash value
+ multi.sadd "#{db}:#{name}_#{property}:#{value}", recordId
#multi.zadd "#{s.db}:#{s.name}_#{property}", 0, record[property]
# Store the record
r = {}
# Filter null values
for property, value of record
r[property] = value if value?
- multi.hmset "#{s.db}:#{s.name}:#{recordId}", r
+ multi.hmset "#{db}:#{name}:#{recordId}", r
multi.exec (err, results) ->
return callback err if err
for result in results
@@ -343,25 +186,25 @@ module.exports = class Records
are present if the record exists or null if it doesn't.
###
exists: (records, callback) ->
- $ = @
- s = @schema
+ {redis, schema} = @
+ {db, name, identifier, unique} = schema.data
isArray = Array.isArray records
records = [records] if ! isArray
- multi = @redis.multi()
+ multi = redis.multi()
for record in records
if typeof record is 'object'
- if record[s.identifier]?
- recordId = record[s.identifier]
- multi.hget "#{s.db}:#{s.name}:#{recordId}", s.identifier
+ if record[identifier]?
+ recordId = record[identifier]
+ multi.hget "#{db}:#{name}:#{recordId}", identifier
else
- for property of s.unique
+ for property of unique
if record[property]?
- multi.hget "#{s.db}:#{s.name}_#{property}", record[property]
+ multi.hget "#{db}:#{name}_#{property}", record[property]
else
- multi.hget "#{s.db}:#{s.name}:#{record}", s.identifier
+ multi.hget "#{db}:#{name}:#{record}", identifier
multi.exec (err, recordIds) ->
return callback err if err
- $.type recordIds
+ schema.type recordIds
callback null, if isArray then recordIds else recordIds[0]
###
@@ -382,8 +225,8 @@ module.exports = class Records
if arguments.length is 2
callback = options
options = {}
- $ = @
- s = @schema
+ {redis, schema} = @
+ {db, name, identifier, unique} = schema.data
isArray = Array.isArray records
records = [records] if not isArray
cmds = []
@@ -393,40 +236,40 @@ module.exports = class Records
if not record?
if not options.accept_null
return callback new Error 'Invalid object, got ' + (JSON.stringify record)
- else if record[s.identifier]?
+ else if record[identifier]?
# It's perfect, no need to hit redis
else if record.username? #todo
- cmds.push ['hget', "#{s.db}:#{s.name}_username", record.username, ((record) -> (err, recordId) ->
- record[s.identifier] = recordId
+ cmds.push ['hget', "#{db}:#{name}_username", record.username, ((record) -> (err, recordId) ->
+ record[identifier] = recordId
)(record)]
else
withUnique = false
- for property of s.unique
+ for property of unique
if record[property]?
withUnique = true
- cmds.push ['hget', "#{s.db}:#{s.name}_#{property}", record[property], ((record) -> (err, recordId) ->
- record[s.identifier] = recordId
+ cmds.push ['hget', "#{db}:#{name}_#{property}", record[property], ((record) -> (err, recordId) ->
+ record[identifier] = recordId
)(record)]
# Error if no identifier and no unique value provided
return callback new Error 'Invalid object, got ' + (JSON.stringify record) unless withUnique
else if typeof record is 'number' or typeof record is 'string'
records[i] = {}
- records[i][s.identifier] = record
+ records[i][identifier] = record
else
return callback new Error 'Invalid id, got ' + (JSON.stringify record)
# No need to hit redis if no comand are registered
if cmds.length is 0
if not options.object
records = for record in records
- if record? then record[s.identifier] else record
+ if record? then record[identifier] else record
#$.type records
return callback null, if isArray then records else records[0]
- multi = @redis.multi cmds
+ multi = redis.multi cmds
multi.exec (err, results) ->
if not options.object
records = for record in records
- record[s.identifier]
- $.type records
+ record[identifier]
+ schema.type records
callback null, if isArray then records else records[0]
###
@@ -446,26 +289,25 @@ module.exports = class Records
options = {}
if Array.isArray options
options = {properties: options}
- {redis} = @
- $ = @
- s = @schema
+ {redis, schema} = @
+ {db, name, identifier} = schema.data
isArray = Array.isArray records
records = [records] if ! isArray
@id records, {object: true}, (err, records) ->
cmds = []
records.forEach (record, i) ->
- if record[s.identifier] is null
+ if record[identifier] is null
records[i] = null
else if options.properties?
options.properties.forEach (property) ->
if ! options.force and ! record[property]
- recordId = record[s.identifier]
- cmds.push ['hget', "#{s.db}:#{s.name}:#{recordId}", property, (err, value)->
+ recordId = record[identifier]
+ cmds.push ['hget', "#{db}:#{name}:#{recordId}", property, (err, value)->
record[property] = value
]
else
- recordId = record[s.identifier]
- cmds.push ['hgetall', "#{s.db}:#{s.name}:#{recordId}", (err, values)->
+ recordId = record[identifier]
+ cmds.push ['hgetall', "#{db}:#{name}:#{recordId}", (err, values)->
for property, value of values
record[property] = value
]
@@ -474,21 +316,23 @@ module.exports = class Records
multi = redis.multi cmds
multi.exec (err, values) ->
return callback err if err
- $.type records
+ schema.type records
callback null, if isArray then records else records[0]
list: (options, callback) ->
if typeof options is 'function'
callback = options
options = {}
- s = @schema
+ {redis, schema} = @
+ {hash} = schema
+ {db, name, properties, identifier, index} = schema.data
args = []
multi = @redis.multi()
# Index
options.where = {} unless options.where?
where = []
for property, value of options
- if s.index[property]
+ if index[property]
if Array.isArray value
for v in value
where.push [property, v]
@@ -497,29 +341,29 @@ module.exports = class Records
options.where = if Object.keys(options.where).length then options.where else false
if where.length is 1
[property, value] = where[0]
- value = _ron.hash value
- args.push "#{s.db}:#{s.name}_#{property}:#{value}"
+ value = hash value
+ args.push "#{db}:#{name}_#{property}:#{value}"
else if where.length > 1
tempkey = "temp:#{(new Date).getTime()}#{Math.random()}"
keys = []
keys.push tempkey
args.push tempkey
for filter in where
[property, value] = filter
- value = _ron.hash value
- keys.push "#{s.db}:#{s.name}_#{property}:#{value}"
+ value = hash value
+ keys.push "#{db}:#{name}_#{property}:#{value}"
operation = options.operation ? 'union'
multi["s#{operation}store"] keys...
else
- args.push "#{s.db}:#{s.name}_#{s.identifier}"
+ args.push "#{db}:#{name}_#{identifier}"
# Sorting by one property
if options.sort?
args.push 'by'
- args.push "#{s.db}:#{s.name}:*->" + options.sort
+ args.push "#{db}:#{name}:*->" + options.sort
# Properties to return
- for property of s.properties
+ for property of properties
args.push 'get'
- args.push "#{s.db}:#{s.name}:*->" + property
+ args.push "#{db}:#{name}:*->" + property
# Sorting property is a string
args.push 'alpha'
# Sorting direction
@@ -528,7 +372,7 @@ module.exports = class Records
args.push (err, values) ->
return callback err if err
return callback null, [] unless values.length
- keys = Object.keys s.properties
+ keys = Object.keys properties
result = for i in [0 ... values.length] by keys.length
record = {}
for property, j in keys
@@ -542,27 +386,32 @@ module.exports = class Records
###
Remove one or several records
+ -----------------------------
+ Take one or multiple records and remove them from the database as
+ well as all the indexes referencing those records.
+
###
remove: (records, callback) ->
- {redis} = @
- s = @schema
+ {redis, schema} = @
+ {hash} = schema
+ {db, name, identifier, index, unique} = schema.data
isArray = Array.isArray records
- records = [records] if ! isArray
- @get records, [].concat(Object.keys(s.unique), Object.keys(s.index)), (err, records) ->
+ records = [records] unless isArray
+ @get records, [].concat(Object.keys(unique), Object.keys(index)), (err, records) ->
return callback err if err
multi = redis.multi()
for record in records
do (record) ->
# delete objects
- recordId = record[s.identifier]
- multi.del "#{s.db}:#{s.name}:#{recordId}"
+ recordId = record[identifier]
+ multi.del "#{db}:#{name}:#{recordId}"
# delete indexes
- multi.srem "#{s.db}:#{s.name}_#{s.identifier}", recordId
- for property of s.unique
- multi.hdel "#{s.db}:#{s.name}_#{property}", record[property]
- for property of s.index
- value = _ron.hash record[property]
- multi.srem "#{s.db}:#{s.name}_#{property}:#{value}", recordId, (err, count) ->
+ multi.srem "#{db}:#{name}_#{identifier}", recordId
+ for property of unique
+ multi.hdel "#{db}:#{name}_#{property}", record[property]
+ for property of index
+ value = hash record[property]
+ multi.srem "#{db}:#{name}_#{property}:#{value}", recordId, (err, count) ->
console.warn('Missing indexed property') if count isnt 1
multi.exec (err, results) ->
return callback err if err
@@ -573,9 +422,10 @@ module.exports = class Records
###
update: (records, callback) ->
{redis, schema} = @
- {db, name, properties, identifier, unique, index} = schema
+ {hash} = schema
+ {db, name, properties, identifier, unique, index} = schema.data
isArray = Array.isArray records
- records = [records] if ! isArray
+ records = [records] unless isArray
# 1. Get values of indexed properties
# 2. If indexed properties has changed
# 2.1 Make sure the new property is not assigned to another record
@@ -623,8 +473,8 @@ module.exports = class Records
console.warn 'Trying to write on existing unique property' unless success
]
else if properties[property].index
- valueOld = _ron.hash values[propertyI]
- valueNew = _ron.hash record[property]
+ valueOld = hash values[propertyI]
+ valueNew = hash record[property]
cmdsUpdate.push ['srem', "#{db}:#{name}_#{property}:#{valueOld}", recordId ]
cmdsUpdate.push ['sadd', "#{db}:#{name}_#{property}:#{valueNew}", recordId ]
# Get the value of those indexed properties to see if they changed
View
200 lib/Schema.coffee
@@ -0,0 +1,200 @@
+
+crypto = require 'crypto'
+
+###
+Schema
+======
+Define a new schema.
+
+Sample
+------
+
+ ron.schema
+ name: 'users'
+ properties:
+ user_id: identifier: true
+ username: unique: true
+ password: true
+
+and then you can manipulate your records
+
+ users = ron.get 'users'
+ users.list (err, users) -> console.log users
+
+###
+module.exports = class Schema
+
+ constructor: (ron, options) ->
+ @ron = ron
+ options = {name: options} if typeof options is 'string'
+ @data =
+ db: ron.name
+ name: options.name
+ properties: {}
+ identifier: null
+ index: {}
+ unique: {}
+ email: {}
+ if options.properties
+ for name, value of options.properties
+ @property name, value
+
+ ###
+ Retrieve/define a new property
+ ------------------------------
+ Define a new property or overwrite the definition of an
+ existing property. If no schema is provide, return the
+ property information.
+
+ Calling this function with only the property argument will return the schema
+ information associated with the property.
+
+ It is possible to define a new property without any schema information by
+ providing an empty object.
+
+ Example:
+ User.property 'id', identifier: true
+ User.property 'username', unique: true
+ User.property 'email', { index: true, email: true }
+ User.property 'name', {}
+
+ ###
+ property: (property, schema) ->
+ if schema?
+ schema ?= {}
+ schema.name = property
+ @data.properties[property] = schema
+ @identifier property if schema.identifier
+ @index property if schema.index
+ @unique property if schema.unique
+ @email property if schema.email
+ @
+ else
+ @data.properties[property]
+
+ ###
+ Cast record values to their correct type
+ ----------------------------------------
+ Traverse all the record properties and update
+ values with correct types.
+ ###
+ type: (records) ->
+ s = @schema
+ {properties} = @data
+ isArray = Array.isArray records
+ records = [records] if ! isArray
+ for record, i in records
+ continue unless record?
+ if typeof record is 'object'
+ for property, value of record
+ if properties[property]?.type is 'int' and value?
+ record[property] = parseInt value, 10
+ else if typeof record is 'number' or typeof record is 'string'
+ records[i] = parseInt record
+
+ ###
+ Define a property as an identifier
+ ----------------------------------
+ An identifier is a property which uniquely define a record.
+ Internaly, those type of property are stored in set.
+
+ Calling this function without any argument will return the identifier if any.
+ ###
+ identifier: (property) ->
+ # Set the property
+ if property?
+ @data.properties[property] = {} unless @data.properties[property]?
+ @data.properties[property].type = 'int'
+ @data.properties[property].identifier = true
+ @data.identifier = property
+ @
+ # Get the property
+ else
+ @data.identifier
+
+ ###
+ Define a property as indexable or return all index properties
+ -------------------------------------------------------------
+ An indexed property allow records access by its property value. For example,
+ when using the `list` function, the search can be filtered such as returned
+ records match one or multiple values.
+
+ Calling this function without any argument will return an array with all the
+ indexed properties.
+
+ Example:
+ User.index 'email'
+ User.list { filter: { email: 'my@email.com' } }, (err, users) ->
+ console.log 'This user has the following accounts:'
+ for user in user
+ console.log "- #{user.username}"
+ ###
+ index: (property) ->
+ # Set the property
+ if property?
+ @data.properties[property] = {} unless @data.properties[property]?
+ @data.properties[property].index = true
+ @data.index[property] = true
+ @
+ # Get the property
+ else
+ Object.keys(@data.index)
+
+ ###
+ Define a property as unique
+ ---------------------------
+ An unique property is similar to a unique one but,... unique. In addition for
+ being filterable, it could also be used as an identifer to access a record.
+
+ Calling this function without any argument will return an arrya with all the
+ unique properties.
+
+ Example:
+ User.unique 'username'
+ User.get { username: 'me' }, (err, user) ->
+ console.log "This is #{user.username}"
+ ###
+ unique: (property) ->
+ # Set the property
+ if property?
+ @data.properties[property] = {} unless @data.properties[property]?
+ @data.properties[property].unique = true
+ @data.unique[property] = true
+ @
+ # Get the property
+ else
+ Object.keys(@data.unique)
+
+ ###
+ Define property as en email
+ ---------------------------
+ Check that a property validate as an email
+
+ Calling this function without any argument will return all the email
+ properties.
+
+ Example:
+ User.unique 'username'
+ User.get { username: 'me' }, (err, user) ->
+ console.log "This is #{user.username}"
+ ###
+ email: (property) ->
+ # Set the property
+ if property?
+ @data.properties[property] = {} unless @data.properties[property]?
+ @data.properties[property].email = true
+ @data.email[property] = true
+ @
+ # Get the property
+ else
+ @data.email
+
+ ###
+ Hash a key
+ ----------
+ This is a utility function used when redis key are created out of
+ uncontrolled values.
+ ###
+ hash: (key) ->
+ key = "#{key}" if typeof key is 'number'
+ return if key? then crypto.createHash('sha1').update(key).digest('hex') else 'null'
View
23 test/Client.coffee
@@ -1,23 +0,0 @@
-
-should = require 'should'
-
-try config = require '../conf/test' catch e
-Ron = require '../index'
-
-describe 'client', ->
-
- ron = Ron config
-
- it 'init', (next) ->
- next()
-
- it 'Test hash # with string', (next) ->
- ron.hash('1').should.eql '356a192b7913b04c54574d18c28d46e6395428ab'
- next()
-
- it 'Test hash # with number', (next) ->
- ron.hash(1).should.eql '356a192b7913b04c54574d18c28d46e6395428ab'
- next()
-
- it 'destroy', (next) ->
- ron.quit next
View
19 test/all.coffee
@@ -6,24 +6,27 @@ Ron = require '../index'
describe 'all', ->
- ron = User = null
+ ron = Users = null
before (next) ->
ron = Ron config
- User = ron.define 'users'
- User.identifier 'user_id'
- User.unique 'username'
- User.index 'email'
+ ron.schema
+ name: 'users'
+ properties:
+ user_id: identifier: true
+ username: unique: true
+ email: index: true
+ Users = ron.get 'users'
next()
beforeEach (next) ->
- User.clear next
+ Users.clear next
after (next) ->
ron.quit next
it 'shall create 2 users and list them', (next) ->
- User.create [
+ Users.create [
username: 'my_username_1',
email: 'my_first@email.com',
password: 'my_password'
@@ -32,7 +35,7 @@ describe 'all', ->
email: 'my_second@email.com',
password: 'my_password'
], (err, users) ->
- User.all (err, users) ->
+ Users.all (err, users) ->
should.not.exist err
users.length.should.eql 2
users[0].password.should.eql 'my_password'
View
17 test/count.coffee
@@ -6,24 +6,25 @@ Ron = require '../index'
describe 'count', ->
- ron = User = null
+ ron = Users = null
before (next) ->
ron = Ron config
- User = ron.define 'users'
- User.identifier 'user_id'
- User.unique 'username'
- User.index 'email'
+ schema = ron.schema 'users'
+ schema.identifier 'user_id'
+ schema.unique 'username'
+ schema.index 'email'
+ Users = ron.get 'users'
next()
beforeEach (next) ->
- User.clear next
+ Users.clear next
after (next) ->
ron.quit next
it 'Test count', (next) ->
- User.create [
+ Users.create [
username: '1my_username',
email: '1my@email.com',
password: 'my_password'
@@ -32,7 +33,7 @@ describe 'count', ->
email: '2my@email.com',
password: 'my_password'
], (err, user) ->
- User.count (err, count) ->
+ Users.count (err, count) ->
should.not.exist err
count.should.eql 2
next()
View
37 test/create.coffee
@@ -6,24 +6,27 @@ Ron = require '../index'
describe 'create', ->
- ron = User = null
+ ron = Users = null
before (next) ->
ron = Ron config
- User = ron.define 'users'
- User.identifier 'user_id'
- User.unique 'username'
- User.index 'email'
+ ron.schema
+ name: 'users'
+ properties:
+ user_id: identifier: true
+ username: unique: true
+ email: index: true
+ Users = ron.get 'users'
next()
beforeEach (next) ->
- User.clear next
+ Users.clear next
after (next) ->
ron.quit next
it 'Test create # one user', (next) ->
- User.create
+ Users.create
username: 'my_username',
email: 'my@email.com',
password: 'my_password'
@@ -32,10 +35,10 @@ describe 'create', ->
user.user_id.should.be.a 'number'
user.email.should.eql 'my@email.com'
# toto: Replace by User.remove
- User.clear next
+ Users.clear next
it 'Test create # multiple users', (next) ->
- User.create [
+ Users.create [
username: 'my_username_1',
email: 'my_first@email.com',
password: 'my_password'
@@ -47,39 +50,39 @@ describe 'create', ->
should.not.exist err
users.length.should.eql 2
users[0].password.should.eql 'my_password'
- # toto: Replace by User.remove
- User.clear next
+ # toto: Replace by Users.remove
+ Users.clear next
it 'Test create # existing id', (next) ->
- User.create
+ Users.create
username: 'my_username',
email: 'my@email.com',
password: 'my_password'
, (err, user) ->
should.not.exist err
- User.create {
+ Users.create {
user_id: user.user_id,
username: 'my_new_username',
email: 'my_new@email.com',
password: 'my_password'
}, (err, user) ->
err.message.should.eql 'Record 1 already exists'
- User.clear next
+ Users.clear next
it 'Test create # unique exists', (next) ->
- User.create
+ Users.create
username: 'my_username',
email: 'my@email.com',
password: 'my_password'
, (err, user) ->
should.not.exist err
- User.create
+ Users.create
username: 'my_username',
email: 'my@email.com',
password: 'my_password'
, (err, user) ->
err.message.should.eql 'Record 1 already exists'
- User.clear next
+ Users.clear next
View
21 test/create_validation.coffee
@@ -6,28 +6,31 @@ Ron = require '../index'
describe 'create_validation', ->
- ron = User = null
+ ron = Users = null
before (next) ->
ron = Ron config
- User = ron.define 'users'
- User.identifier 'user_id'
- User.unique 'username'
- User.index 'email'
- User.email 'email'
+ ron = Ron config
+ ron.schema
+ name: 'users'
+ properties:
+ user_id: identifier: true
+ username: unique: true
+ email: {index: true, email: true}
+ Users = ron.get 'users'
next()
beforeEach (next) ->
- User.clear next
+ Users.clear next
after (next) ->
ron.quit next
it 'Test create validate # email with record', (next) ->
- User.create
+ Users.create
username: 'my_username',
email: 'invalid_email.com',
password: 'my_password'
, (err, user) ->
err.message.should.eql 'Invalid email invalid_email.com'
- User.clear next
+ Users.clear next
View
60 test/define.coffee
@@ -1,60 +0,0 @@
-
-should = require 'should'
-
-try config = require '../conf/test' catch e
-ron = require '..'
-
-describe 'define', ->
-
- it 'Define # new schema # string', (next) ->
- client = ron config
- user = client.define 'user'
- user.should.be.instanceof ron.Records
- user.should.eql client.get 'user'
- client.quit next
-
- it 'Define # new schema # object', (next) ->
- client = ron config
- user = client.define name: 'user'
- user.should.eql client.get 'user'
- user.should.be.instanceof ron.Records
- client.quit next
-
- it 'Define # identifier', (next) ->
- client = ron config
- user = client.define name: 'user'
- user.should.eql user.identifier('id')
- user.identifier().should.eql 'id'
- client.quit next
-
- it 'Define # index', (next) ->
- client = ron config
- user = client.define name: 'user'
- user.should.eql user.index('my_index')
- ['my_index'].should.eql user.index()
- client.quit next
-
- it 'Define # unique', (next) ->
- client = ron config
- user = client.define name: 'user'
- user.should.eql user.unique('my_unique')
- user.unique().should.eql ['my_unique']
- client.quit next
-
- it 'Define # property', (next) ->
- client = ron config
- user = client.define name: 'user'
- # Define properties
- user.should.eql user.property('id', identifier: true)
- user.should.eql user.property('username', unique: true)
- user.should.eql user.property('email', { index: true, email: true })
- user.should.eql user.property('name', {})
- # Retrieve properties
- user.property('id').should.eql { name: 'id', identifier: true, type: 'int' }
- user.property('username').should.eql { name: 'username', unique: true }
- user.property('email').should.eql { name: 'email', index: true, email: true }
- user.property('name').should.eql { name: 'name' }
-
- client.quit next
-
-
View
41 test/exists.coffee
@@ -7,7 +7,7 @@ Ron = require '../index'
describe 'exists', ->
create = (callback) ->
- User.create [
+ Users.create [
username: 'my_username_1',
email: 'my_1@email.com',
password: 'my_password'
@@ -19,62 +19,65 @@ describe 'exists', ->
should.ifError err
callback(null, users)
- ron = User = null
+ ron = Users = null
before (next) ->
ron = Ron config
- User = ron.define 'users'
- User.identifier 'user_id'
- User.unique 'username'
- User.index 'email'
+ ron.schema
+ name: 'users'
+ properties:
+ user_id: identifier: true
+ username: unique: true
+ email: index: true
+ Users = ron.get 'users'
next()
beforeEach (next) ->
- User.clear next
+ Users.clear next
after (next) ->
ron.quit next
it 'Test exists # true # identifier', (next) ->
create (err, users) ->
user = users[1]
- User.exists user.user_id, (err, userId) ->
+ Users.exists user.user_id, (err, userId) ->
should.not.exist err
userId.should.eql user.user_id
- User.clear next
+ Users.clear next
it 'Test exists # true # record with identifier', (next) ->
create (err, users) ->
user = users[1]
- User.exists {user_id: user.user_id}, (err, userId) ->
+ Users.exists {user_id: user.user_id}, (err, userId) ->
should.not.exist err
userId.should.eql user.user_id
- User.clear next
+ Users.clear next
it 'Test exists # true # record with unique property stored in hash', (next) ->
create (err, users) ->
user = users[1]
- User.exists {username: user.username}, (err, userId) ->
+ Users.exists {username: user.username}, (err, userId) ->
should.not.exist err
userId.should.eql user.user_id
- User.clear next
+ Users.clear next
it 'Test exists # false # indentifier', (next) ->
- User.exists 'missing', (err, exists) ->
+ Users.exists 'missing', (err, exists) ->
should.not.exist err
should.not.exist exists
- User.clear next
+ Users.clear next
it 'Test exists # false # record with identifier', (next) ->
- User.exists {user_id: 'missing'}, (err, exists) ->
+ Users.exists {user_id: 'missing'}, (err, exists) ->
should.not.exist err
should.not.exist exists
- User.clear next
+ Users.clear next
it 'Test exists # false # record with unique property stored in hash', (next) ->
- User.exists {username: 'missing'}, (err, exists) ->
+ Users.exists {username: 'missing'}, (err, exists) ->
should.not.exist err
should.not.exist exists
- User.clear next
+ Users.clear next
View
39 test/get.coffee
@@ -6,66 +6,69 @@ Ron = require '../index'
describe 'get', ->
- ron = User = null
+ ron = Users = null
before (next) ->
ron = Ron config
- User = ron.define 'users'
- User.identifier 'user_id'
- User.unique 'username'
- User.index 'email'
+ ron.schema
+ name: 'users'
+ properties:
+ user_id: identifier: true
+ username: unique: true
+ email: index: true
+ Users = ron.get 'users'
next()
beforeEach (next) ->
- User.clear next
+ Users.clear next
after (next) ->
ron.quit next
it 'Test get # identifier', (next) ->
- User.create
+ Users.create
username: 'my_username',
email: 'my@email.com'
, (err, user) ->
userId = user.user_id
# Test with a number
- User.get userId, (err, user) ->
+ Users.get userId, (err, user) ->
should.not.exist err
user.user_id.should.eql userId
user.username.should.eql 'my_username'
user.email.should.eql 'my@email.com'
# Test with a string
- User.get '' + userId, (err, user) ->
+ Users.get '' + userId, (err, user) ->
should.not.exist err
user.user_id.should.eql userId
- User.clear next
+ Users.clear next
it 'Test get # unique property', (next) ->
- User.create
+ Users.create
username: 'my_username',
email: 'my@email.com'
, (err, user) ->
userId = user.user_id
- User.get {username: 'my_username'}, (err, user) ->
+ Users.get {username: 'my_username'}, (err, user) ->
should.not.exist err
user.user_id.should.eql userId
- User.clear next
+ Users.clear next
it 'Test get # unique property missing', (next) ->
- User.get {username: 'my_missing_username'}, (err, user) ->
+ Users.get {username: 'my_missing_username'}, (err, user) ->
should.not.exist err
should.not.exist user
- User.clear next
+ Users.clear next
it 'Test get # properties', (next) ->
- User.create
+ Users.create
username: 'my_username',
email: 'my@email.com',
, (err, user) ->
userId = user.user_id
- User.get userId, ['username'], (err, user) ->
+ Users.get userId, ['username'], (err, user) ->
should.not.exist err
user.user_id.should.eql userId
user.username.should.eql 'my_username'
should.not.exist user.email
- User.clear next
+ Users.clear next
View
27 test/hash.coffee
@@ -0,0 +1,27 @@
+
+should = require 'should'
+
+try config = require '../conf/test' catch e
+Ron = require '../index'
+
+describe 'client', ->
+
+ ron = null
+
+ before (next) ->
+ ron = Ron config
+ next()
+
+ after (next) ->
+ ron.quit next
+
+ it 'init', (next) ->
+ next()
+
+ it 'should hash a string', (next) ->
+ ron.schema('users').hash('1').should.eql '356a192b7913b04c54574d18c28d46e6395428ab'
+ next()
+
+ it 'should hash a number', (next) ->
+ ron.schema('users').hash(1).should.eql '356a192b7913b04c54574d18c28d46e6395428ab'
+ next()
View
89 test/id.coffee
@@ -6,91 +6,94 @@ Ron = require '../index'
describe 'id', ->
- ron = User = null
+ ron = Users = null
before (next) ->
ron = Ron config
- User = ron.define 'users'
- User.identifier 'user_id'
- User.unique 'username'
- User.index 'email'
+ ron.schema
+ name: 'users'
+ properties:
+ user_id: identifier: true
+ username: unique: true
+ email: index: true
+ Users = ron.get 'users'
next()
beforeEach (next) ->
- User.clear next
+ Users.clear next
after (next) ->
ron.quit next
it 'Test id # number', (next) ->
- User.id 3, (err, userId) ->
+ Users.id 3, (err, userId) ->
should.not.exist err
userId.should.eql 3
- User.id [3], (err, userId) ->
+ Users.id [3], (err, userId) ->
should.not.exist err
userId.should.eql [3]
next()
it 'Test id # user.user_id', (next) ->
- User.id {user_id: 3}, (err, userId) ->
+ Users.id {user_id: 3}, (err, userId) ->
should.not.exist err
userId.should.eql 3
- User.id [{user_id: 3, username: 'my_username'}], (err, userId) ->
+ Users.id [{user_id: 3, username: 'my_username'}], (err, userId) ->
should.not.exist err
userId.should.eql [3]
next()
it 'Test id # user.username', (next) ->
- User.create
+ Users.create
username: 'my_username',
email: 'my@email.com',
password: 'my_password'
, (err, user) ->
# Pass an object
- User.id {username: 'my_username'}, (err, userId) ->
+ Users.id {username: 'my_username'}, (err, userId) ->
should.not.exist err
userId.should.eql user.user_id
# Pass an array of ids and objects
- User.id [1, {username: 'my_username'}, 2], (err, userId) ->
+ Users.id [1, {username: 'my_username'}, 2], (err, userId) ->
should.not.exist err
userId.should.eql [1, user.user_id, 2]
- User.clear next
+ Users.clear next
it 'Test id # invalid object empty', (next) ->
# Test an array of 3 arguments,
# but the second is invalid since it's an empty object
- User.id [1, {}, {user_id: 2}], (err, user) ->
+ Users.id [1, {}, {user_id: 2}], (err, user) ->
err.message.should.eql 'Invalid object, got {}'
- User.id {}, (err, user) ->
+ Users.id {}, (err, user) ->
err.message.should.eql 'Invalid object, got {}'
- User.clear next
+ Users.clear next
it 'Test id # missing unique', (next) ->
# Test an array of 3 arguments,
# but the second is invalid since it's an empty object
- User.create [
+ Users.create [
{ username: 'my_username_1', email: 'my1@mail.com' }
{ username: 'my_username_2', email: 'my2@mail.com' }
], (err, users) ->
# Test return id
- User.id [
+ Users.id [
{ username: users[1].username } # By unique
{ user_id: users[0].user_id } # By identifier
{ username: 'who are you' } # Alien
], (err, result) ->
result[0].should.eql users[1].user_id
result[1].should.eql users[0].user_id
should.not.exist result[2]
- User.clear next
+ Users.clear next
it 'Test id # missing unique + option object', (next) ->
# Test an array of 3 arguments,
# but the second is invalid since it's an empty object
- User.create [
+ Users.create [
{ username: 'my_username_1', email: 'my1@mail.com' }
{ username: 'my_username_2', email: 'my2@mail.com' }
], (err, users) ->
- User.id [
+ Users.id [
{ username: users[1].username } # By unique
{ user_id: users[0].user_id } # By identifier
{ username: 'who are you' } # Alien
@@ -99,82 +102,82 @@ describe 'id', ->
result[0].user_id.should.eql users[1].user_id
result[1].user_id.should.eql users[0].user_id
should.not.exist result[2].user_id
- User.clear next
+ Users.clear next
it 'Test id # invalid type id', (next) ->
# Test an array of 3 arguments,
# but the second is invalid since it's a boolean
- User.id [1, true, {user_id: 2}], (err, user) ->
+ Users.id [1, true, {user_id: 2}], (err, user) ->
err.message.should.eql 'Invalid id, got true'
- User.id false, (err, user) ->
+ Users.id false, (err, user) ->
err.message.should.eql 'Invalid id, got false'
- User.clear next
+ Users.clear next
it 'Test id # invalid type null', (next) ->
# Test an array of 3 arguments,
# but the second is invalid since it's a boolean
- User.id [1, null, {user_id: 2}], (err, users) ->
+ Users.id [1, null, {user_id: 2}], (err, users) ->
err.message.should.eql 'Invalid object, got null'
- User.id null, (err, user) ->
+ Users.id null, (err, user) ->
err.message.should.eql 'Invalid object, got null'
- User.clear next
+ Users.clear next
it 'Test id # accept null', (next) ->
# Test an array of 3 arguments,
# but the second is invalid since it's a boolean
- User.id [1, null, {user_id: 2}], {accept_null: true}, (err, users) ->
+ Users.id [1, null, {user_id: 2}], {accept_null: true}, (err, users) ->
should.not.exist err
users.length.should.eql 3
should.exist users[0]
should.not.exist users[1]
should.exist users[2]
# Test null
- User.id null, {accept_null: true}, (err, user) ->
+ Users.id null, {accept_null: true}, (err, user) ->
should.not.exist err
should.not.exist user
- User.clear next
+ Users.clear next
it 'Test id # accept null return object', (next) ->
# Same test than 'Test id # accept null' with the 'object' option
- User.id [1, null, {user_id: 2}], {accept_null: true, object: true}, (err, users) ->
+ Users.id [1, null, {user_id: 2}], {accept_null: true, object: true}, (err, users) ->
should.not.exist err
users.length.should.eql 3
users[0].user_id.should.eql 1
should.not.exist users[1]
users[2].user_id.should.eql 2
# Test null
- User.id null, {accept_null: true, object: true}, (err, user) ->
+ Users.id null, {accept_null: true, object: true}, (err, user) ->
should.not.exist err
should.not.exist user
- User.clear next
+ Users.clear next
it 'Test id # id return object', (next) ->
- User.create {
+ Users.create {
username: 'my_username'
email: 'my@email.com'
password: 'my_password'
}, (err, orgUser) ->
# Pass an id
- User.id orgUser.user_id, {object: true}, (err, user) ->
+ Users.id orgUser.user_id, {object: true}, (err, user) ->
should.not.exist err
user.should.eql {user_id: orgUser.user_id}
# Pass an array of ids
- User.id [orgUser.user_id, orgUser.user_id], {object: true}, (err, user) ->
+ Users.id [orgUser.user_id, orgUser.user_id], {object: true}, (err, user) ->
user.should.eql [{user_id: orgUser.user_id}, {user_id: orgUser.user_id}]
- User.clear next
+ Users.clear next
it 'Test id # unique + option object', (next) ->
- User.create {
+ Users.create {
username: 'my_username'
email: 'my@email.com'
password: 'my_password'
}, (err, orgUser) ->
# Pass an object
- User.id {username: 'my_username'}, {object: true}, (err, user) ->
+ Users.id {username: 'my_username'}, {object: true}, (err, user) ->
should.not.exist err
user.should.eql {username: 'my_username', user_id: orgUser.user_id}
# Pass an array of ids and objects
- User.id [1, {username: 'my_username'}, 2], {object: true}, (err, user) ->
+ Users.id [1, {username: 'my_username'}, 2], {object: true}, (err, user) ->
should.not.exist err
user.should.eql [{user_id: 1}, {username: 'my_username', user_id: orgUser.user_id}, {user_id: 2}]
- User.clear next
+ Users.clear next
View
50 test/list.coffee
@@ -6,85 +6,81 @@ Ron = require '../index'
describe 'list', ->
- ron = User = null
+ ron = Users = null
before (next) ->
ron = Ron config
- User = ron.define 'users'
- User.identifier 'user_id'
- User.unique 'username'
- User.index 'email'
- User.index 'name'
+ ron.schema
+ name: 'users'
+ properties:
+ user_id: identifier: true
+ username: unique: true
+ email: index: true
+ name: index: true
+ Users = ron.get 'users'
next()
beforeEach (next) ->
- User.clear next
+ Users.clear next
after (next) ->
ron.quit next
- ron = Ron config
- User = ron.define 'users'
- User.identifier 'user_id'
- User.unique 'username'
- User.index 'email'
- User.index 'name'
-
it 'Test list # result empty', (next) ->
- User.list { }, (err, users) ->
+ Users.list { }, (err, users) ->
should.not.exist err
users.length.should.eql 0
next()
it 'Test list # sort', (next) ->
- User.create [
+ Users.create [
{ username: 'username_1', email: '1@email.com', password: 'my_password' }
{ username: 'username_2', email: '2@email.com', password: 'my_password' }
], (err, users) ->
- User.list { sort: 'username', direction: 'desc' }, (err, users) ->
+ Users.list { sort: 'username', direction: 'desc' }, (err, users) ->
should.not.exist err
users.length.should.eql 2
users[0].username.should.eql 'username_2'
users[1].username.should.eql 'username_1'
- User.clear next
+ Users.clear next
it 'Test list # where', (next) ->
- User.create [
+ Users.create [
{ username: 'username_1', email: '1@email.com', password: 'my_password' }
{ username: 'username_2', email: '2@email.com', password: 'my_password' }
{ username: 'username_3', email: '1@email.com', password: 'my_password' }
], (err, users) ->
- User.list { email: '1@email.com', direction: 'desc' }, (err, users) ->
+ Users.list { email: '1@email.com', direction: 'desc' }, (err, users) ->
should.not.exist err
users.length.should.eql 2
users[0].username.should.eql 'username_3'
users[1].username.should.eql 'username_1'
- User.clear next
+ Users.clear next
it 'Test list # where union, same property', (next) ->
- User.create [
+ Users.create [
{ username: 'username_1', email: '1@email.com', password: 'my_password' }
{ username: 'username_2', email: '2@email.com', password: 'my_password' }
{ username: 'username_3', email: '1@email.com', password: 'my_password' }
{ username: 'username_4', email: '4@email.com', password: 'my_password' }
], (err, users) ->
- User.list { email: ['1@email.com', '4@email.com'], operation: 'union', direction: 'desc' }, (err, users) ->
+ Users.list { email: ['1@email.com', '4@email.com'], operation: 'union', direction: 'desc' }, (err, users) ->
should.not.exist err
users.length.should.eql 3
users[0].username.should.eql 'username_4'
users[1].username.should.eql 'username_3'
users[2].username.should.eql 'username_1'
- User.clear next
+ Users.clear next
it 'Test list # where inter, same property', (next) ->
- User.create [
+ Users.create [
{ username: 'username_1', email: '1@email.com', password: 'my_password', name: 'name_1' }
{ username: 'username_2', email: '2@email.com', password: 'my_password', name: 'name_2' }
{ username: 'username_3', email: '1@email.com', password: 'my_password', name: 'name_3' }
{ username: 'username_4', email: '4@email.com', password: 'my_password', name: 'name_4' }
], (err, users) ->
- User.list { email: '1@email.com', name: 'name_3', operation: 'inter', direction: 'desc' }, (err, users) ->
+ Users.list { email: '1@email.com', name: 'name_3', operation: 'inter', direction: 'desc' }, (err, users) ->
should.not.exist err
users.length.should.eql 1
users[0].username.should.eql 'username_3'
- User.clear next
+ Users.clear next
View
19 test/remove.coffee
@@ -6,33 +6,34 @@ Ron = require '../index'
describe 'remove', ->
- ron = User = null
+ ron = Users = null
before (next) ->
ron = Ron config
- User = ron.define 'users'
- User.identifier 'user_id'
- User.unique 'username'
- User.index 'email'
+ schema = ron.schema 'users'
+ schema.identifier 'user_id'
+ schema.unique 'username'
+ schema.index 'email'
+ Users = ron.get 'users'
next()
beforeEach (next) ->
- User.clear next
+ Users.clear next
after (next) ->
ron.quit next
it 'Test remove # from identifier', (next) ->
- User.create {
+ Users.create {
username: 'my_username'
email: 'my@email.com'
password: 'my_password'
}, (err, user) ->
# Delete record bsed on identifier
- User.remove user.user_id, (err, count) ->
+ Users.remove user.user_id, (err, count) ->
should.not.exist err
count.should.eql 1
# Check record doesn't exist
- User.exists user.user_id, (err, exists) ->
+ Users.exists user.user_id, (err, exists) ->
should.not.exist exists
next()
View
74 test/schema.coffee
@@ -0,0 +1,74 @@
+
+ should = require 'should'
+
+ try config = require '../conf/test' catch e
+ ron = require '..'
+
+ describe 'schema', ->
+
+ it 'should create a schema from a name', (next) ->
+ client = ron config
+ schema = client.schema 'users'
+ schema.should.be.instanceof ron.Schema
+ client.quit next
+
+ it 'should create a schema from an object', (next) ->
+ client = ron config
+ schema = client.schema name: 'users'
+ schema.should.be.instanceof ron.Schema
+ client.quit next
+
+ it 'should define and retrieve an identifier', (next) ->
+ client = ron config
+ schema = client.schema name: 'users'
+ schema.should.eql schema.identifier('id')
+ schema.identifier().should.eql 'id'
+ client.quit next
+
+ it 'should define and retrieve an index', (next) ->
+ client = ron config
+ schema = client.schema name: 'users'
+ schema.should.eql schema.index('my_index')
+ ['my_index'].should.eql schema.index()
+ client.quit next
+
+ it 'Define # unique', (next) ->
+ client = ron config
+ schema = client.schema name: 'users'
+ schema.should.eql schema.unique('my_unique')
+ schema.unique().should.eql ['my_unique']
+ client.quit next
+
+ it 'should define multiple properties from object', (next) ->
+ client = ron config
+ # Define properties
+ schema = client.schema
+ name: 'users'
+ properties:
+ id: identifier: true
+ username: unique: true
+ email: { index: true, email: true }
+ name: {}
+ # Retrieve properties
+ schema.property('id').should.eql { name: 'id', identifier: true, type: 'int' }
+ schema.property('username').should.eql { name: 'username', unique: true }
+ schema.property('email').should.eql { name: 'email', index: true, email: true }
+ schema.property('name').should.eql { name: 'name' }
+ client.quit next
+
+ it 'should define multiple properties by calling functions', (next) ->
+ client = ron config
+ schema = client.schema name: 'users'
+ # Define properties
+ schema.should.eql schema.property('id', identifier: true)
+ schema.should.eql schema.property('username', unique: true)
+ schema.should.eql schema.property('email', { index: true, email: true })
+ schema.should.eql schema.property('name', {})
+ # Retrieve properties
+ schema.property('id').should.eql { name: 'id', identifier: true, type: 'int' }
+ schema.property('username').should.eql { name: 'username', unique: true }
+ schema.property('email').should.eql { name: 'email', index: true, email: true }
+ schema.property('name').should.eql { name: 'name' }
+ client.quit next
+
+
View
63 test/update.coffee
@@ -6,58 +6,59 @@ Ron = require '../index'
describe 'update', ->
- ron = User = null
+ ron = Users = null
before (next) ->
ron = Ron config
- User = ron.define 'users'
- User.identifier 'user_id'
- User.unique 'username'
- User.index 'email'
+ schema = ron.schema 'users'
+ schema.identifier 'user_id'
+ schema.unique 'username'
+ schema.index 'email'
+ Users = ron.get 'users'
next()
beforeEach (next) ->
- User.clear next
+ Users.clear next
after (next) ->
ron.quit next
describe 'identifier', ->
it 'missing id', (next) ->
- User.update [{email: 'missing@email.com'}], (err, users) ->
+ Users.update [{email: 'missing@email.com'}], (err, users) ->
# Todo, could be "Record without identifier or unique properties
err.message.should.eql 'Invalid object, got {"email":"missing@email.com"}'
- User.clear next
+ Users.clear next
it 'should use unique index and fail because the provided value is not indexed', (next) ->
- User.update [{username: 'missing'}], (err, users) ->
+ Users.update [{username: 'missing'}], (err, users) ->
err.message.should.eql 'Unsaved record'
- User.clear next
+ Users.clear next
describe 'unique', ->
it 'should update a unique value', (next) ->
- User.create
+ Users.create
username: 'my_username'
email: 'my@email.com'
password: 'my_password'
, (err, user) ->
should.not.exist err
user.username = 'new_username'
- User.update user, (err, user) ->
+ Users.update user, (err, user) ->
should.not.exist err
user.username.should.eql 'new_username'
- User.count (err, count) ->
+ Users.count (err, count) ->
count.should.eql 1
- User.get {username: 'my_username'}, (err, user) ->
+ Users.get {username: 'my_username'}, (err, user) ->
should.not.exist user
- User.get {username: 'new_username'}, (err, user) ->
+ Users.get {username: 'new_username'}, (err, user) ->
user.username.should.eql 'new_username'
- User.clear next
+ Users.clear next
it 'should fail to update a unique value that is already defined', (next) ->
- User.create [
+ Users.create [
username: 'my_username_1'
email: 'my@email.com'
password: 'my_password'
@@ -69,48 +70,48 @@ describe 'update', ->
should.not.exist err
user = users[0]
user.username = 'my_username_2'
- User.update user, (err, user) ->
+ Users.update user, (err, user) ->
err.message.should.eql 'Unique value already exists'
- return User.clear next
+ return Users.clear next
describe 'index', ->
it 'should update an indexed property', (next) ->
- User.create {
+ Users.create {
username: 'my_username'
email: 'my@email.com'
password: 'my_password'
}, (err, user) ->
should.not.exist err
user.email = 'new@email.com'