Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Added js-oo

Storage logic moved into connection.js/model.js
Started moving document logic into model compilation
Removed legacy schema/ code
Started moving query writer and promises into query.js
  • Loading branch information...
commit 5cd7b268bf3b73ab307251eea4ad3234a2aab2ab 1 parent 33fb631
Guillermo Rauch authored
2  .gitmodules
@@ -9,4 +9,4 @@
9 9
 	url = git://github.com/visionmedia/expresso.git
10 10
 [submodule "lib/support/js-oo"]
11 11
 	path = lib/support/js-oo
12  
-	url = git://github.com/visionmedia/js-oo.git
  12
+	url = git://github.com/visionmedia/js-oo.git
4  Makefile
... ...
@@ -1,4 +1,6 @@
  1
+SH = sh
1 2
 NODE = node
2 3
 
3 4
 test:
4  
-	@$(NODE) spec/specs.js
  5
+	@$(NODE) tests/unit/run.js
  6
+	# @$(SH) tests/integration/support/expresso/bin/expresso tests/integration/*
2  README.md
Source Rendered
@@ -76,7 +76,7 @@ To fetch some stuff
76 76
 		
77 77
 	});
78 78
 
79  
-### Operating on embeded objects
  79
+### Operating on embedded objects
80 80
 
81 81
 Embedded objects are hydrated like model instances. Assume a MongoDB document like this stored in a variable `user`
82 82
 
103  lib/connection.js
... ...
@@ -0,0 +1,103 @@
  1
+var url = require('url'),
  2
+    mongo = require('mongodb/index'),
  3
+    Model = require('model').Model,
  4
+    Collection = require('mongodb/collection').Collection,
  5
+    EventEmitter = require('events').EventEmitter,
  6
+    InsertCommand = require('./commands/insert_command').InsertCommand,
  7
+
  8
+Connection = this.Connection = Class({
  9
+  
  10
+  include: [EventEmitter.prototype],
  11
+  
  12
+  init: function(base, uri, options){
  13
+    var self = this;
  14
+    this.base = base;
  15
+    this.name = uri.pathname.replace('/', '');
  16
+    this.uri = uri;
  17
+    this.db = new mongo.Db(this.name, new mongo.Server(uri.hostname, uri.port, options));
  18
+    this.db.open(function(err){
  19
+      if (err) return self._error("Can't connect to " + url.format(uri));
  20
+      self.db.collection(function(err, collection){
  21
+        if (err) return self._error(err);
  22
+        self._collection = collection;
  23
+      });
  24
+    });
  25
+    this._compiled = {};
  26
+    this._queued = [];
  27
+    EventEmitter.call(this);
  28
+  },
  29
+  
  30
+  model: function(model){
  31
+    if (name in this._compiled) return this._compiled[name];
  32
+    return this._compile(model);
  33
+  },
  34
+  
  35
+  _error: function(err){
  36
+    this.emit('error', err);
  37
+    return this;
  38
+  },
  39
+  
  40
+  _compile: function(model){
  41
+    var _model = this.base.model(model), _definition;
  42
+    _definition.extend = _model['static'] || {};
  43
+    _definition.include = [Model];
  44
+    _definition.__doc = this._compileProperties(_model.properties);
  45
+    _model = Class(_definition);
  46
+    _model.prototype._connection = _model._connection = this;
  47
+    this._compiled[model] = _model;
  48
+    return _model;
  49
+  },
  50
+  
  51
+  _compileProperties: function(props){
  52
+    var _props = props || [], _ret = {};
  53
+    _props.forEach(function(prop){
  54
+      if (typeof prop == 'string'){
  55
+        _ret[prop] = '';
  56
+      } else if (prop instanceof Array){
  57
+        // inspect first element
  58
+        if (_props[prop].length == 0)
  59
+          throw new Error('Bad `properties` definition. Empty array');
  60
+        if (_props[prop].length > 1)
  61
+          throw new Error('Bad `properties` definition. An array cannot contain multiple elements.');
  62
+        switch (typeof _props[prop][0]){
  63
+          // simply an array
  64
+          case 'string':
  65
+            _ret[_props[prop][0]]
  66
+            break
  67
+          case 'object':
  68
+            break;
  69
+          default:
  70
+            throw new Error('Bad `properties` definition. Array contains illegal element')
  71
+        }
  72
+      }
  73
+    });
  74
+    return _props;
  75
+  },
  76
+  
  77
+  _queue: function(method, args){
  78
+    if (this._collection) return this._collection[method].apply(this._collection, args);
  79
+    this._queued.push([method, args]);
  80
+  },
  81
+  
  82
+  _process: function(){
  83
+    if (this._queued.length){
  84
+      this._queued.forEach(function(m){
  85
+        this._collection[m[0]].apply(this._collection, m[1]);
  86
+      }, this);
  87
+    }
  88
+  },
  89
+  
  90
+  set _collection(collection){
  91
+    this._collection = collection;
  92
+    this._process();
  93
+  }
  94
+  
  95
+});
  96
+
  97
+for (var i in Collection.prototype){
  98
+  if (!(i in Connection.prototype)){
  99
+    Connection.prototype[i] = function(){
  100
+      return this._queue(i, arguments);
  101
+    };
  102
+  }
  103
+}
56  lib/model.js
... ...
@@ -0,0 +1,56 @@
  1
+var query = require('query'),
  2
+    
  3
+Model = this.Model = Class({
  4
+  
  5
+  extend: {
  6
+    find: function(hydrate){
  7
+      this._connection.
  8
+    }
  9
+  },
  10
+  
  11
+  init: function(){
  12
+    this.isNew = true;
  13
+    this.isDirty = false;
  14
+  },
  15
+  
  16
+  _set: function(path){
  17
+    var parts = path.split('.'), doc = this.__doc, dirty = false;
  18
+    for (var i = 0, l = parts.length; i < l; i++){
  19
+      doc = doc[i];
  20
+      if (!dirty && (typeof doc == 'object' || (i + 1 == l))){
  21
+        dirty = true;
  22
+        this._dirty = true;
  23
+      }
  24
+    }
  25
+  },
  26
+  
  27
+  _get: function(path){
  28
+    var parts = path.split('.'), doc = this.__doc;
  29
+    for (var i = 0, l = parts.length; i < l; i++){
  30
+      doc = doc[i];
  31
+      if (typeof doc == 'object' && i + 1 !== l){
  32
+        throw new Error("Can't access " + path);
  33
+      }
  34
+    }
  35
+    return doc;
  36
+  },
  37
+  
  38
+  _hydrate: function(doc){
  39
+    this.isNew = false;
  40
+    Object.merge(this.__doc, doc);
  41
+  },
  42
+  
  43
+  isDirty: function(n){
  44
+    if (typeof n == 'string') return n in this._dirty;
  45
+    return !!Object.keys(this._dirty).length;
  46
+  },
  47
+  
  48
+  toObject: function(){
  49
+    return this.__doc;
  50
+  },
  51
+  
  52
+  save: function(fn){
  53
+    this._connection.save(this.__doc, fn);
  54
+  }
  55
+  
  56
+});
10  lib/query.js
... ...
@@ -0,0 +1,10 @@
  1
+this.Writer = Class({
  2
+  
  3
+  
  4
+});
  5
+
  6
+this.Promise = Class({
  7
+  
  8
+  
  9
+  
  10
+});
15  lib/schema/index.js
... ...
@@ -1,15 +0,0 @@
1  
-
2  
-var Type = require('./type').Type,
3  
-    Validator = require('./validator').Validator,
4  
-    
5  
-    Schema = function(instance){
6  
-      this.mongoose = instance;
7  
-      this.Type = new Type(instance);
8  
-      this.Validator = new Validator(instance);
9  
-    };
10  
-    
11  
-    Schema.prototype = {
12  
-      
13  
-    };
14  
-    
15  
-this.Schema = Schema;
15  lib/schema/type.js
... ...
@@ -1,15 +0,0 @@
1  
-
2  
-var Type = function(instance){
3  
-  this.mongoose = instance;
4  
-  this.mongoose.addDefiner('type',this);
5  
-}
6  
-
7  
-Type.prototype = {
8  
-  
9  
-  define : function(type){
10  
-    
11  
-  }
12  
-  
13  
-}
14  
-
15  
-this.Type = Type;
15  lib/schema/validator.js
... ...
@@ -1,15 +0,0 @@
1  
-
2  
-var Validator = function(instance){
3  
-  this.mongoose = instance;
4  
-  this.mongoose.addDefiner('validator',this);
5  
-}
6  
-
7  
-Validator.prototype = {
8  
-  
9  
-  define : function(validation){
10  
-    
11  
-  }
12  
-  
13  
-}
14  
-
15  
-this.Validator = Validator;
137  lib/storage.js
... ...
@@ -1,137 +0,0 @@
1  
-
2  
-var mongo = require('mongodb/'),
3  
-    object = require('./utils/object'),
4  
-    Model = require('./model').Model,
5  
-    EventEmitter = require('events').EventEmitter,
6  
-    sys = require('sys'),
7  
-    instances = 0,
8  
-
9  
-    Storage = exports.Storage = function(instance,conn,options){
10  
-
11  
-      this.id = ++instances;
12  
-      this.conn = conn;
13  
-      this.mongoose = instance;
14  
-
15  
-      this.db = this.getDatabaseInstance(options);
16  
-
17  
-      EventEmitter.call(this);
18  
-      var self = this;
19  
-      this.db.open(function(err,connection){
20  
-        if(err) self.emit('error',err);
21  
-        self.loaded = (err) ? false : connection;
22  
-        self.dequeue();
23  
-      });
24  
-
25  
-      return this;
26  
-    };
27  
-
28  
-    Storage.prototype = {
29  
-  
30  
-        loaded : false,
31  
-        halted : false,
32  
-        collections : {},
33  
-        buffer : [],
34  
-  
35  
-        getDatabaseInstance : function(options){
36  
-          var conn = this.conn,
37  
-              options = options || {};
38  
-
39  
-          if(conn[0].type != 'mongodb'){
40  
-            this.emit('error','Must use mongodb:// in uri connection string');
41  
-            return false;
42  
-          }
43  
-    
44  
-          if(conn.length == 1){ // simple (single server)
45  
-              return new mongo.Db(conn[0].db, new mongo.Server(conn[0].host, (conn[0].port || 27017), options),{});
46  
-          }
47  
-          else if(conn.length == 2) // server pair
48  
-              return new mongo.Db(conn[0].db, new mongo.ServerPair(
49  
-                new mongo.Server(conn[0].host, conn[0].port || 27017, options),
50  
-                new mongo.Server(conn[1].host, conn[1].port || 27017, options)
51  
-              ));
52  
-          else // cluster (master and multiple slaves)
53  
-            return new mongo.Db(conn[0].db, new mongo.ServerCluster(
54  
-              conn.map(function(server){
55  
-                return new mongo.Server(server.host, server.port || 27017, options);
56  
-              })
57  
-            ));          
58  
-        },
59  
-  
60  
-        dequeue : function(){
61  
-          if(!this.buffer.length || !this.loaded || this.halted) return;
62  
-    
63  
-          var op = this.buffer.shift();
64  
-          if(op.name == 'collection'){
65  
-            var self = this;
66  
-            op.args.push(function(err,aCollection){
67  
-              if(err) self.emit('error',err);
68  
-              else {
69  
-                self.collections[aCollection.collectionName] = aCollection;
70  
-                op.callback(aCollection);
71  
-              }
72  
-            }); 
73  
-          }
74  
-          else op.args.push(op.callback || function(){});
75  
-    
76  
-          this.db[op.name].apply(this.db,op.args);
77  
-          this.dequeue();
78  
-        },
79  
-        
80  
-        static : function(model){
81  
-          return this.mongoose.get(model,this);
82  
-        },
83  
-        
84  
-        use : function(collection){
85  
-          return this.mongoose.get(collection,this,true);
86  
-        },
87  
-        
88  
-        noSchema : function(collection){
89  
-          return Model.load(collection, this, {noSchema : true});
90  
-        },
91  
-
92  
-        collection : function(){ return this._cmd('collection',Array.prototype.slice.call(arguments,0)); },
93  
-        close : function(){ return this._cmd('close', Array.prototype.slice.call(arguments,0)); },
94  
-        dropCollection : function(){ return this._cmd('dropCollection', Array.prototype.slice.call(arguments,0)); },
95  
-        
96  
-        _cmd : function(cmd,args){
97  
-          var operation = { 
98  
-                name : cmd,
99  
-                callback : (args.length) ? ( (args[args.length-1] instanceof Function) ? args.pop() : null ) : null,
100  
-                args : args 
101  
-              };
102  
-        
103  
-          this.buffer.push(operation);
104  
-          this.dequeue();
105  
-        },
106  
-  
107  
-        halt : function(){
108  
-          this.halted = true;
109  
-          return this;
110  
-        },
111  
-  
112  
-        resume : function(){
113  
-          this.halted = false;
114  
-          this.dequeue();
115  
-          return this;
116  
-        },
117  
-  
118  
-        clear : function(){
119  
-          this.buffer = [];
120  
-          return this;
121  
-        },
122  
-        
123  
-        close : function(){
124  
-          this.halt();
125  
-          this.clear();
126  
-          for(col in this.collections){
127  
-            this.collections[col].close(function(){});
128  
-            delete this.collections[col];
129  
-          }
130  
-          this.db.close(function(){});
131  
-          delete this.db;
132  
-          this.loaded = false;
133  
-        }
134  
-    };
135  
-
136  
-    Storage.prototype.loadModel = Storage.prototype.bindModel; // alias
137  
-    object.merge(Storage.prototype, EventEmitter.prototype);
1  lib/support/js-oo
... ...
@@ -0,0 +1 @@
  1
+Subproject commit 1f94bd897994a952114cb1f280c1949d5e6a0648
41  mongoose.js
... ...
@@ -1,7 +1,42 @@
1  
-require.paths.push(__dirname + "/lib/support/node-mongodb-native/lib");
  1
+require.paths.push(__dirname + '/lib/support/node-mongodb-native/lib');
  2
+require('lib/support/js-oo/lib/oo.js');
2 3
 
3  
-this.Mongoose = Class({
  4
+var sys = require('sys'),
  5
+    url = require('url'),
  6
+    Connection = require('lib/connection').Connection,
  7
+    EventEmitter = require('events').EventEmitter;
  8
+
  9
+Mongoose = this.Mongoose = {
  10
+  
  11
+  _models: {},
  12
+  
  13
+  connect: function(uri, options){
  14
+    var _uri = url.parse(uri);
  15
+    _uri.port = _uri.port || 27017;
  16
+    return this._lookup(_uri) || this._open(_uri, options);
  17
+  },
4 18
   
  19
+  model: function(name, definition){
  20
+    if (definition){
  21
+      this._models[name] = definition;
  22
+    } else {
  23
+      return this._models[name];
  24
+    }
  25
+  },
5 26
   
  27
+  _open: function(uri, options){
  28
+    var connection = new Connection(this, uri, options);
  29
+    this._connections[url.format(uri)] = connection;
  30
+    return connection;
  31
+  },
6 32
   
7  
-});
  33
+  _lookup: function(uri){
  34
+    var _uri = url.format(uri);
  35
+    if (_uri in this._connections) return this._connections[_uri];
  36
+    return false;
  37
+  }
  38
+  
  39
+};
  40
+
  41
+sys.inherits(Mongoose, EventEmitter.prototype);
  42
+EventEmitter.call(Mongoose);
1  tests/integration/support/expresso
... ...
@@ -0,0 +1 @@
  1
+Subproject commit 08ea1b7d8176a6ad210df69dc4e2c40b99a431a5
1  tests/unit/support/jspec
... ...
@@ -0,0 +1 @@
  1
+Subproject commit df48355d3a5ff11bdd28ea0a2c2ee5bf7064e49c

0 notes on commit 5cd7b26

Please sign in to comment.
Something went wrong with that request. Please try again.