node.jsnode-orm2

Node-orm saving nested objects


My model is essentially

I have added 'Q' promises to many of the node-orm functions to program in that manner. So find is now qFind etc...

I am struggling to find the best way to persist this to the DB (MySql):

User.qGet(1004).then(function(user) {

    var newIdea = new Idea({
        'openedOn': new Date()
    })

    newIdea.setUser(user, console.log)

    Idea.qCreate(newIdea).then(function(idea)  {
        _.each(positions, function(position) {

            Security.qFind({ticker: position.ticker}).then(function(securities){
                var security = securities[0]

                Direction.qFind({direction: position.direction}).then(function(directions){
                    var direction = directions[0]
                    var newPosition = Position({
                        'weight': 1
                    })  

                    newPosition.setIdea(idea, console.log)
                    newPosition.setDirection(direction, console.log)
                    newPosition.setSecurity(security, console.log)

                    console.log(JSON.stringify(newPosition))

                })  // Direction.qFind              
            }) // Security.qFind
        }) // _.each

        console.log(JSON.stringify(idea))
        res.send(idea)
    }) // Idea.qCreate

}) // User.find

Here are my problems

  1. It is not working. When I set the idea, i get the error:

[Error: ER_BAD_NULL_ERROR: Column 'directionId' cannot be null]

The issue is I need to set three foreign keys in this object... 2. Is this the right approach to saving nested objects?


Solution

  • I have decided to embrace the use of promises, and the Q library

    Step 1 adding q nbind to interesting methods in my orm model. for instance:

    model = db.models.direction
    model['qFind'] = Q.nbind(model['find'], model);
    

    Step 2 was adding instance methods to my Models to:

    setDirectionByName: function(direction) {
    
        var _this = this;
        var internalSuccess = function(directions) {
            _this.direction = directions[0]
            _this.directionId = directions[0].id
            return directions
        }
    
        return {
            then: function(externalSuccess, externalFail) {
                var success = _.compose(externalSuccess, internalSuccess)
                Direction.qFind({direction: direction}).then(success, externalFail)
            }
        }
    }
    

    in this step i define an internal success method which stores the properties, and return a promise which utilizes composition to form an overall success function (the one from my model inside of the one passed to the 'then' invocation.

    Step 3: handling the request and saving the data

    User.qGet(1004).then(function(user) {
    
        var newIdea = new Idea({
            'openedOn': new Date()
        })
    
        newIdea.setUser(user, function(){})
    
        Idea.qCreate(newIdea).then(function(idea)  {
    
            var positionPromises = _.map(positions, function(position) {
    
                var newPosition = Position({
                    'weight': 1
                    ,'ideaId': idea.id
                })  
    

    Here I set the foreign keys, and wait for them to complete, before the Position.create is asynchronously kicked off, with a promise being returned.

                return Q.all([
                        newPosition.setDirectionByName(position.direction)
                        , newPosition.setSecurityByTicker(position.ticker) 
                    ]).then(function(noop) {
                        //newPosition.setIdea(idea)
                        return Position.qCreate(newPosition)
                    })
            }) // _.map
    

    SO then with an array of promises for Position objects. Here I am going to wait for them all to fill, prior to returning the results tot he client

            Q.all(positionPromises).then(function(positions){
                console.log('RESULTS of POSITION Promises')
                //console.log(JSON.stringify(positions))
    
                //This doesn't seem to work as expected
                //idea.setPositions(positions, function(e, o){ })
    
                // kludge it
                idea.positions = positions
    
    
    
                console.log(JSON.stringify(idea))
                console.log('/RESULTS of POSITION Promises')
                res.send(idea)
    
            })
    
            console.log('FALL THROUGH')
        }) // Idea.qCreate
    
    }) // User.find