We've all built forms that use common reference data like country codes/names, states, etc. Historically I've always stored this type of information in a database that I would query as needed. However, some types of reference data may change once in awhile (e.g. zip/postal codes) and maintaining that data across apps can be a bit cumbersome. Now that I've started thinking about apps from a modular HMVC approach (Coldbox fanboy here), I played with the idea of moving reference data into an external module that could be more easily updated and shared, both between apps and with the CF community (e.g. Forgebox). To play around with this concept further, I created a generic module called "DataLib" that would store US States. The first thing I did was eliminate the database dependency, and instead, I stored all of the reference data as a .json file residing in the module. I then created a component that, when instantiated, would read the reference data and deserialize it for CFML use. Here's an example of my first experiment: Structure /modules_app/dataLib/ModuleConfig.cfc // Coldbox module file /modules_app/dataLib/models/UsStates.cfc // The CFC that is responsible for providing data /modules_app/dataLib/data/usStates.json // the raw JSON file containing the data The UsStates.cfc file might look something like this: component
hint="I am the the US State data library"
{
/**
* Constructor
*/
function init() {
// read the data file into the private scope
variables.states = deSerializeJson( fileRead( expandPath( "/dataLib/data/usstates.json" ) ) );
return this;
}
/**
* list
* Returns the data
*/
struct function list() {
return variables.states;
}
/**
* listAsArray
* returns the data as an array
* todo: force the array to be alphabetical.
*/
array function listAsArray() {
var stateArray = [];
variables.states.each( function( key, value ) {
stateArray.append( { "name": value, "initials": key } );
} );
return stateArray;
} I had a few thoughts about my approach: 1. I love the modularity and ability to store the actual data separately. When the US finally decides to conquer Canada, updating the json file would be extremely easy and it could be pushed to Github, Forgebox, or wherever. 2. I am concerned about the performance implications of using fileRead() to consume the JSON file during instantation. I could make the component a singleton, but for larger reference data (e.g. ZipCodes), I don't like the idea of all that data sitting in memory during the lifespan of the app. For smaller data sets like countries/states, keeping things in memory doesn't smell bad to me. Perhaps this method of storing reference data is ideal only for smaller data sets. Larger data sets like zip codes likely belong in the database, especially since you typically query a subset of data instead of the whole thing at once and databases are good at that type of thing. 3. I also like the idea of adding data manipulation methods onto the component. For example, requesting the data in array format, sorted, etc would be pretty easy to implement and provide useful utilities for consumption. What do you think? How do you handle storing commonly used reference data? Can you see any other flaws in modulizing small reference data sets like I've done in my example?
... View more