2

I am looking for opinions and alternate ideas, as what I am doing is working, but wanted to ask if it was optimal

I have a site that when the index handler is called, it populates the request collection with specific queries from database tables so that I can build drop downs for the user to select.

i am querying two models and putting their results in their respective variables, then loop thru them in the view to create the drop down

index Handler

function index(event, rc, prc){
    event.paramValue("debug",0);
    rc.stages  = getmodel("tms_proposal_stage").select();
    rc.plannedGiftTypes  = getmodel("tms_funding_type").select();
    event.setLayout('layout.bootstrap');
}

index view

  <div class="form-group">
    <label for="proposal_stage" class="control-label">Proposal Stage Code</label>
    <select id="proposal_stage" name="proposal_stage" class="form-control">
    <cfloop query="rc.stages">
        <option value="#stage_code#">#short_desc#</option>
    </cfloop>

    </select>
  </div>

I understand that two queries isnt that costly, but if I needed to run 100 of these that would have scalability issues. These query result sets do not change much, so I was thinking, shouldnt these be cached or stored and accessed a different way?

I thought about html5 local storage, which I have used but not in this regard. I also considered making a new handler function that makes all of these database calls and is cached, then referenced by other functions

anyways, all thoughts are appreciated

Jay Rizzi
  • 4,196
  • 5
  • 42
  • 71
  • A separate function for the database calls makes sense. Caching does not. A query result that doesn't change much still changes and caching prevents those changes from being available. – Dan Bracuk Apr 10 '15 at 16:32

1 Answers1

3

You have several options available to you. Since you're using ColdBox, you have CacheBox readily available to you. https://github.com/ColdBox/cbox-refcards/raw/master/CacheBox/CacheBox-Refcard.pdf

A very simple way to do inline caching of the data would be to inject a CacheBox provider at the top of your component:

component {
  property name="cache" inject="cachebox:default";
}

Then use the cache API in your event to store and retrieve data. My favorite method is getOrSet() because it wraps it up in a single call.

rc.stages = cache.getOrSet(
  objectKey="stages",
  produce=function(){ 
    return getmodel("tms_proposal_stage").select();
  }
);

The closure is only executed if the key is not already in the cache. http://wiki.coldbox.org/wiki/WhatsNew:CacheBox-1.6.cfm#Get_Or_Set_Baby

Another approach is to cache the full HTML. To do this, create a viewlet that only outputs the HTML for your form control. Create an event that returns the output of just that view like so:

function stagesFormInput(event, rc, prc) cache=true {
  var stagesData = getmodel("tms_proposal_stage").select();
  return renderView(view="viewlets/stages", args={ stagesData : stagesData } );
}

Note, I'm passing stageData directly into the view so it doesn't pollute the rc or prc. This data will be available in your viewlet as "args.stagesData".

Also note the "cache=true" in the method declaration. That's the magic that will tell ColdBox to cache this event (inside CacheBox's "template" provider"). You can specify a timeout, but this will use the default. Now, enabled eventCaching in your /config/ColdBox.cfc file.

coldbox={
    eventCaching = true
}

http://wiki.coldbox.org/wiki/ConfigurationCFC.cfm#Application_Aspects

And finally, in your main view or layout, just run your new viewlet everywhere you want the cached HTML to be output.

#runEvent("viewlets.stagesFormInput")#

This is a little bit more setup, but is more powerful since it caches the full HTML snippet which is really ideal. I also have an entire sample app that demos this inside a working app. You can check it out here: https://github.com/bdw429s/ColdBox-Viewlet-Sample

Brad Wood
  • 3,863
  • 16
  • 23