Ask Ben: Building A jQuery And ColdFusion Rating System

<!--- Create a unified API resposne. --->
<cfset apiResponse = {
	success = true,
	errors = [],
	data = ""
	} />
 
 
<!--- Try to execute the api request / response. --->
<cftry>
 
	<!--- Param the FORM variable. --->
	<cfparam name="form.image_id" type="numeric" />
	<cfparam name="form.rating" type="numeric" />
 
 
	<!---
		Check to see if this user has already rated this image.
		We do not want to allow duplicate ratings.
	--->
	<cfquery name="existingRating" datasource="#application.dsn#">
		SELECT
			r.id
		FROM
			rating r
		WHERE
			r.image_id = <cfqueryparam value="#form.image_id#" cfsqltype="cf_sql_integer" />
		AND
			r.ip_address = <cfqueryparam value="#cgi.remote_addr#" cfsqltype="cf_sql_varchar" />
		AND
			r.user_agent = <cfqueryparam value="#cgi.http_user_agent#" cfsqltype="cf_sql_varchar" />
	</cfquery>
 
 
	<!--- Check to see if the rating exists. --->
	<cfif existingRating.recordCount>
 
		<!--- Add error. --->
		<cfset arrayAppend(
			apiResponse.errors,
			"You have already rated this image."
			) />
 
	</cfif>
 
 
	<!--- Check to see if we have any errors. --->
	<cfif NOT arrayLen( apiResponse.errors )>
 
		<!--- Insert new rating. --->
		<cfquery name="insertRating" datasource="#application.dsn#">
			INSERT INTO rating
			(
				ip_address,
				user_agent,
				rating,
				date_created,
				image_id
			) VALUES (
				<cfqueryparam value="#cgi.remote_addr#" cfsqltype="cf_sql_varchar" />,
				<cfqueryparam value="#cgi.http_user_agent#" cfsqltype="cf_sql_varchar" />,
				<cfqueryparam value="#form.rating#" cfsqltype="cf_sql_integer" />,
				<cfqueryparam value="#now()#" cfsqltype="cf_sql_timestamp" />,
				<cfqueryparam value="#form.image_id#" cfsqltype="cf_sql_integer" />
			);
 
			<!--- Get the new overall rating. --->
			SELECT
				(
					SUM( r.rating ) /
					COUNT( r.rating )
				) AS overall_rating
			FROM
				rating r
			WHERE
				r.image_id = <cfqueryparam value="#form.image_id#" cfsqltype="cf_sql_integer" />
			;
		</cfquery>
 
 
		<!--- Set the current rating as the response data. --->
		<cfset apiResponse.data = insertRating.overall_rating />
 
	</cfif>
 
 
	<!--- Catch any api errors. --->
	<cfcatch>
 
		<!--- Set the error in our api response object. --->
		<cfset apiResponse.errors = [ cfcatch.message, cfcatch.detail ] />
 
	</cfcatch>
</cftry>
 
 
<!--- Check to see if we have any errors at this point. --->
<cfif arrayLen( apiResponse.errors )>
 
	<!--- Flag the API request as unsuccessful. --->
	<cfset apiResponse.success = false />
 
</cfif>
 
 
<!--- Searialize the API response into our JSON value. --->
<cfset jsonResponse = serializeJSON( apiResponse ) />
 
<!--- Convert the response string to binary for streaming. --->
<cfset binaryResponse = toBinary( toBase64( jsonResponse ) ) />
 
 
<!--- Stream the binary data back. --->
<cfheader
	name="content-length"
	value="#arrayLen( binaryResponse )#"
	/>
 
<cfcontent
	type="text/x-json"
	variable="#binaryResponse#"
	/>

For Cut-and-Paste