Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I have a situation where I have multiple objects that each needs to connect to a different mongodb uri.

I am currently testing this using mongolia but the concept should be the same if I were to use the collection() method of Mongodb's native driver.

Mongolia requires a db object when creating a new model and since I do not have this object from start I thought it would be better to callback the hell out of it.

I do not wish to force all objects to connect to their databases from the start so it seems that nesting the callbacks are the way to go.

MongoClient = (require 'mongodb').MongoClient
mongolia = require 'mongolia'

modelFactory = (db, modelName, cb) ->
  model = mongolia.model db, modelName
  cb undefined, model

class SomethingWithDb
  tag: undefined
  databaseUri: undefined
  databaseInstance: undefined
  models: {}
  collections: {}

  log: (text) =>
    console.log "[#{@tag}] #{text}"

  database: (cb) =>
    if not @databaseInstance?
      @log 'database() > Creating new database instance.'
      MongoClient.connect @databaseUri, {}, (err, db) =>
        return cb err if err
        @log 'database() > Database instance ready, returning.'
        @databaseInstance = db
        cb undefined, @databaseInstance
    else
      @log 'database() > Database instance existed, returning.'
      cb undefined, @databaseInstance

  model: (modelName, cb) =>
    if modelName not of @models
      @log "model(#{modelName}) > Creating new model."
      @database (errDb, db) =>
        return cb errDb if errDb
        modelFactory db, modelName, (errFactory, model) =>
          @log "model(#{modelName}) > Model created, returning."
          return cb errFactory if errFactory
          @models[modelName] = model
          cb undefined, model
    else
      @log "model(#{modelName}) > Model existed, returning."
      cb undefined, @models[modelName]

  collection: (collectionName, cb) =>
    if collectionName not of @collections
      @log "collection(#{collectionName}) > Creating new collection."
      if not @databaseInstance?
        @database (errDb, db) =>
          return cb errDb if errDb
          @log "collection(#{collectionName}) > Collection created (new db), returning."
          @collections[collectionName] = db.collection collectionName
          cb undefined, @collections[collectionName]
      else
        @log "collection(#{collectionName}) > Collection created (existing db), returning."
        cb undefined, @databaseInstance.collection collectionName
    else
      @log "collection(#{collectionName}) > Collection existed, returning."
      cb undefined, @collections[collectionName]

  constructor: (@tag, @databaseUri, @databaseOptions) ->

one = new SomethingWithDb "mongodb://localhost/test-one"
two = new SomethingWithDb "mongodb://localhost/test-two"

one.model 'user', (errModel, user) ->
  user.insert name: 'test', (errInsert, respInsert) ->

    one.model 'user', (_errModel, _user) ->
      _user.findOne name: 'test', (_errFind, _result) ->
        console.info _result

two.model 'user', (errModel, user) ->
  user.insert name: 'test-two', (errInsert, respInsert) ->
    user.findOne name: 'test-two', (errFind, result) ->
      console.info result

The output is something like this.

# [one] model(user) > Creating new model.
# [one] database() > Creating new database instance.
# [two] model(user) > Creating new model.
# [two] database() > Creating new database instance.
# [two] database() > Database instance ready, returning.
# [two] model(user) > Model created, returning.
# [one] database() > Database instance ready, returning.
# [one] model(user) > Model created, returning.
# [one] model(user) > Model existed, returning.

Is the logic behind this correct or is there some better way to do this that I am not aware of?

I'd be also very interested in any possible code or flow optimizations that might make this saner or more solid.

Thank you in advance.

ps. I have included a @collection() method that is not tested but should provide a hint to other uses.

share|improve this question
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.