Thursday, December 30, 2010

DSL's or Domain Specific Languages

I saw this at Adobe MAX last year and I finally got a chance to try it out. DSL or Domain Specifically Languages are languages that only reside in a domain, in our case the web app we are developing. A good example of where DSLs are used is in gMail in the search box. If you haven't noticed it yet they are really handy, but they only work in gMail. Another good one is MS Outlook, they support crazy operators. Here is what one would look like:

dsl

I grabbed this one from gMail. The convention seems to use a keyword followed by a ":". In the case above it's "from:". I have only found DSLs helpfully for search boxes. If you are going to use DSLs you need to have legend so your users know what keys are available. You need to support it everywhere or tell the user where it is supported. If you are going to use them you should do whatever it takes in the keys and language to make it easier for the user. DSLs should be quick to use. Some advanced DSLs might look like this "from:(name:*joe)" or something like that or if operators are involved.

Once the user enters the DSLs you need to parse the string and do something with it. I create a query criteria snippet for sql or orm queries to allow the user to search across other things in the search box.

DSLs aren't really user friendly that's why I would recommend "search areas". Search areas are much easier to read, but less flexible. I posted on it early tonight here.

Getting all the URL params in Javascript

I've been updating a lot of href's lately and found these functions to be very handy. They basically take all the pars in a string and put them in a JS object. There is other functions out there that get you 1 url param, but I wanted them all. Reason being, is I need to see if that param exists and do some more checks on it for business logic, then take all the pars and turn then into a querystring and add them back to href again.


getURLParameters = function(url){

var results = {};

if(url == ""){
var url = window.document.URL.toString();
}
if (url.indexOf("?") > 0){
var splitURL = url.split("?");
params = splitURL[1].split("&");

for (var i=0;i var param = params[i].split("=");
if (param[1] != "")
results[param[0]] = unescape(param[1]);
else
results[param[0]] = "";
}

}

return results;
};
getURL = function(url){

if(url == ""){
var url = window.document.URL.toString();
}

if(url.indexOf("?") > 0){
var splitURL = url.split("?");
url = splitURL[0];
}

return url;
};


getURL() actually serves two purposes. If a url isn't passed in get the current url. And it also cleans off all of params so all you get the base url.

Search Areas

Had a task where a user didn't want to use the primary "search by" of searching in a list which is usually to search by "name" or "number". I did some research and found a way to keep the majority users satisfied, yet still giving the ability to the advanced user. Check it out...

Regular search box:
plain

Search box with search areas:
search_areas

It's actually not to tricky to do. It's just a table with two cells. The left cell is the input box with a style of no boarders and right cell is a div with a pic in it. When you click the div with the pic in it another div below is shown with absolute positioning. I will let you figure out the javascript and css. It's not too hard.

iStockPhotography currently has something similar.

MS SQL GUID lengths

Working with MS SQL and found out that errors with GUIDs are only thrown if the length of the GUID isn't met. The length of the GUID can be over the length of a regular GUID. This is kinda wierd because one would think this would error, but in fact MS SQL actually only will store the length of the GUID String up to the length of a normal GUID. Check out the examples below...


create table Snowboarder(
id uniqueidentifier not null,
name varchar(200) not null,
primary key (id)
)

/*--will throw an error---*/
insert into Snowboarder(
id,
name
)values(
'',
'Blank GUID'
)

/*--will work---*/
insert into Snowboarder(
id,
name
)values(
'D832DE4B-8453-4831-9505-6CA8CB4A4033',
'Regular GUID'
)

/*--will work, but it will only store the first guid---*/
insert into Snowboarder(
id,
name
)values(
'FE7A6068-080B-43B3-B392-3ABCE2E5FADF13725D91-B434-41B4-97A8-5607BF864EF5',
'Two GUIDS together'
)

/*--will throw an error because the first part is already in the db--*/
insert into Snowboarder(
id,
name
)values(
'D832DE4B-8453-4831-9505-6CA8CB4A40336448153D-A72F-42A8-BB35-17EE076D393C',
'Two GUIDS together with the first part already in the db'
)

ColdMVC: AJAX call

Trying to make ajax calls with ColdMVC was a little difficult for me because I struggle with routes, but I found a way. Here is what I did to make an AJAX call with ColdMVC.

First I created a function on a Controller so I can return "hi" back from the AJAX call. Notice I have @view json.cfm above the function. Since ColdMVC uses routes I need to send the data to a view and cfoutput it on the page.

TestController

/**
* @accessors true
* @extends coldmvc.controller
*/
component {

/**
@view json.cfm
*/
function testMethod(){
params.json = "hi";
}

}


Here is json.cfm. All that I do with it is output the variable "json".

json.cfm

<cfoutput>#params.json#</cfoutput>


And lastly I preform my AJAX call using jQuery. In the url setting of jQuery.ajax() I just link to the controller. In my case, my controller's name is TestController, so my route with just be "test" and then I can change out the method. In my case I am calling the "testMethod" on the controller.

ajaxCall = function(){

jQuery.ajax({
url:"#coldmvc.link.to('/test')#/test?returnformat=json",
type:"GET",
success:function(data){
jQuery("body").html(data);
}
});
};


If you want to return json back just go to json.cfm and wrap params.json in SerializeJSON(). Then in your ajax call, do jQuery.parseJSON(). This is the only way I can think of right now to make an ajax call with ColdMVC, if there are any other techniques I would be more then happy to listen.

Tuesday, October 19, 2010

CF9 hibernate file includes.

This was so cool I had to repost it. After you've defined a few hibernate.hbmxml files it gets annoying to have type the same properties on every class. My fingers were getting sore to complain a little. After a reference shown to me by Tony Nelson, Mark Mandal had a great post on "includes in the hibernate file". Check it out.

If you notice in the hibernate.hbmxml below there is a line that says "&common;".

hibernate.hbmxml

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
[ <!ENTITY common SYSTEM "common.hbm.xml"> ]
>
<hibernate-mapping>

<class entity-name="User" lazy="true" name="cfc:beforeandafter.app.model.User" table="`User`">
&common;
<property name="firstName" type="string">
<column name="First_Name" length="200" />
</property>
<property name="lastName" type="string">
<column name="Last_Name" length="200" />
</property>
<property name="emailAddress" type="string">
<column name="Email_Address" length="200" />
</property>
<property name="password" type="string">
<column name="Password" length="200" />
</property>
<bag name="projects">
<key column="User_ID" />
<one-to-many class="cfc:beforeandafter.app.model.Project" />
</bag>
<bag name="projectRatings">
<key column="User_ID" />
<one-to-many class="cfc:beforeandafter.app.model.ProjectRating" />
</bag>
</class>
</hibernate-mapping>


&common; points to file called common.hbm.xml. Within common.hbm.xml file I defined all my similiar properties and just include it on all my classes.

common.hbm.xml

<id name="id" type="int">
<column length="10" name="ID" />
<generator class="identity" />
</id>
<property name="isDeleted" type="boolean">
<column name="isDeleted" />
</property>
<property name="createdBy" type="int">
<column length="10" name="Created_By" />
</property>
<property name="createdOn" type="timestamp">
<column name="Created_On" />
</property>
<property name="updatedBy" type="int">
<column length="10" name="Modified_By" />
</property>
<property name="updatedOn" type="timestamp">
<column name="Modified_On" />
</property>

Make sure your include file ends in .xml and not .hbmxml otherwise it won't work. Made my life a ton a easier. Thanks Mark and Tony for sharing this.

Tuesday, August 10, 2010

ColdMVC: Plugging in fckeditor

I am working on a CMS app and I wanted the fckeditor in my app, while using ColdMVC. Here's what I did to get it in my app.

I downloaded the fckeditor and put it in the public folder, like below...

app
>public
>>plugins
>>>fckeditor

Next, on a custom helper called "util.cfc", I added a function called editor().
1. Create a fckeditor bean.
2. Set the properties of the fckeditor. Specifically the basepath is really important. I used $.config.get('assetPath') to get to the directory where the fckeditor is located.
3. Lastly, I wrap the fckeditor in ColdMVC's field() so it looks like the other fields.

<cffunction name="editor" access="public" output="false" returntype="string">
<cfargument name="name" required="true"/>
<cfargument name="value" required="false" default=""/>
<cfargument name="width" required="false" default="100%"/>
<cfargument name="height" required="false" default="300px"/>

<cfset local.bean = application.coldmvc.beanFactory.getBean("fckeditor")/>

<cfset local.bean.basePath = "#$.config.get('assetPath')#plugins/fckeditor/"/>
<cfset local.bean.instanceName = arguments.name/>
<cfset local.bean.value = arguments.value/>
<cfset local.bean.width = arguments.width/>
<cfset local.bean.height = arguments.height/>

<cfif not StructKeyExists(arguments,"label")>
<cfset arguments.label = $.string.humanize(arguments.name)/>
</cfif>

<cfoutput>
<cfsavecontent variable="local.field">
#local.bean.create()#
</cfsavecontent>
</cfoutput>

<cfreturn $.form.field(label=arguments.label,field=trim(local.field))/>

</cffunction>


Finally on my view, I call the helper function editor() and pass in my value. The use case below is for the editing a layout record for a cms app.

<cfoutput>
<c:form action="save" bind="layout">
<c:hidden name="id" value="#layout.id()#" />
<c:input name="name" value="#layout.name()#" />

#$.util.editor(label="Layout",name="layout.layout",value=layout.layout())#

<c:submit name="save" />
</c:form>
</cfoutput>


One thing to note is that if you want to bind the fckeditor textarea to an object, so it can be used in ColdMVC's populate() for a save, you will need to prefix your instanceName in the fckeditor. I do this by wrapping the fckeditor in a helper function and use the "name" argument like this...


<--- on my view I put in "layout.layout" as the name--->
#$.util.editor(label="Layout",name="layout.layout",value=layout.layout())#

<--- inside the editor()--->
<cfset local.bean.instanceName = arguments.name/>

Thursday, August 5, 2010

ColdMVC: Deploying my first app.

I just wanted to share some things I struggled with when deploying my first ColdMVC app.

1. Deploying the code to the server.
My web root on the hosted server looks like this:

->myApp
->coldMVC
->hyrule

2. Make sure the config.ini is setup correctly.
config.ini file
[default]
controller=route
action=render

[development]
development=true

[production]
datasource=myDataSourceName
development=false
sesURLs=true
urlPath=
assetPath=http://www.myDomain.com/myApp/public/
tagPrefix=c

In the block [production] you will see that sesURLs=true. This will get rid of /index.cfm on the tail of url. Example www.myDomain.com/public/

Next, I changed my urlPath to nothing because I want urls to not have the public in front of them. Example www.myDomain.com/

Finally, Since my urlPath doesn't point to the public folder any more all my assets ( css, js..etc) will be broken. So I point my assets back to the public folder. Examples http://www.myDomain.com/myApp/public/

Note: If you haven't already, make sure you create a default controller and action to hit. This will be excuted if somebody hits your base url. Example www.myDomain.com

3. Use apache or isapi rewrite rules to make the url prettier.
With out the /public/index.cfm at the end of url the app can't do routes. In order to solve this I had to make isapi rewrite rules to point anything after www.myDomain.com to the http://www.myDomain.com/myApp/public/index.cfm files so routes would work again.
.htaccess file
RewriteEngine on

#---redirect actions for www.myDomain.com
RewriteCond %{HTTP_HOST} ^www.myDomain.com [QSA]
RewriteCond %{SCRIPT_NAME} ^/index.cfm$
RewriteRule ^(.*)$ http://www.myDomain.com/myApp/public/index.cfm/%{REQUEST_URI} [QSA]

#---redirect assets for www.myDomain.com
RewriteCond %{HTTP_HOST} ^www.myDomain.com [QSA]
RewriteCond %{SCRIPT_NAME} !^/index.cfm$
RewriteCond %{SCRIPT_NAME} !(css|js|images)
RewriteCond %{SCRIPT_NAME} !-f
RewriteCond %{SCRIPT_NAME} !-d
RewriteRule ^(.*)$ http://www.myDomain.com/myApp/public/index.cfm/%{REQUEST_URI} [QSA,L]

4. Make sure the production environment.txt has the production text in it.
Since my app's config.ini file has block called [production] in it the environment.txt on the hosted server needs to have the text "production" in it.

5. Remember to create a datasource.
If the datasource name is not the same as your app folder name you need to add the datasource name in config.ini
[production]
datasource=myDataSourceName

Other than the isapi rewrite rules, it was my first time writing them, deploying my first ColdMVC app went well.

Wednesday, August 4, 2010

Select Top N Rows Per Group

I had an interesting sql task today. Someone asked me to get a max of three time-sheet entries per project. When an employee fills out a time-sheet they select a project for which the time is applied to. I was asked to grab a max of three of these entries and dump them in a csv for the accountant to audit. I was troubled on where to start this task. I am not an sql guy, so this was a challenge for me. I talked to the sql guys, but they were pretty busy today. One helped me but are minds together struggled to find the answer. After the googling, I tried a search result called "Cosmo Central" and found the anwser. Below is the piece that helped me so much...


with data as(
select row_number() over(partition by projects.name order by timesheet.id) as 'RowNumber’,
timesheet.id, projects.name
from timesheet
inner join projects on projects.id = timesheet.project_id
)

select id, name
from data
where RowNumber <= 3


Resource Used:
http://www.cosmocentral.com/2010/04/select-top-n-rows-per-group-ms-sql/

Yes. It looks like I copied the post and re-posted, but I am more so happy that I found the answer that I wanted to share the solution again. The credit still goes to Cosmo Central. Thanks a bundle.

ColdMVC: Basic CMS app request handling

I wanted to try make a cms app with ColdMVC so I took a stab at it. This is my first draft at a cms app. Below is a light weight request handler for cms views. We will break it down in a sec.


/**
* @accessors true
* @extends coldmvc.Controller
* @controller cmsview
* @layout cms_public
*/
component {

property _CMSPage;

/**
* @events requestStart
*/
function requestStart(){

var page = _CMSPage.findByAddress(getPath());

/*---check if the path is a cms page---*/
if(len(page.id()) gt 0){
$.event.action("render");
$.event.controller("cmsView");
$.event.view("cms/view/index.cfm");
}

}

function render(){

var path = getPath();
var actual_path = expandPath("/app/views/#path#");

/*---handles pages that end in a slash. Ex: www.mydomain.com/public/index.cfm/products/---*/
if(right(path,1) eq "/"){
actual_path = actual_path & "index.cfm";
path = path & "index.cfm";
}

/*---if the file exists render it, else run the page's html through the cms_public layout.---*/
if(fileExists(actual_path)){

$.event.view(path);

}else{

params.page = _CMSPage.findByAddress(getPath());

if(len(params.page.id()) eq 0){

render404();

}

}

}

/**
* @events invalidController, invalidAction
*/
function render404(){

params.page = _CMSPage.findByAddress("404");

if(len(params.page.id()) eq 0){
params.page._set("html","Sorry. We couldn't find the page you were looking for.");
}

$.event.controller("cmsView");
$.event.action("render404");
$.event.view("cms/view/index.cfm");

}

function getPath(){

var path = $.event.path();

if(left(path,1) eq "/"){
path = replace(path,"/","");
}

return path;

}

}


When a request begins I use the event "requestStart" to check if it's a cms page. This happens here...


/**
* @events requestStart
*/
function requestStart(){

var page = _CMSPage.findByAddress(getPath());

/*---check if the path is a cms page---*/
if(len(page.id()) gt 0){
$.event.action("render");
$.event.controller("cmsView");
$.event.view("cms/view/index.cfm");
}

}


As you can see above we are checking if getPath() is a cms page. getPath() gets the tail end of the url. Example: If the url read "www.mydomain.com/public/index.cfm/contact_us/", getPath() would return "contact_us/". This happens here...

function getPath(){

var path = $.event.path();

if(left(path,1) eq "/"){
path = replace(path,"/","");
}

return path;

}


If a cms page isn't found the request will run as usual. If a cms page is found it will go to render(). render() does a lot of checks.

First, we check if there is no file extension, example ".cfm", on path. If there is none I put in an "index.cfm" at the end. I do this for the next check which checks to see if the file exists.

Second, next we check if the file path actually exists in the app/views/ directory. If it does I render it. I do this because some pages might need to be coded where as other pages will be setup with a "web page generater" tool.

Third, if the file doesn't exists I can assume it's a page that was created by web page generator tool.

Lastly, I check if the page doesn't exists. I do this because my config.ini uses render() as defaults.
[default]
controller=cmsView
action=render

If someone requests "www.mydomain.com/public/index.cfm" the path won't exist. Therefore we excute the 404 handler, which is called render404().

This happens here...

function render(){

var path = getPath();
var actual_path = expandPath("/app/views/#path#");

/*---handles pages that end in a slash. Ex: www.mydomain.com/public/index.cfm/products/---*/
if(right(path,1) eq "/"){
actual_path = actual_path & "index.cfm";
path = path & "index.cfm";
}

/*---if the file exists render it, else run the page's html through the cms_public layout.---*/
if(fileExists(actual_path)){

$.event.view(path);

}else{

params.page = _CMSPage.findByAddress(getPath());

if(len(params.page.id()) eq 0){

render404();

}

}

}

If a page doesn't exists in the cms pages, an invalid controller or action is found I render404() is executed. I first check to see if a 404 page was created in the cms pages else I render my own html message.

This happens here...


/**
* @events invalidController, invalidAction
*/
function render404(){

params.page = _CMSPage.findByAddress("404");

if(len(params.page.id()) eq 0){
params.page._set("html","Sorry. We couldn't find the page you were looking for.");
}

$.event.controller("cmsView");
$.event.action("render404");
$.event.view("cms/view/index.cfm");

}


As I have been going through these functions I didn't explain where the pages are getting renderer. If you noticed at the top of first block of code there was an annotation @layout cms_public. All cms pages, whether they are coded up or database driven, run through the layout cms_public.cfm. Here's what it looks like...

<cfoutput>
< !DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en-us" xmlns="http://www.w3.org/1999/xhtml">

<cfif structKeyExists(params,"page")>
#page.html()#
<cfelse>
#render()#
</cfif>

</html>
</cfoutput>


All database driven pages run through a view in "views/cms/view/index.cfm" which looks like this...

<cfoutput>#page.html()#</cfoutput>


Thoughts on what I have so far?

Sunday, July 25, 2010

Declaring a variable with same name as a column in cfloop

I have a query with a column name json in it, which may or maynot contain a json string. If it does contain json I want to deserialize it, put it into an array loop, and output the results. I want to use the same in a variable as the column coming from the query because it reads good. When I did this I noticed that you can't declare a variable with the same name...even if you prefix the query column.

Here's is my test case. We will break it down in a sec.

<cfset query = queryNew("id,json")/>

<cfset queryAddRow(query)/>
<cfset querySetCell(query,"id","1")/>
<cfset querySetCell(query,"json","")/>

<cfset array = [{id=1,name="Joe"},{id=2,name="Tony"},{id=3,name="Ryan"}]/>

<cfset queryAddRow(query)/>
<cfset querySetCell(query,"id","2")/>
<cfset querySetCell(query,"json",serializeJSON(array))/>

<cfloop query="query">

<cfset json = []/>

<cfif len(query.json) gt 0>
<cfset json = deserializeJSON(query.json)/>
</cfif>

<cfloop from="1" to="#arrayLen(json)#" index="i">
#i.name#
</cfloop>

</cfloop>


The above test case will error out. Because you can't loop the following because ColdFusion thinks that variable "json" is a string, even though I declared it as an array.

<cfloop from="1" to="#arrayLen(json)#" index="i">


First we make a query with a json string in it

<cfset query = queryNew("id,json")/>

<cfset queryAddRow(query)/>
<cfset querySetCell(query,"id","1")/>
<cfset querySetCell(query,"json","")/>

<cfset array = [{id=1,name="Joe"},{id=2,name="Tony"},{id=3,name="Ryan"}]/>

<cfset queryAddRow(query)/>
<cfset querySetCell(query,"id","2")/>
<cfset querySetCell(query,"json",serializeJSON(array))/>


Next we loop the query and check if there is a json string in the query column "JSON". I started an array with the same name as query column json. I did this so if there isn't any json after we deserialize the json it won't error when we try to loop the array.

<cfset json = []/>

<cfif len(json) gt 0>
<cfset json = deserializeJSON(query.json)/>
</cfif>


Lastly I try to loop the array "json" and output the data, but it errors out because it still is looking at the loop variable "json" not the variable I declared "json". Yes, I can solve this problem easily but changing my declared variable from "json" to "array" or something like that, but I wanted to be clear what I was loop...and I just wanted to use the variable name "json".

Saturday, July 24, 2010

ColdMVC: Flatten an array of objects with children.

In record based systems "non object based" if you wanted to store a parent/child relationship you usually stored a parent_id on the same table.

Example:

CMS example showing a page table where a page can have many pages underneath it.

Page table.
ID,Name,Address,Parent_ID
1,Products,products/,null
2,Tiles,products/tiles/,1

Then in order to simulate an object based system, you usually loop the query and put the records in structs of structs.

Example.

result = {
id="1",
name="Products",
address="products/",
children=[
{
id="1",
name="Products",
address="products/",
children=[]
}
]
}

Notice there is children an array.

Using ColdMVC we actually start with "struct of structs" or object based, instead of starting with a query. So we need to take the objects array, we are using array of objects because that is what is return from an hql query, and pull out the children and put them in the array, thus flattening the tree.

To do this I run it through a helper function I made below.

<cffunction name="flattenArrayTree" access="public" output="false" returntype="array">
<cfargument name="array" required="true"/>
<cfargument name="result" required="false" default="#[]#"/>
<cfargument name="treeDepth" required="false" default="0"/>
<cfargument name="childrenPropertyName" required="false" default="children" hint="A property with an array of child objects."/>

<cfset var local = {}/>
<cfset var i = ""/>

<cfloop from="1" to="#arrayLen(arguments.array)#" index="i">

<cfset local.object = arguments.array[i]/>

<cfset local.object.setTreeDepth(arguments.treeDepth)/>

<cfset arrayAppend(arguments.result,local.object)>

< !---make sure the "children" property exists is in the object--->
<cfif not structKeyExists(local.object,"set"&arguments.childrenPropertyName)>

<cfthrow detail="The argument childrenPropertyName which is currently #arguments.childrenPropertyName# does not exist as a property in the object"/>

< /cfif>

<cfif arrayLen(local.object._get(arguments.childrenPropertyName)) gt 0>

<cfset arguments.treeDepth++/>

<cfset arguments.result = flattenArrayTree(local.object._get(arguments.childrenPropertyName),arguments.result,arguments.treeDepth)/>

<cfset arguments.treeDepth--/>

< /cfif>

< /cfloop>

<cfreturn arguments.result/>

< /cffunction>

You will notice I add a property called "treeDepth". In order to use the function you need to add a property to the model cfc called "treeDepth". Don't worry about it being added to db, if it's not mapped in hibernate file it won't be added to the db. I use the treeDepth property to know how far in a child object is. Technically...you don't need this, but I find a very handy.

Monday, July 12, 2010

CF9 ormsetting dialect

I was just wondering why you need to specify a dialect in ORM, if you define this in your datasource?

Example:
Application.cfc
this.ormSettings = { datasource="jbankenBlogspot",dialect="MySQLwithInnoDB" };

I shouldn't have to specify dialect="MySQLwithInnoDB" if I did it already in my datasource. Maybe I am missing something here.

The real hard part is that hibernate was throwing an error that was the same as if you had a bad path to your entity cfc.

Wednesday, July 7, 2010

ColdMVC: Parse checkboxes or radios generically

I ran into an interesting issue awhile, back. I wanted to edit a product and click on checkboxes for one to many relationships to colors, categories, and sizes. When I post the form to the ProductController save() I wanted a generic way to convert checkbox values (which are ids) to actually objects. Below are the steps I took followed by the code.

First, I call private functions to parse the specific checkbox ids ( Ex. parseCategories()), but they all just call parseResource().

Next, while in parseResource() I look into the variables scope for the model (Ex. _Size) to dynamically get the object by using findByID().

Lastly, I append the object to an array and populate the Product object and save it.

ProductController.cfc

/**
* @accessors true
* @action list
* @extends coldmvc.Controller
*/
component {
property _Size;
property _Color;
property _Category;

function save() {

var product = _Product.new();

params.product.categories = parseCategories(params.product.categories);
params.product.sizes = parseSizes(params.product.sizes);
params.product.colors = parseColors(params.product.colors);

product.populate(params.product);

product.save();

redirect({controller="product",action="setup"},"productID=#product.id()#");
}

private array function parseCategories(string categoryIDs) {

return parseResource("Category",arguments.categoryIDs);

}

private array function parseSizes(string sizeIDs) {

return parseResource("Size",arguments.sizeIDs);

}

private array function parseColors(string colorIDs) {

return parseResource("Color",arguments.colorIDs);

}

private array function parseResource(string resource, string resourceIDs){

var resources = $.string.toArray(arguments.resourceIDs);

var result = [];
var i = "";

for (i=1; i <= arrayLen(resources); i++) {

arrayAppend(result, variables["_#arguments.resource#"].findByID(resources[i]));

}

return result;

}
}


I wanted to share this just in case someone else is running into the issue.

Thursday, June 24, 2010

CSS hierarchy wish

Alot, of times I find myself having a wrapper around some elements in my html so that I can do some custom css inside of it. In the css case below the wrapper is a div with a class of "webfolio".

div.webfolio h3{
font-size:1.5em;
color:#333;
}

div.webfolio div.article{
border:1px solid #666;
}

div.webfolio div.description{
color:#555;
}

Notice I have to write "div.webfolio" over and over. I just want to write it once, with everything (it's children) inside of it. I wish I could do it like this:

div.webfolio{

h3{
font-size:1.5em;
color:#333;
}

div.article{
border:1px solid #666;
}

div.description{
color:#555;
}

}

I just feel dirty writing the same name over and over. Yes, I realize if you get more than one or two deep in above css it would get harder to read. In a perfect world this could be prevented by code responsibility.

Tuesday, May 25, 2010

From SQL to HQL

Most of the development I have done has been with SQL records. Now that CF9 is out I've started playing around with HQL objects and it has been a learning curve but for the best. I struggled and continue to struggle with writing HQL, because my mind still wants to do SQL. I wanted to share what I have learned so far.

Given the db schema below I will show how to write a piece in sql followed by a piece in hql.

There is a PRODUCT table with a many to many relationship with the SIZE table and the PRODUCT table has many to many relationship with the CATEGORY table.

PRODUCT -|-----= PRODUCT_SIZE =------|- SIZE
PRODUCT -|-----= PRODUCT_CATEGORY =-----|- CATEGORY

1. Get all the products
SQL

select * from product


HQL

from Product


2. Get all the products with price equal to $100.
SQL

select * from product where price = '100'


HQL

from Product where price = '100'


3. Get all the products with size_id = 1.
SQL

select * from product
inner join product_size on product.id = product_size.product_id
where product_size.size_id = 1


HQL

select product
from Product product
join product.sizes size
where size.id = 1


4. Get all the products with size_id = 1 and category_id = 1.
SQL

select * from product
inner join product_size on product.id = product_size.product_id
inner join product_category on product.id = product_category.product_id
where product_size.size_id = 1
and product_category.category_id = 1


HQL

select product
from Product product
where exists (
from product.categories category
where category.id = 1
)
and exists (
from product.sizes size
where size.id = 1
)


Note: HQL can't solve all queries, a good example is Accounting queries, but it does help with the majority of the light weight queries. I get the line "Well what's the point of using objects if records work fine.". I reply with "There is no point, but if you want to update all your queries with new properties, you will quickly find the point."

Resources used:

http://www.barneyb.com/barneyblog/2010/05/05/embrace-your-hsql/

Sunday, April 11, 2010

ColdMVC: Create your own Helpers.

I wanted to try extending ColdMVC's helpers and create my own helper that formatted stuff for me and it turned out to be quite simple.

First, I created my own directory in my project called "helpers".

Second, I added a cfc named "format".

Third, I extended the ViewHelper from ColdMVC. Not sure, If this is the correct Helper Util class I am suppose to be using...but it worked.


<cfcomponent extends="coldmvc.utils.ViewHelper">

<!------>

<cffunction name="money" access="public" output="false" returntype="any">
<cfargument name="amount" required="false" default="0"/>

<cfreturn dollarFormat(arguments.amount)/>


</cffunction>

<!------>

</cfcomponent>


Lastly, I used my new helper function:

#$.format.money(product.getPrice())#


If you noticed in money() I set a default value of zero. For some odd reason when I put "product.getPrice()" in for the amount argument it has a value of [empty string] and it throws an error. The error says "The AMOUNT parameter to the money function is required but was not passed in.". But clearly there is a value of [empty string]. If any one knows what up give me hollar.

Entity Name is same for two CFCs

As I have been trying out CF9 and the ColdMVC I occasionally get this error "Entity Name Category is same for two CFCs". Where "Category" is my model cfc. This is ok if I really had two CFC's with the same name. Here's the rest of the error:

Entity Name Category is same for two CFCs, superior.app.model.Category and superior.app.model.Category.

As you can see, the error looks like it's pointing at the same file. Searching up and down my Eclipse project explorer I find no two cfc with the same name. Guess what...do a refresh on your model directory or where ever you put your VO's. You probably have two hibernate files, both containing your VO's name...mine was "Category".

Get rid of one of them and it should work.

Tuesday, April 6, 2010

Exploring ColdMVC

If you haven't checked out ColdMVC yet you should. It's a light weight ColdFusion ORM framework I've being playing around with. The biggest thing I was impressed with is the tags on the views you can make...I am easily satisfied.

Have you ever been tired of typing that same css container.
Ex:

<div class="buttons">
<!--- some buttons --->
</div>


With ColdMVC's tags that section turns into:

<buttons>
<!--- some buttons --->
</buttons>

The tags help keep the view clean. The only worry that I have NOT ran into yet is that helper tags are very similar to html tags. Not sure how it will play out yet, but no problems so far.

Monday, March 15, 2010

Just Do It : Programming to the Nike Approach.

After reading a recommended book by a friend, I wanted to talk about the Nike's old marketing slogan, "Just Do It.", and it's relationship to my programming experiences. Nike's "Just Do It" slogan really helps me answer those 50/50 questions or "hmm, we could probably use this snippet of code in other places, but I am not sure if it should be reused" or "this might be a pretty good idea, but I am not sure if we have permission to do it." you have when you are programming. Do what you think is right. Basically, JUST DO IT! There have been so many times another programmer or myself have been stuck or afraid of making a business decision becomes of fears of the wrong outcome. The fact is "no one likes to make decisions" period, so presenting it to another person really just causes frustration. So just code it the way you think it needs to be done.

Now, I am not saying you should do this for ever decision but most of the decisions left up to a developer are minor in the eyes of the user. They want you to tell them how they should work and they will tell you what's missing, named wrong, or doesn't work. So I invite you to be bold like Nike and "Just Do It.".

Throw that extra icon or link in there.
Set the smart default you think you would use the most.
Constrain the user to a set of options to choose from to better focus the experience.

Once it's coded and demo-able, have another couple set of eyes look at it. They will tell you what works and doesn't work, but at least you create some discussion on your concern by showing. Showing is such a strong yet hard thing to accomplish in programming, because it's hard to finish something. By getting something to show you are very close if not finished with your task. People aren't dump, they will notice the changes you did and if they don't that means they don't care and your in the clear or you chose "what the user will naturally want" and it will work. Either way it's a silent win for you.

If you spend too much time deciding how something should be done vs. doing it, more and more requests will be added and you will get overwhelmed with tasks. Just code it and demo it to a group of people, whom will spend the next week ripping and tweaking the piece you created, until they figure out what they want. Where this kinda sucks cause you will have to go back and look at your code, you will find out what worked and didn't, be able to create some direction for your self by involving others in your concerns, and be more prepared for the next task for which you can transfer the tips you learned. It also allows you to focus more on code instead of managing politics.

In recap...Just Do It!

Simplicity vs. DRY code

I was in a pickle today over whether or not to consolidate code or keep it a little bit wet for simplicity sake. I consider simplicity sake, going to a view and not having to unlock the rubric's cube of "if" logic. If you are not familiar with wet and dry code, wet is where you repeat yourself over and over and dry is where you "Don't Repeat Yourself (DRY)". I went with "Simplicity". I decided to consolidate parts of the view, yet repeat myself a little. I found this to be safe because I felt like the views would grow and I didn't want it to end up with a crazy page that only the maker has the key to unlocking its craziness. Yeah, we have all seen some of those old pages that are a disaster to debug and I didn't want to start that trend. Also, I wanted the next person behind me to get in and out of the view as quickly as possible. It wasn't very much fun going through every view and updating the same piece of code...but it was simple.

Sunday, March 14, 2010

Small == Big

Have you ever tried to over architect something so that it fits all cases and solves world hunger?

I think we have all ran into this problem before and I think it's due to fear. We are afraid that the wierd, the one-off case comes along and we have to re-work our code that we spent so much time and thought into. Let's be honest no-one likes to go back and repeat something all over again, just because of one little feature/request. Sadly, no matter what you do, it will quickly become out-dated and need to be looked at again. On the flip side, the cool part is that you get solve the issue in a new way.

One thing that helps remind me not to over architect something is to start small. Solve your issue for one record. Example: "Add one user to the system". Solving for one record helps you identify the core pieces that make up the record.

Next, go back and tweak your code to do a group of records. Example: "Add a group of users to the system." Processing records in a group helps save the end user time.

And finally package your code, if you it's generic enough, to be used by other systems. Packaging helps the next developer who needs to solve a similar issue jump start there development efforts and gives them a feeling of "safety net" that someone else can help them if they get stuck.

Going back and touching your code sucks but it can be made more fun if you try to solve for the group of records and packaging. It will help you discover a new solution to your issue and keep you interested in your re-work.

Remeber:
1. One record
2. A group of records
3. Package it for the next developer

Indexed views, not using your indexes

I was working on an export where we were building a query in a string to be passed to a CLR through a stored proc to a small .NET assembly on the db server and ran into some issues with performance. Now, of course CF is slow at running queries...that's why we passed to it .NET to handle the execution, but I didn't think .NET would be slow. I couldn't figure out why my query was slow for the life of me. All the indexes were place, no extra joins were added and the query still took 20 minutes to run. After talking to a DB developer he told me that even though we indexed the sql "views" the indexes were not being used. I quickly freaked out wondering why SQL didn't use the indexes on the views like it uses the indexes on the tables. It should be assumed. Turns out the reason was that, "It is just one of those things". To fix the issue we added "with noexpand" to the joins to the indexed view and then query time went down to about 8 seconds. Ridiculous.

StructSort() does not sort your keys

Ran into an issue on Friday where I was trying to sort a struct numerically by it's keys. My struct looked something like this {"1"= query,"11"=query,"2"=query}. I first tried StructSort(struct) but it didn't work for me, it kept erroring on me. I wanted my keys to be sorted like this 1,2,11 but we all know CF automatically sorts your structs alphabetically.

So I tested structSort() with a different struct like this {"1"= "1","11"="11","2"="2"}. Bam! It worked. Hmm...something is fishy here. StructSort() works with simply values, but not complex values...but it should be just looking at the struct's keys. Anyways got around it by doing this listSort(structKeyList(struct))

Tell the join how to join.

I have been having a lot issues…with query execution plans lately (using CF and SQL). SQL has been choosing shitty plans thus making my query slow. If you have ever looked at execution plans, they are difficult read...unless you are a DB developer. I have had no idea wtf was going on with these plans…until now. Another developer sent this great link explaining what the joins are doing in the execution plan. You can then tell your joins in your query how to join.

Example:
select * from [user]
inner hash join enterprise_user on enterprise_user.user_id = [user].id

An execution plan does more than just join identification, such as indexes, but the join thingy is all I really cared about at the moment.

P.S. Only specify the “how to join” if you have to; if your query blows at running, let SQL try to calculate the best plan.

Use Case: Had a query in cfquery tags and it was choosing an execution plan with nested loop joins instead of the fast hash joins.

Tuesday, February 16, 2010

Developer's Inspiration

I have read a lot of blogs of web designers who have a post about "Sources of Inspiration" and I just wanted to through one out there for the developers.

Outdoors

The outdoors is a great way to relief stress and concentrate on a single problem. In other words, "It gives you a chance to clear away all the daily bull shit and focus on the problem at hand." When I am talking about "The Outdoors" I am not talking about having your window open while you play video games. I am referring to remote areas usually where vehicles can't go. Examples of outdoor places would be the woods, a cliff, or a lake/river. I personally find the woods to be the most beneficial because of the silence and random things that can keep your eyes busy and your mind relaxed, yet turning.

We as developers don't care that much about the looks of that app or naming things in it...even though we should. I have had many walks in the woods where I have came up with a solution for a navigation issue by just looking at how the trees where aligned, just as an example of how the outdoors have inspired me.

A few things that can create inspiration:
• Hiking/walking in the woods
• Mountain biking
• Hunting/Archery
• Golfing for pleasure.
• Lawn mowing...because you get in the zone, at least I do, and nothing else matters. Until you mow over the flowers.

Constructing Things

One word...Lego’s. Lego’s, in case you don't know, are small little bricks that fit together and you can build things out of them. Kind of like pieces of code that form an app in nerd speak. While the outdoors in the section above focus more on freedom, constructing things focuses on constraints. When you construct something you are usually limited by the resources you have available. Example you are building a bed and you only have steel, well how do you make the most out your steel to maximize the outcome of the bed. The constraints force you to be creative to solve a solution and often require you think in a different way. My uncle told me a quote once that helps describe this better than I am right now. He said, "Poverty is the fuel of innovation". Poverty is the problem and the constraint and it requires you to maximize the outcome. We as developers can relate to this easily by having very little time or resources as our constraint and a business requirement as our problem.

A few of things that can create inspiration:
• Lego’s
• Carpentry
• Chingling a roof
• Arts and crafts...if you are in to that stuff.

Kids

Kids are great for inspiration because they see things in a simple way and don't care about the complexities. Often times we only see things in a overly complex way because we are trying to account for all the bullshit one-off requirements that we are trying to satisfy. Sometimes if we break these complexities into simple pieces it helps you see the hidden path through the labyrinth of craziness. A thing that web designers do that I am going to steal because developers don't do it enough is "The drawing board." This is the concept of writing all your complexities on a white board and moving them around and fine tuning them until you can see the path. Granted sometimes you need a really big white board but it does help to break things down.

Another thing that kids do well is trying hard at something they suck at. An example of this would include watching 4th graders play basketball. The hoop is clearly too high but they don't care because they are focused at getting a basket. I was able to figure out how I could refactor an old spaghetti code app by watching some kids play basketball. Watching them help me separate the old code into modules with which I could slowing fix while keeping the old code working. How does this apply to the kids playing basketball you might ask?

The kids all crowded around the bottom of the hoop = the spaghetti code.

Pulling one kid aside and explaining to him that if you stand by the free throw line you will be open for a pass by teammate = separating the spaghetti code into modules.

Video games and movies

...nothing really to say here, we all know.

Other blogs

There is a ton of developers and designers blogging inspiration. Read them and take what you need

Monday, February 1, 2010

value-of-select inside an xslt tag's attribute

I've been work with xslt lately and ran into an issue the other day while trying to put the value of a node inside a tag's attribute while in xslt. If you know a little about xslt...this will error out because you can't have a < or > inside the attribute. So what do you do? Well in the past I have been escaping the quotes in xslt and writing a ton of code to something so little...until now. Check it out:

Here is my xml that I want to loop over.

<cfsavecontent variable="xml">


<boarders>
<boarder>
<id>1</id>
<name>Joe</name>
<board>Forum</board>
</boarder>
</boarders>


</cfsavecontent>

<!---Here I am putting the value of the id node in the href attribute of an a tag by escaping quotes. Pretty gross huh?--->
<cfsavecontent variable="xslt">
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xdt="http://www.w3.org/2005/xpath-datatypes" xmlns:xs="http://www.w3.org/2001/XMLSchema" >
<xsl:variable name="XML" select="/"/>
<xsl:template match="/">
<html>
<head></head>
<body>
<xsl:for-each select="$XML">
<xsl:text disable-output-escaping="yes"><</xsl:text>a
href='test.cfm?id=
<xsl:value-of select="boarders/boarder/id"/>
'<xsl:text disable-output-escaping="yes">></xsl:text>
<xsl:value-of select="boarders/boarder/name"/>
<xsl:text disable-output-escaping="yes"></a</xsl:text>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
</cfsavecontent>

<cfoutput>
#xmltransform(xml,xslt)#
</cfoutput>


Now check this out. The same xslt with {} to access the node. Alot cleaner.


<cfsavecontent variable="xslt">
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xdt="http://www.w3.org/2005/xpath-datatypes" xmlns:xs="http://www.w3.org/2001/XMLSchema" >
<xsl:variable name="XML" select="/"/>
<xsl:template match="/">
<html>
<head></head>
<body>
<xsl:for-each select="$XML">

<a href="test.cfm?id={boarders/boarder/id}"><xsl:value-of select="boarders/boarder/name"/></a>

</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
</cfsavecontent>
<a href="http://www.w3.org/TR/xslt#dt-attribute-value-template">http://www.w3.org/TR/xslt#dt-attribute-value-template</a><br/>
<cfoutput>
#xmltransform(xml,xslt)#
</cfoutput>


It, the {}, also supports xslt variables as well.


<cfsavecontent variable="xslt">
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xdt="http://www.w3.org/2005/xpath-datatypes" xmlns:xs="http://www.w3.org/2001/XMLSchema" >
<xsl:variable name="XML" select="/"/>
<xsl:template match="/">
<html>
<head></head>
<body>
<xsl:for-each select="$XML">

<xsl:variable name="boarder_Var">
<xsl:value-of select="boarders/boarder/id"/>
</xsl:variable>
a href="test.cfm?id={$boarder_Var}"><xsl:value-of select="boarders/boarder/name"/></a>

</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
</cfsavecontent>

<cfoutput>
#xmltransform(xml,xslt)#
</cfoutput>


Use Case:
I wanted to merge some data into a set of links that the user clicks on that returns the value to an FCKeditor.

Playing with cfloop's file attribute

I was playing around with cfloop's file attribute and how it only grabs the rows you want to loop over...not the entire file. So cool. I am amazed at how well and easy it is to use. Here's what I got:

<!---data.csv--->
ID,Name,Board,Gender
1,Joe,Forum,M
2,Jamie,Nitro,F
3,Jake,Forum,M
4,Ben,Burton,M
5,Ken,Elan,M


<cfset columns = "ID,Name,Board,Gender"/>

<cfset boarders = arrayNew(1)/>

<cfloop from="2" to="6" file="C:/workspace/examples/file_looping/data.csv" index="row">

<cfset boarder = structNew()/>

<!---loop through the columns and create a struct of the row's data--->
<cfloop from="1" to="#listLen(columns)#" index="column">
<cfset boarder[listGetAt(columns,column)] = listGetAt(row,column)/>
</cfloop>

<!---append the boarder struct to the boarders array--->
<cfset arrayAppend(boarders,boarder)/>

</cfloop>

<cfdump var="#boarders#">


I put the rows in an array of structs to work with it more easily.

Use case:
It works great for imports where you want to throttle the amount of data you process at a time. Example you only want to pull records 1-99 process them, then 100-199 and so on.