Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

init

  • Loading branch information...
commit 0a7a5fef383f069eb777c549f69bf9c30fa1e3ca 0 parents
@vdemedes authored
3  .gitignore
@@ -0,0 +1,3 @@
+.DS_Store
+node_modules
+*.sock
4 .npmignore
@@ -0,0 +1,4 @@
+support
+test
+examples
+*.sock
70 Readme.md
@@ -0,0 +1,70 @@
+# Mongorito
+
+*Awesome* MongoDB ODM for Node.js. Just take a look on its pretty models. Uses Mongolian for interacting with MongoDB.
+
+# Installation
+
+```
+npm install mongorito
+```
+
+# Usage
+
+```coffee-script
+Mongorito = require 'mongorito'
+
+Mongorito.connect 'database', ['127.0.0.1:27017'], 'user', 'password'
+
+class Post extends Mongorito.Model
+ constructor: ->
+ super 'posts' # telling our collection name
+
+Post = Mongorito.bake Post # Now, we are ready to go!
+
+post = new Post
+post.title = 'Very interesting article.'
+post.content = 'Really, really, exciting.'
+post.save (err) ->
+ # saved!
+
+ post.title = 'Edited title!'
+ post.save (err) ->
+ # updated!
+
+ post.remove ->
+ # removed!
+
+Post.find { title : 'Some title!' }, (err, posts) ->
+ for post in posts
+ # post is an instance of Post model, so you can perform usual methods on it
+ post.remove ->
+```
+
+# Interested?
+
+Check out **examples** folder, it has a lot of code, which describes all parts of Mongorito.
+
+# License
+
+(The MIT License)
+
+Copyright (c) 2011 Vadim Demedes <sbioko@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
3  examples/connection.coffee
@@ -0,0 +1,3 @@
+Mongorito = require '../lib/mongorito'
+
+Mongorito.connect 'databaseName', ['127.0.0.1:27017']
5 examples/connection.js
@@ -0,0 +1,5 @@
+var Mongorito;
+
+Mongorito = require('../lib/mongorito');
+
+Mongorito.connect('databaseName', ['127.0.0.1:27017']);
9 examples/definition.coffee
@@ -0,0 +1,9 @@
+Mongorito = require '../lib/mongorito'
+
+Mongorito.connect 'databaseName', ['127.0.0.1:27017']
+
+class Post extends Mongorito.Model
+ constructor: ->
+ super 'posts' # REQUIRED STEP
+
+Post = Mongorito.bake Post # REQUIRED STEP
21 examples/definition.js
@@ -0,0 +1,21 @@
+var Mongorito, Post,
+ __hasProp = Object.prototype.hasOwnProperty,
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; };
+
+Mongorito = require('../lib/mongorito');
+
+Mongorito.connect('databaseName', ['127.0.0.1:27017']);
+
+Post = (function(_super) {
+
+ __extends(Post, _super);
+
+ function Post() {
+ Post.__super__.constructor.call(this, 'posts');
+ }
+
+ return Post;
+
+})(Mongorito.Model);
+
+Post = Mongorito.bake(Post);
21 examples/hooks.coffee
@@ -0,0 +1,21 @@
+Mongorito = require '../lib/mongorito'
+
+Mongorito.connect 'databaseName', ['127.0.0.1:27017']
+
+class Post extends Mongorito.Model
+ constructor: ->
+ super 'posts'
+
+ beforeCreate: -> # before creating post
+
+ aroundCreate: -> # before and after creating post
+
+ afterCreate: -> # after creating post
+
+ beforeUpdate: -> # before updating post
+
+ aroundUpdate: -> # before and after updating post
+
+ afterUpdate: -> # after updating post
+
+Post = Mongorito.bake Post
33 examples/hooks.js
@@ -0,0 +1,33 @@
+var Mongorito, Post,
+ __hasProp = Object.prototype.hasOwnProperty,
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; };
+
+Mongorito = require('../lib/mongorito');
+
+Mongorito.connect('databaseName', ['127.0.0.1:27017']);
+
+Post = (function(_super) {
+
+ __extends(Post, _super);
+
+ function Post() {
+ Post.__super__.constructor.call(this, 'posts');
+ }
+
+ Post.prototype.beforeCreate = function() {};
+
+ Post.prototype.aroundCreate = function() {};
+
+ Post.prototype.afterCreate = function() {};
+
+ Post.prototype.beforeUpdate = function() {};
+
+ Post.prototype.aroundUpdate = function() {};
+
+ Post.prototype.afterUpdate = function() {};
+
+ return Post;
+
+})(Mongorito.Model);
+
+Post = Mongorito.bake(Post);
26 examples/operations.coffee
@@ -0,0 +1,26 @@
+Mongorito = require '../lib/mongorito'
+
+Mongorito.connect 'databaseName', ['127.0.0.1:27017']
+
+class Post extends Mongorito.Model
+ constructor: ->
+ super 'posts'
+
+Post = Mongorito.bake Post
+
+# Creating new post
+post = new Post
+post.title = 'Title of the post'
+post.content = 'Content of the post'
+post.save (err, results) ->
+ # results will be populated with invalid fields, if validators will be defined
+
+# Updating post
+
+post.title = 'Changed title of the previously saved post'
+post.save (err, results) ->
+ # results will be populated with invalid fields, if validators will be defined
+
+# Removing post
+
+post.remove (err) ->
35 examples/operations.js
@@ -0,0 +1,35 @@
+var Mongorito, Post, post,
+ __hasProp = Object.prototype.hasOwnProperty,
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; };
+
+Mongorito = require('../lib/mongorito');
+
+Mongorito.connect('databaseName', ['127.0.0.1:27017']);
+
+Post = (function(_super) {
+
+ __extends(Post, _super);
+
+ function Post() {
+ Post.__super__.constructor.call(this, 'posts');
+ }
+
+ return Post;
+
+})(Mongorito.Model);
+
+Post = Mongorito.bake(Post);
+
+post = new Post;
+
+post.title = 'Title of the post';
+
+post.content = 'Content of the post';
+
+post.save(function(err, results) {});
+
+post.title = 'Changed title of the previously saved post';
+
+post.save(function(err, results) {});
+
+post.remove(function(err) {});
31 examples/queries.coffee
@@ -0,0 +1,31 @@
+Mongorito = require '../lib/mongorito'
+
+Mongorito.connect 'databaseName', ['127.0.0.1:27017']
+
+class Post extends Mongorito.Model
+ constructor: ->
+ super 'posts'
+
+Post = Mongorito.bake Post
+
+Post.find (err, posts) ->
+ for post in posts
+ console.log post.title # post is a Post model, so you can perform all usual operations
+
+Post.find { title: 'Nice title!' }, (err, posts) ->
+
+Post.findWithLimit 5, (err, posts) -> # getting only first 5 posts
+
+Post.findWithLimit { author: 'Drew' }, 5, (err, posts) -> # getting only first 5 posts with author = Drew
+
+Post.findWithLimit 5, 2, (err, posts) -> # getting only 5 posts, skipping first 2
+
+Post.findWithLimit { author: 'Drew' }, 5, 2, (err, posts) -> # getting only 5 posts, skipping first 2, with author = Drew
+
+Post.findWithOrder { _id: -1 }, (err, posts) -> # getting posts, sorted by _id
+
+Post.findWithOrderAndLimit { _id: -1 }, 5, (err, posts) -> # getting first 5 posts, sorted by _id
+
+Post.findWithOrderAndLimit { _id: -1 }, 5, 2, (err, posts) -> # getting 5 posts, skipping first 2, sorted by _id
+
+Post.findWithOrderAndLimit { author: 'Drew' }, { _id: -1 }, 5, 2, (err, posts) -> # getting 5 posts, skipping first 2, sorted by _id, with author = Drew
65 examples/queries.js
@@ -0,0 +1,65 @@
+var Mongorito, Post,
+ __hasProp = Object.prototype.hasOwnProperty,
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; };
+
+Mongorito = require('../lib/mongorito');
+
+Mongorito.connect('databaseName', ['127.0.0.1:27017']);
+
+Post = (function(_super) {
+
+ __extends(Post, _super);
+
+ function Post() {
+ Post.__super__.constructor.call(this, 'posts');
+ }
+
+ return Post;
+
+})(Mongorito.Model);
+
+Post = Mongorito.bake(Post);
+
+Post.find(function(err, posts) {
+ var post, _i, _len, _results;
+ _results = [];
+ for (_i = 0, _len = posts.length; _i < _len; _i++) {
+ post = posts[_i];
+ _results.push(console.log(post.title));
+ }
+ return _results;
+});
+
+Post.find({
+ title: 'Nice title!'
+}, function(err, posts) {});
+
+Post.findWithLimit(5, function(err, posts) {});
+
+Post.findWithLimit({
+ author: 'Drew'
+}, 5, function(err, posts) {});
+
+Post.findWithLimit(5, 2, function(err, posts) {});
+
+Post.findWithLimit({
+ author: 'Drew'
+}, 5, 2, function(err, posts) {});
+
+Post.findWithOrder({
+ _id: -1
+}, function(err, posts) {});
+
+Post.findWithOrderAndLimit({
+ _id: -1
+}, 5, function(err, posts) {});
+
+Post.findWithOrderAndLimit({
+ _id: -1
+}, 5, 2, function(err, posts) {});
+
+Post.findWithOrderAndLimit({
+ author: 'Drew'
+}, {
+ _id: -1
+}, 5, 2, function(err, posts) {});
20 examples/validations.coffee
@@ -0,0 +1,20 @@
+Mongorito = require '../lib/mongorito'
+
+Mongorito.connect 'databaseName', ['127.0.0.1:27017']
+
+class Tweet extends Mongorito.Model
+ constructor: ->
+ super 'tweets'
+
+ validateBody: (callback) -> # you should pass false, if invalid and true, if valid
+ if @body.length >= 140
+ callback false
+ else
+ callback true
+
+Tweet = Mongorito.bake Tweet
+
+tweet = new Tweet
+tweet.body = 'I want to be super-super-super-super long! Reallly, reallly, long!!!! In fact, I am VEEERY long! You\'ve never seen such a looooooong tweeeeeet!'
+tweet.save (err, results) ->
+ # results will be ['body'], because body field did not pass validation
35 examples/validations.js
@@ -0,0 +1,35 @@
+var Mongorito, Tweet, tweet,
+ __hasProp = Object.prototype.hasOwnProperty,
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; };
+
+Mongorito = require('../lib/mongorito');
+
+Mongorito.connect('databaseName', ['127.0.0.1:27017']);
+
+Tweet = (function(_super) {
+
+ __extends(Tweet, _super);
+
+ function Tweet() {
+ Tweet.__super__.constructor.call(this, 'tweets');
+ }
+
+ Tweet.prototype.validateBody = function(callback) {
+ if (this.body.length >= 140) {
+ return callback(false);
+ } else {
+ return callback(true);
+ }
+ };
+
+ return Tweet;
+
+})(Mongorito.Model);
+
+Tweet = Mongorito.bake(Tweet);
+
+tweet = new Tweet;
+
+tweet.body = 'I want to be super-super-super-super long! Reallly, reallly, long!!!! In fact, I am VEEERY long! You\'ve never seen such a looooooong tweeeeeet!';
+
+tweet.save(function(err, results) {});
2  index.js
@@ -0,0 +1,2 @@
+
+module.exports = require('./lib/mongorito');
286 lib/mongorito.coffee
@@ -0,0 +1,286 @@
+mongolian = require 'mongolian'
+async = require 'async'
+Client = undefined
+
+`String.prototype.plural = function() {
+ var s = this.trim().toLowerCase();
+ end = s.substr(-1);
+ if(end == 'y') {
+ var vowels = ['a', 'e', 'i', 'o', 'u'];
+ s = s.substr(-2, 1) in vowels ? s + 's' : s.substr(0, s.length-1) + 'ies';
+ } else if(end == 'h') {
+ s += s.substr(-2) == 'ch' || s.substr(-2) == 'sh' ? 'es' : 's';
+ } else if(end == 's') {
+ s += 'es';
+ } else {
+ s += 's';
+ }
+ return s;
+}
+
+String.prototype.singular = function() {
+ var s = this.trim().toLowerCase();
+ var end = s.substr(-3);
+ if(end == 'ies') {
+ s = s.substr(0, s.length-3) + 'y';
+ } else if(end == 'ses') {
+ s = s.substr(0, s.length-2);
+ } else {
+ end = s.substr(-1);
+ if(end == 's') {
+ s = s.substr(0, s.length-1);
+ }
+ }
+ return s;
+}
+
+String.prototype.camelize = function() {
+ var s = 'x_' + this.trim().toLowerCase();
+ s = s.replace(/[\s_]/g, ' ');
+ s = s.replace(/^(.)|\s(.)/g, function($1) {
+ return $1.toUpperCase();
+ });
+ return s.replace(/ /g, '').substr(1);
+}
+
+String.prototype.underscore = function() {
+ return this.trim().toLowerCase().replace(/[\s]+/g, '_');
+}`
+
+class Mongorito
+ @disconnect: ->
+ do Client.close
+ @connect: (database = '', servers = [], username = '', password = '') ->
+ if servers.length is 1
+ server = new mongolian servers[0]
+ Client = server.db database
+ Client.log=
+ debug: ->
+ info: ->
+ warn: ->
+ error: ->
+ Client.auth username, password if username
+ else
+ # Support comes soon to Replica Sets
+ server = new mongolian servers[0]
+ Client = server.db database
+ Client.log=
+ debug: ->
+ info: ->
+ warn: ->
+ error: ->
+ Client.auth username, password if username
+
+ @bake: (model) ->
+ object = new model
+ model.collection = object.collection
+ model.model = model
+
+class MongoritoModel
+ constructor: (@collection = '') ->
+
+ fields: ->
+ notFields = ['constructor', 'save', 'collection', 'create', 'fields', 'update', 'remove']
+ fields = {}
+ for field of @
+ fields[field] = @[field] if -1 is notFields.indexOf field
+ fields
+
+ @findById: (id, callback) ->
+ that = @
+
+ Client.collection(@collection).find({ _id: new mongolian.ObjectId(id.toString()) }).toArray (err, item) ->
+ if item.length is 0
+ item = item[0]
+ item._id = item._id.toString()
+ model = new that.model
+ model.collection = that.collection
+ for field of item
+ model[field] = item[field]
+ else
+ model = no
+
+ process.nextTick ->
+ callback err, model
+
+ @findWithOrderAndLimit: (criteria, order, limit, skip, callback) ->
+ if typeof criteria is 'object'
+ if typeof order is 'number'
+ if typeof limit is 'function'
+ callback = limit
+ limit = order
+ order = criteria
+ criteria = {}
+ if typeof limit is 'number'
+ if typeof skip is 'function'
+ callback = skip
+ skip = limit
+ limit = order
+ order = criteria
+ criteria = {}
+
+ skip = 0 if not skip
+ that = @
+
+ Client.collection(@collection).find(criteria).sort(order).limit(limit).skip(skip).toArray (err, items) ->
+ models = []
+ for item in items
+ item._id = item._id.toString()
+ model = new that.model
+ model.collection = that.collection
+ for field of item
+ model[field] = item[field]
+ models.push model
+
+ process.nextTick ->
+ callback err, models
+
+ @findWithOrder: (criteria, order, callback) ->
+ if typeof criteria is 'object' and typeof order is 'function'
+ callback = order
+ order = criteria
+ criteria = {}
+ order = { _id: -1 }
+
+ that = @
+
+ Client.collection(@collection).find(criteria).sort(order).toArray (err, items) ->
+ models = []
+ for item in items
+ item._id = item._id.toString()
+ model = new that.model
+ model.collection = that.collection
+ for field of item
+ model[field] = item[field]
+ models.push model
+
+ process.nextTick ->
+ callback err, models
+
+ @findWithLimit: (criteria, limit, skip, callback) ->
+ if typeof criteria is 'number'
+ if typeof limit is 'function'
+ callback = limit
+ limit = criteria
+ criteria = {}
+ if typeof limit is 'number'
+ if typeof skip is 'function'
+ callback = skip
+ skip = limit
+ criteria = {}
+ else
+ if typeof limit is 'function'
+ callback = limit
+ limit = 10
+ if typeof skip is 'function'
+ callback = skip
+ skip = 0
+
+ that = @
+
+ Client.collection(@collection).find(criteria).limit(limit).skip(skip).toArray (err, items) ->
+ models = []
+ for item in items
+ item._id = item._id.toString()
+ model = new that.model
+ model.collection = that.collection
+ for field of item
+ model[field] = item[field]
+ models.push model
+
+ process.nextTick ->
+ callback err, models
+
+ @find: (criteria = {}, callback) ->
+ if typeof(criteria) is 'function'
+ callback = criteria
+ criteria = {}
+
+ that = @
+
+ Client.collection(@collection).find(criteria).toArray (err, items) ->
+ models = []
+ for item in items
+ item._id = item._id.toString()
+ model = new that.model
+ model.collection = that.collection
+ for field of item
+ model[field] = item[field]
+ models.push model
+
+ process.nextTick ->
+ callback err, models
+
+ save: (callback) ->
+ that = @
+ fields = @fields
+
+ notFields = ['constructor', 'save', 'collection', 'create', 'fields', 'update', 'remove', 'models']
+ keys = []
+ for field of @
+ keys.push field if -1 is notFields.indexOf field
+
+ async.filter keys, (key, nextKey) ->
+ if that["validate#{ key.camelize() }"]
+ that["validate#{ key.camelize() }"] (valid) ->
+ nextKey not valid
+ else
+ nextKey false
+ , (results) ->
+ return callback yes, results if results.length > 0
+
+ if fields._id
+ that.update callback, yes
+ else
+ that.create callback, yes
+
+ create: (callback, fromSave = no) ->
+ object = @fields()
+
+ do @beforeCreate if @['beforeCreate']
+ do @aroundCreate if @['aroundCreate']
+ that = @
+
+ Client.collection(@collection).insert object, (err, result) ->
+ result._id = result._id.toString()
+ that._id = result._id
+ do that.aroundCreate if that['aroundCreate']
+ do that.afterCreate if that['afterCreate']
+ process.nextTick ->
+ callback err, result if callback
+
+ update: (callback, fromSave = no) ->
+ object = @fields()
+ _id = new mongolian.ObjectId object._id
+ delete object._id
+
+ do @beforeUpdate if @['beforeUpdate']
+ do @aroundUpdate if @['aroundUpdate']
+ that = @
+
+ Client.collection(@collection).update { _id: _id }, object, (err, rowsUpdated) ->
+ do that.aroundUpdate if that['aroundUpdate']
+ do that.afterUpdate if that['afterUpdate']
+ process.nextTick ->
+ callback err, rowsUpdated if callback
+
+ remove: (callback) ->
+ object = @fields()
+
+ _id = new mongolian.ObjectId object._id
+
+ do @beforeRemove if @['beforeRemove']
+ do @aroundRemove if @['aroundRemove']
+ that = @
+
+ Client.collection(@collection).remove { _id: _id }, (err) ->
+ do that.aroundRemove if that['aroundRemove']
+ do that.afterRemove if that['afterRemove']
+ process.nextTick ->
+ callback err if callback
+
+module.exports=
+ connect: Mongorito.connect
+ disconnect: Mongorito.disconnect
+ bake: Mongorito.bake
+ Model: MongoritoModel
378 lib/mongorito.js
@@ -0,0 +1,378 @@
+var Client, Mongorito, MongoritoModel, async, mongolian;
+
+mongolian = require('mongolian');
+
+async = require('async');
+
+Client = void 0;
+
+String.prototype.plural = function() {
+ var s = this.trim().toLowerCase();
+ end = s.substr(-1);
+ if(end == 'y') {
+ var vowels = ['a', 'e', 'i', 'o', 'u'];
+ s = s.substr(-2, 1) in vowels ? s + 's' : s.substr(0, s.length-1) + 'ies';
+ } else if(end == 'h') {
+ s += s.substr(-2) == 'ch' || s.substr(-2) == 'sh' ? 'es' : 's';
+ } else if(end == 's') {
+ s += 'es';
+ } else {
+ s += 's';
+ }
+ return s;
+}
+
+String.prototype.singular = function() {
+ var s = this.trim().toLowerCase();
+ var end = s.substr(-3);
+ if(end == 'ies') {
+ s = s.substr(0, s.length-3) + 'y';
+ } else if(end == 'ses') {
+ s = s.substr(0, s.length-2);
+ } else {
+ end = s.substr(-1);
+ if(end == 's') {
+ s = s.substr(0, s.length-1);
+ }
+ }
+ return s;
+}
+
+String.prototype.camelize = function() {
+ var s = 'x_' + this.trim().toLowerCase();
+ s = s.replace(/[\s_]/g, ' ');
+ s = s.replace(/^(.)|\s(.)/g, function($1) {
+ return $1.toUpperCase();
+ });
+ return s.replace(/ /g, '').substr(1);
+}
+
+String.prototype.underscore = function() {
+ return this.trim().toLowerCase().replace(/[\s]+/g, '_');
+};
+
+Mongorito = (function() {
+
+ function Mongorito() {}
+
+ Mongorito.disconnect = function() {
+ return Client.close();
+ };
+
+ Mongorito.connect = function(database, servers, username, password) {
+ var server;
+ if (database == null) database = '';
+ if (servers == null) servers = [];
+ if (username == null) username = '';
+ if (password == null) password = '';
+ if (servers.length === 1) {
+ server = new mongolian(servers[0]);
+ Client = server.db(database);
+ Client.log = {
+ debug: function() {},
+ info: function() {},
+ warn: function() {},
+ error: function() {}
+ };
+ if (username) return Client.auth(username, password);
+ } else {
+ server = new mongolian(servers[0]);
+ Client = server.db(database);
+ Client.log = {
+ debug: function() {},
+ info: function() {},
+ warn: function() {},
+ error: function() {}
+ };
+ if (username) return Client.auth(username, password);
+ }
+ };
+
+ Mongorito.bake = function(model) {
+ var object;
+ object = new model;
+ model.collection = object.collection;
+ return model.model = model;
+ };
+
+ return Mongorito;
+
+})();
+
+MongoritoModel = (function() {
+
+ function MongoritoModel(collection) {
+ this.collection = collection != null ? collection : '';
+ }
+
+ MongoritoModel.prototype.fields = function() {
+ var field, fields, notFields;
+ notFields = ['constructor', 'save', 'collection', 'create', 'fields', 'update', 'remove'];
+ fields = {};
+ for (field in this) {
+ if (-1 === notFields.indexOf(field)) fields[field] = this[field];
+ }
+ return fields;
+ };
+
+ MongoritoModel.findById = function(id, callback) {
+ var that;
+ that = this;
+ return Client.collection(this.collection).find({
+ _id: new mongolian.ObjectId(id.toString())
+ }).toArray(function(err, item) {
+ var field, model;
+ if (item.length === 0) {
+ item = item[0];
+ item._id = item._id.toString();
+ model = new that.model;
+ model.collection = that.collection;
+ for (field in item) {
+ model[field] = item[field];
+ }
+ } else {
+ model = false;
+ }
+ return process.nextTick(function() {
+ return callback(err, model);
+ });
+ });
+ };
+
+ MongoritoModel.findWithOrderAndLimit = function(criteria, order, limit, skip, callback) {
+ var that;
+ if (typeof criteria === 'object') {
+ if (typeof order === 'number') {
+ if (typeof limit === 'function') {
+ callback = limit;
+ limit = order;
+ order = criteria;
+ criteria = {};
+ }
+ if (typeof limit === 'number') {
+ if (typeof skip === 'function') {
+ callback = skip;
+ skip = limit;
+ limit = order;
+ order = criteria;
+ criteria = {};
+ }
+ }
+ }
+ }
+ if (!skip) skip = 0;
+ that = this;
+ return Client.collection(this.collection).find(criteria).sort(order).limit(limit).skip(skip).toArray(function(err, items) {
+ var field, item, model, models, _i, _len;
+ models = [];
+ for (_i = 0, _len = items.length; _i < _len; _i++) {
+ item = items[_i];
+ item._id = item._id.toString();
+ model = new that.model;
+ model.collection = that.collection;
+ for (field in item) {
+ model[field] = item[field];
+ }
+ models.push(model);
+ }
+ return process.nextTick(function() {
+ return callback(err, models);
+ });
+ });
+ };
+
+ MongoritoModel.findWithOrder = function(criteria, order, callback) {
+ var that;
+ if (typeof criteria === 'object' && typeof order === 'function') {
+ callback = order;
+ order = criteria;
+ criteria = {};
+ order = {
+ _id: -1
+ };
+ }
+ that = this;
+ return Client.collection(this.collection).find(criteria).sort(order).toArray(function(err, items) {
+ var field, item, model, models, _i, _len;
+ models = [];
+ for (_i = 0, _len = items.length; _i < _len; _i++) {
+ item = items[_i];
+ item._id = item._id.toString();
+ model = new that.model;
+ model.collection = that.collection;
+ for (field in item) {
+ model[field] = item[field];
+ }
+ models.push(model);
+ }
+ return process.nextTick(function() {
+ return callback(err, models);
+ });
+ });
+ };
+
+ MongoritoModel.findWithLimit = function(criteria, limit, skip, callback) {
+ var that;
+ if (typeof criteria === 'number') {
+ if (typeof limit === 'function') {
+ callback = limit;
+ limit = criteria;
+ criteria = {};
+ }
+ if (typeof limit === 'number') {
+ if (typeof skip === 'function') {
+ callback = skip;
+ skip = limit;
+ criteria = {};
+ }
+ }
+ } else {
+ if (typeof limit === 'function') {
+ callback = limit;
+ limit = 10;
+ }
+ if (typeof skip === 'function') {
+ callback = skip;
+ skip = 0;
+ }
+ }
+ that = this;
+ return Client.collection(this.collection).find(criteria).limit(limit).skip(skip).toArray(function(err, items) {
+ var field, item, model, models, _i, _len;
+ models = [];
+ for (_i = 0, _len = items.length; _i < _len; _i++) {
+ item = items[_i];
+ item._id = item._id.toString();
+ model = new that.model;
+ model.collection = that.collection;
+ for (field in item) {
+ model[field] = item[field];
+ }
+ models.push(model);
+ }
+ return process.nextTick(function() {
+ return callback(err, models);
+ });
+ });
+ };
+
+ MongoritoModel.find = function(criteria, callback) {
+ var that;
+ if (criteria == null) criteria = {};
+ if (typeof criteria === 'function') {
+ callback = criteria;
+ criteria = {};
+ }
+ that = this;
+ return Client.collection(this.collection).find(criteria).toArray(function(err, items) {
+ var field, item, model, models, _i, _len;
+ models = [];
+ for (_i = 0, _len = items.length; _i < _len; _i++) {
+ item = items[_i];
+ item._id = item._id.toString();
+ model = new that.model;
+ model.collection = that.collection;
+ for (field in item) {
+ model[field] = item[field];
+ }
+ models.push(model);
+ }
+ return process.nextTick(function() {
+ return callback(err, models);
+ });
+ });
+ };
+
+ MongoritoModel.prototype.save = function(callback) {
+ var field, fields, keys, notFields, that;
+ that = this;
+ fields = this.fields;
+ notFields = ['constructor', 'save', 'collection', 'create', 'fields', 'update', 'remove', 'models'];
+ keys = [];
+ for (field in this) {
+ if (-1 === notFields.indexOf(field)) keys.push(field);
+ }
+ return async.filter(keys, function(key, nextKey) {
+ if (that["validate" + (key.camelize())]) {
+ return that["validate" + (key.camelize())](function(valid) {
+ return nextKey(!valid);
+ });
+ } else {
+ return nextKey(false);
+ }
+ }, function(results) {
+ if (results.length > 0) return callback(true, results);
+ if (fields._id) {
+ return that.update(callback, true);
+ } else {
+ return that.create(callback, true);
+ }
+ });
+ };
+
+ MongoritoModel.prototype.create = function(callback, fromSave) {
+ var object, that;
+ if (fromSave == null) fromSave = false;
+ object = this.fields();
+ if (this['beforeCreate']) this.beforeCreate();
+ if (this['aroundCreate']) this.aroundCreate();
+ that = this;
+ return Client.collection(this.collection).insert(object, function(err, result) {
+ result._id = result._id.toString();
+ that._id = result._id;
+ if (that['aroundCreate']) that.aroundCreate();
+ if (that['afterCreate']) that.afterCreate();
+ return process.nextTick(function() {
+ if (callback) return callback(err, result);
+ });
+ });
+ };
+
+ MongoritoModel.prototype.update = function(callback, fromSave) {
+ var object, that, _id;
+ if (fromSave == null) fromSave = false;
+ object = this.fields();
+ _id = new mongolian.ObjectId(object._id);
+ delete object._id;
+ if (this['beforeUpdate']) this.beforeUpdate();
+ if (this['aroundUpdate']) this.aroundUpdate();
+ that = this;
+ return Client.collection(this.collection).update({
+ _id: _id
+ }, object, function(err, rowsUpdated) {
+ if (that['aroundUpdate']) that.aroundUpdate();
+ if (that['afterUpdate']) that.afterUpdate();
+ return process.nextTick(function() {
+ if (callback) return callback(err, rowsUpdated);
+ });
+ });
+ };
+
+ MongoritoModel.prototype.remove = function(callback) {
+ var object, that, _id;
+ object = this.fields();
+ _id = new mongolian.ObjectId(object._id);
+ if (this['beforeRemove']) this.beforeRemove();
+ if (this['aroundRemove']) this.aroundRemove();
+ that = this;
+ return Client.collection(this.collection).remove({
+ _id: _id
+ }, function(err) {
+ if (that['aroundRemove']) that.aroundRemove();
+ if (that['afterRemove']) that.afterRemove();
+ return process.nextTick(function() {
+ if (callback) return callback(err);
+ });
+ });
+ };
+
+ return MongoritoModel;
+
+})();
+
+module.exports = {
+ connect: Mongorito.connect,
+ disconnect: Mongorito.disconnect,
+ bake: Mongorito.bake,
+ Model: MongoritoModel
+};
12 package.json
@@ -0,0 +1,12 @@
+{
+ "name": "mongorito",
+ "version": "0.1.0",
+ "description": "ODM for MongoDB.",
+ "keywords": ["mongo", "mongodb"],
+ "author": "Vadim Demedes <sbioko@gmail.com>",
+ "dependencies": {
+ "async": "*"
+ },
+ "main": "index",
+ "engines": { "node": ">= 0.4.x" }
+}
Please sign in to comment.
Something went wrong with that request. Please try again.