diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ce380c6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules/* +.DS_Store diff --git a/argon/model.js b/argon/model.js index 254abea..196a7cd 100644 --- a/argon/model.js +++ b/argon/model.js @@ -64,6 +64,33 @@ Module(Argon, 'Model').includes(CustomEventSupport, ValidationSupport)({ }); return this; }, + + /** + Fetches as many record matching a given query. Query lenguaje and structure + depends on the storage used for the model. + @method search + @argument query [Object] the query with the criteria to perform the lookup. + @argument callback [Function] method to handle data. + @return [Array]. + **/ + search : function search(query, callback) { + var Model; + + Model = this, + request = { + action : 'search', + model : Model, + query : query + }; + + this.storage.search(request, function searchCallback(data) { + if (callback) { + callback(data); + } + }); + + return this; + }, prototype : { diff --git a/argon/storage/json_rest.js b/argon/storage/json_rest.js index c64327c..396002a 100644 --- a/argon/storage/json_rest.js +++ b/argon/storage/json_rest.js @@ -376,6 +376,15 @@ Class(Argon.Storage, 'JsonRest')({ return this; }, + /** + Allias for find + @method search + **/ + search : function search(requestObj, callback) { + this.find(requestObj, callback); + return this; + }, + /** Updates from the resource @method put diff --git a/argon/storage/local.js b/argon/storage/local.js index 8a9b2f2..b4a4b50 100644 --- a/argon/storage/local.js +++ b/argon/storage/local.js @@ -224,6 +224,15 @@ Class(Argon.Storage, 'Local')({ return this; }, + /** + Allias for find + @method search + **/ + search : function search(requestObj, callback) { + this.find(requestObj, callback); + return this; + }, + /** Updates a set of data on the storage instance @method put diff --git a/argon/storage/mongodb.js b/argon/storage/mongodb.js new file mode 100644 index 0000000..f52638a --- /dev/null +++ b/argon/storage/mongodb.js @@ -0,0 +1,106 @@ +Class(Argon.Storage, 'MongoDB')({ + + prototype : { + + driver : null, + collectionName : null, + collection : null, + + preprocessors : [], + processors : [], + + init : function init(config) { + if(this.preprocessors instanceof Array === false){ + this.preprocessors = [].concat(this.constructor.preprocessors); + } + + if(this.preprocessors instanceof Array === false){ + this.preprocessors = [].concat(this.constructor.preprocessors); + } + + this.driver = config.driver; + this.collectionName = config.collectionName; + this.collection = config.driver.collection(this.collectionName); + + return this; + }, + + create : function create(requestObj, callback) { + var storage = this; + + for (var i = 0; i < this.preprocessors.length; i++) { + requestObj.data = this.preprocessors[i](requestObj.data, requestObj); + } + + this.collection.insert(requestObj.data, function handleInsert(error, data) { + if (error) { + return callback(error); + } + + data = data[0]; + + for (var i = 0; i < storage.processors.length; i++) { + data = storage.processors[i](data, requestObj); + } + + callback(data); + }); + + return this; + }, + + update : function update(requestObj, callback) { + for (i = 0; i < this.preprocessors.length; i++) { + requestObj.data = this.preprocessors[i](requestObj.data, requestObj); + } + + this.collection.update({_id : requestObj.data._id}, requestObj.data, function handleInsert(error, data) { + callback(error || data); + }); + + return this; + }, + + find : function find(requestObj, callback) { + this.collection.find().toArray(function findCallback(error, data) { + callback(error || data.map(function (item) { return new requestObj.model(item)})); + }); + + return this; + }, + + findOne : function findOne(requestObj, callback) { + this.collection.find({_id : requestObj.data._id}, function findCallback(error, data) { + callback(error || data.map(function (item) { return new requestObj.model(item)})[0]); + }); + + return this; + }, + + search : function search(requestObj, callback) { + this.collection.find(requestObj.query, function searchCallback(error, data) { + if (error) { + return callback(error); + } + + data.toArray(function arrayHandler(error, documents) { + callback(JSON.parse(JSON.stringify(documents)).map(function (doc) { + return new requestObj.model(doc) + })); + }); + }); + + return this; + }, + + remove : function remove(requestObj, callback) { + var id = requestObj.data._id; + + this.collection.remove({_id : id}, function removeCallback(error, data) { + callback(error || data); + }); + + return this; + } + } +}); \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..62e6e11 --- /dev/null +++ b/package.json @@ -0,0 +1,22 @@ +{ + "name": "argon", + "description": "Javascript active record implementation.", + "version": "0.0.1", + "repository": { + "type": "git", + "url": "https://github.com/azendal/argon.git" + }, + "main": "argon.js", + "directories": { + "argon": "./argon" + }, + "keywords": [], + "dependencies": { + "mongodb": "^1.4.28", + "neon": "^2.0.0", + "tellurium": "^2.0.0" + }, + "engines": { + "node": "*" + } +} diff --git a/spec/spec/argon/storage/mongodb.js b/spec/spec/argon/storage/mongodb.js new file mode 100644 index 0000000..cdc77f0 --- /dev/null +++ b/spec/spec/argon/storage/mongodb.js @@ -0,0 +1,105 @@ +var client = require('mongodb').MongoClient, + setupSuite; + +require('neon'); +require('neon/stdlib'); +require('../../../../argon'); +require('../../../../vendor/validation_support'); +require('../../../../argon/model'); +require('../../../../argon/association'); +require('../../../../argon/storage'); +require('../../../../argon/storage/mongodb'); +require('tellurium'); + +var TestModel = function TestModel(config) { + return config; +}; + +setupSuite = function setupSuite(db) { + Tellurium.suite('MongoDB Storage')(function(){ + var storage = new Argon.Storage.MongoDB({ + driver : db, + collectionName : 'test' + }); + + this.describe('create records')(function () { + + this.specify('should create a valid record')(function () { + var spec = this; + storage.create({data : {a : 'a'}}, function (data) { + spec.assert(data.a).toBe('a'); + spec.completed(); + }); + }); + + this.specify('should apply preprocessors')(function () { + var spec = this; + storage.preprocessors.push(function (data) { + data.preprocessor = true; + return data; + }); + + storage.create({data : {a : 'a'}}, function (data) { + spec.assert(data.preprocessor).toBe(true); + spec.completed(); + }); + }); + + this.specify('should apply processors')(function () { + var spec = this; + + storage.processors.push(function (data) { + data.processor = true; + return data; + }); + + storage.create({data : {a : 'a'}}, function (data) { + spec.assert(data.processor).toBe(true); + spec.completed(); + }); + }); + + }); + + this.describe('Search records')(function () { + this.specify('should search and return matching records')(function () { + var spec = this, + gusData = {name : 'Gus', surname : 'Ortiz', age : 30}, + ferData = {name : 'Azendal', surname : 'Transvina', age : 5000}, + jonData = {name : 'Jon', surname : 'Snow', age : 18}; + + storage.create({model : TestModel, data : gusData}, function (gus) { + storage.create({model : TestModel, data : ferData}, function (fer) { + storage.create({model : TestModel, data : jonData}, function (jon) { + storage.search({model : TestModel, query : {age : {$lt : 40}}}, function (dudes) { + spec.assert(dudes.length).toBe(2); + spec.assert(dudes.map(function (dude) { + return dude.name; + }).sort().join(',')).toBe('Gus,Jon'); + + spec.completed(); + }) + }); + }); + }); + }) + }); + + }); +}; + +client.connect("mongodb://localhost:27017/argon_test", function handleConnection(error, db) { + + if (error) { + console.log("Could not conenct to mongo"); + return; + }; + + var collection = db.collection('test'); + + collection.remove({}, function (error, data) { + setupSuite(db); + Tellurium.run(); + }); + +});