Wednesday, December 16, 2015

DynamoDB to javascript classes entity framework style with contracts

I am excited to show code from my previous post! Please read previous post if you haven't yet.

PortfolioBalance.db serves as a contract/template before it is filled with the object. The most important part about this is that it defines the object. I can't tell you how many times I end up trying to tab between the database webpage and trying to discern the right cell to figure out what it contains. Now it is very explicit and enforceable and can be done in levels! In the code below I do a trace if it doesn't find a variable, you could add more to enforce everything is there. If you look at PortfolioBalance.db.StocksPercent it is an array of 1 element. This single element is a template for objects in the array which I think is pretty cool. If you follow this pattern you will end up with beautifully formed data in your class. You won't ever need to tediously do constructor initialization or have to be cross referencing the database to find out what your class should contain! It is in one place!

Database.js

var createObjectFromTemplate = function( template, dataItem ) {
    var itemsToFill = Object.keys(template);
   
    var object = {};
   
    for ( var index = 0; index < itemsToFill.length; index++ ) {
        var keyName = itemsToFill[index];
        var isObject = typeof template[keyName] === "object";
       
        if ( template[keyName].constructor === Array ) {
            var array = [];
       
            for ( var item = 0; item < dataItem[keyName].L.length; item++ ) {
                array.push( createObjectFromTemplate( template[keyName][0], dataItem[keyName].L[item].M ) );
            }
            object[keyName] = array;
        }
        else if ( isObject ) {
            object[keyName] = createObjectFromTemplate( template[keyName], dataItem[keyName].M );
        } else if ( !dataItem[keyName] ) {
            //skip trying to set the item because it wasn't found in the data!
            console.log('!!!class is asking for member but not found in database ' + keyName );
        }
        else if ( dataItem[keyName].N ) {
            object[keyName] = Number(dataItem[keyName].N);   
        }
        else if ( dataItem[keyName].S ) {
            object[keyName] = dataItem[keyName].S;   
        }
        else if ( dataItem[keyName].L ) {
            object[keyName] = dataItem[keyName].L;
        }
        else {
            object[keyName] = dataItem[keyName];   
        }
    }    
   
    return object;
};

var convertToObjects = function( err, data, creationFunction ) {
    if ( err ) {
        return null;
    }   
   
    console.log( data.Items );
   
    var objects = [];
   
    for ( var index = 0; index < data.Items.length; index++ ) {
        var portfolioBalance = creationFunction();                                  //create a new class object
        portfolioBalance.db = createObjectFromTemplate( portfolioBalance.db, data.Items[index] );     //initialize the class object based on the db member, and row from database
        objects.push( portfolioBalance );
    }
   
    return objects;
};


PortfolioBalanceRepository.js

var getPortfolioBalanceForUserOnDate = function ( loginName, callback ) {
    var search = {
        TableName: exports.table.Name,
        KeyConditions: {
            "LoginName": {
                "AttributeValueList": [{
                    "S": loginName
                }],
                "ComparisonOperator": "EQ"
            },
        },
        ScanIndexForward: false,
        Limit: 1,
        ProjectionExpression: "#a,#b,#c,#d",
        ExpressionAttributeNames: { "#a": "StocksPercent",
                                    "#b": "CashPortfolioPercent",
                                    "#c" : "Date",
                                    "#d" : "PreviousCashPortfolioPercent"}

    };
   
    databaseLib.query( search, function( err, data ) {
        var objects = databaseLib.convertToObjects( err, data, function() { return new PortfolioBalance.PortfolioBalance(); } );
        callback( err, objects ) ;
    });
};



Portfolio.js:
function PortfolioBalance( ) {
    this.db = {
        LoginName: "",
        Date: "",
        CashBalance: 0,
        CashPortfolioPercent: 0,
        PreviousCashPortfolioPercent: 0,
        ReturnRate: 0.0,
        StocksPercent: [ { "StockId": 0,
                           "Percentage": { "Overall": 0, "Previous": 0, "Short": 0, "Buy": 0 },
                           "CompanyName": "",
                           "CurrentPrice": 0,
                           "Stock": "PM" }],
        StocksQuantity: "",
        TotalPortfolioValue: "",
        TradesForDay: ""
    };
   
    var parent = this;
}

exports.PortfolioBalance = PortfolioBalance;


No comments:

Post a Comment