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

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.