ColdFusion – No Caching Pages

Have you ever wanted to prevent the user from clicking the browser’s “Back” button to go back to a previous page?

This usually happens after some processing has been like making a payment or logging out of the system.

For instance, if a user logs out of your system and they click on the browser’s back button, the previous page where they would need to be logged in would still load.

This is because the browser caches the page so even if all your session variables are destroyed the page still loads as if you were still logged in visually only.

Of course if you click on a link that directs you to another “must be logged in” page it’ll perform the usual “You must be logged in” logic.

The way to prevent this from happening is not to try and disable the browser’s back button (that’s a no-no), but instead we should prevent the browser from caching the page.

This can be done easily in Coldfusion by adding the following lines to your code:

<cfheader name=“cache-control” value=“no-cache, no-store, must-revalidate”>
<cfheader name=“pragma” value=“no-cache”>
<cfheader name=“expires” value=“#getHttpTimeString(now())#”>

Voila! Now when the user clicks back, since we told the browser not to cache the page, it will make the normal request to the server and the normal session verification occurs and the cached page will not display.

Datatables – Fixed Header

datatable

I’m sure most developers already know about data tables: http://datatables.net/

It’s a really awesome jQuery plugin that allows you to quickly sort/search your HTML table. It’s really easy to use and there are tons of examples in the site.

To use data tables simply create your HTML table with proper THEAD and TBODY tags then apply data tables to your table:

$(document).ready(function(){
    $('#myTable').dataTable();
});

There are also several plugins to make data tables even more functional and amazing!

One thing that constantly came up in my projects is that when users display a lot of records per page or if they have lower resolution screens then they have a problem remembering which columns contain what data when they scroll down the table since the header is off screen.

I searched for solutions and found several plugins that surround the data table in a DIV and make the DIV scrollable. It works but doesn’t look that nice visually.

 

One useful plugin I found is the Fixed Header  plugin. It’s easy to implement.:

$(document).ready( function () {
    var table = $('#myTable').dataTable();
    new $.fn.dataTable.FixedHeader( table );
} );

This plugin floats the table headers to the top of the window when scrolled so even when you scroll down the page the header is always visible.

Another great thing about this plugin is that it works without using data tables as well.

Go check it out!

CFScript – Converting an Excel Sheet to a Query

I just posted about an issue I had when importing an Excel file to the database here.

In that project I used a function written by Silverink Consulting. The article is called CFSpreadsheet in cfscript. The hard way and I recommend you check it out.

You just add the function, call it with:

resultQuery = ExcelToQuery(params.thefile);

and it just works!

Just wanted to document it here since I found it very useful.

CFWheels – Model Not Returning Correct Results in Loop

CFWheels

The other day I was working on a project for a client and they wanted an import functionality that would allow them to upload an  Excel file and have the system save the data in the database.  The Excel file  contained duplicates and of course I don’t want duplicate records so I would check whether it already exists in the database before I insert it.
Each time I cleared the data and imported the file it would ALWAYS add all data including duplicates. I would convert the file to a query using a function that I got from here by Silverink Consulting since CFScript didn’t have a way to use CFSpreadSheet. Then I would loop through the query and check whether or not the record exists before adding it.   All the logic makes sense and I couldn’t figure out what I did wrong.

Here’s a simplified version of the code:

// convert file data to query
data = ExcelToQuery(params.theFile);

// loop through each record
for(person in data){
// check if person exists
    person = model(“Person”).findOne(where=”name = ‘#trim(person.name)#'”);
if(NOT isObject(person){
// add person
person = model(“Person”).new();
person.name = trim(person.name);
person.save();
}
}

Turns out that CFWheels caches duplicate queries during a lifetime of the request. Since the query is in the loop and in the same request, it cached.

So if the name was “Bob” obviously it would return false initially since it doesn’t exist in the database.

When it encounters “Bob” again you would think it would find it but since the query is cached it still returns false, therefore, the duplicate record is inserted.

The way to get around this is to ensure the query is not cached. The way to do this is add reload=true in the .findOne()

  person = model(“Person”).findOne(where=”name = ‘#trim(person.name)#’, reload=true”);

Now if we import the file it correctly detects the duplicate and does not insert it. Problem SOLVED!