Archive

Posts Tagged ‘cfwheels’

Accessing the Flickr API from our CFWheels-powered site

June 17, 2011 Leave a comment

Recently at work, I was tasked with adding a one-off page to our site.  Normally, I hate these kinds of assignments. They tend to break any rules you already have established for the site architecture and style; and once you say “yes” to one such project, you open the floodgates for others.  However, I jumped at the opportunity since this was slightly new territory for me.  For this page I was asked if there was a way to display pictures from our Flickr page on a page in our site for an exhibition about snapshots.  Without thinking for too long, I answered yes.  I remember way back when I was exploring Ruby on Rails, one of the first demos I saw was the one where the speaker accessed the Flickr api to pull in images that matched a given tag he passed in.  I knew it was possible and fairly simple to do this.  What I didn’t know at the time was how to do it and stay within the conventions of the CFWheels framework.

The Requirement

Create a page for the exhibition that displays 4 or 5 thumbnail images from selected sets from our Flickr account.  Each image should be a link to the full image on the Flickr web site.  Under each group of images should be a link to the full set of images on the Flickr site. The page should list the set title and description, along with its thumbnails, followed by a link to the set on Flickr.  The selected photo set id’s would be provided.

My Solution

I decided that since the photoset id’s would be provided, I could make them a list.  I would then loop over the list and pass that it into the api to get the data I needed.  I could then loop over the resultsets to create the display.  Sounded simple enough.

Proof of Concept Prototype

After studying the Flickr public api, I settled on the flickr.photosets.getInfo() and flickr.photosets.getPhotos() methods to provide the data for the page.  First, I hit the flickr.photosets.getInfo() method to get the title and description of each photoset.  It looks something like this:

<cfset photosetList = “photosetID1, photosetID2, photosetID3, photosetID4”/>

<cfloop list = “#photosetList#” index=”x”>

<cfhttp url=”http://www.flickr.com/services/rest/” result=”photoSetResult”>

<cfhttpparam type=”url” name=”api_key” value=”myAPIKey”/>

<cfhttpparam type=”url” name=”method” value=”flickr.photosets.getInfo”/>

<cfhttpparam type=”url” name=”photoset_id” value=”#x#”/>

</cfhttp>

<!—Convert xml text response into an XML document—>

<cfset photosetXMLDoc = xmlParse(photosetResult.fileContent)/>

<cfset photosetNodes = xmlSearch(photosetXMLDoc, ‘//photoset’)/>

<!—Now grab the photos for this photoset—>

<cfhttp url=”http://www.flickr.com/services/rest/” result=”photosResult”>

<cfhttpparam type=”url” name=”api_key” value=”myAPIKey”/>

<cfhttpparam type=”url” name=”method” value=”flickr.photosets.getPhotos”/>

<cfhttpparam type=”url” name=”photoset_id” value=”#x#”/>

</cfhttp>

<cfset photosXMLDoc = xmlParse(photosResult.fileContent)/>

<cfset photosNodes = xmlSearch(photosXMLDoc, ‘//photo’)/>

<!—Loop over photosets to output photoset information—>

<cfloop from=”1” to=”#arrayLen(photosetNodes)#” index=”i”>

<cfset photosetsXML = xmlParse(photosetNodes[i]/>

<h2>#photosetsXML.photoset.title.xmlText</h2>

<p>#photosetsXML.photoset.description.xmlText</p>

<!—display 5 thumbnail images from each photoset—>

<cfloop from=”1” to=”5” index=”y”>

<cfset photosXML = xmlParse(photosNodes[y])/>

<div class=”flickrThumbs”>

<a href=”http://www.flickr.com/photos/user_id/#photosXML.photo.xmlAttributes.id#/” target=”_blank”><img src=”http://farm#PhotosXML.photo.XMLAttributes.farm#.static.flickr.com/#PhotosXML.photo.XMLAttributes.server#/#PhotosXML.photo.XMLAttributes.id#_#PhotosXML.photo.XMLAttributes.secret#_m.jpg” alt=#PhotosXML.photo.XMLAttributes.title#”/></a>

</div>

</cfloop>

<br class=”clear”/>

<a href=”” target=”_blank”>View all snapshots in this set</a>

</cfloop>

</cfloop>

The above code works just fine and honestly, my internal client is satisfied with it.  But I have a couple of problems with it.

    1. All this code is in the view file.
    2. If they decide they like this and want another similar page, I have to code an entirely new page with similar calls to the api.
    3. Logic and display all mixed together.
    4. It’s a lot of code ~50 lines.

A Better Way

There had to be a better way to separate logic and display and a way to make the api calls available to any view that needs it in the future.  I knew there were CF scripts available for the Flickr api, but they aren’t ready made for CFWheels.  I figured there would be a Flickr plugin and I was right.  I downloaded the SimpleFlickr plugin and got to reading the documentation.

I was able to determine the plugin would do most of what I needed so I set about tweaking it a bit to get the rest.  Turns out it was fairly simple and enabled me to separate out the logic from the display and make the api available across the site.  Craig Kaminsky created the plugin which provided a great starting point for me.  I contacted Craig to let him know I was using the plugin and wanted to tweak it a bit and he offered to integrate my changes into the full plugin.  The SimpleFlickr plugin is installed in the plugins folder in my site and I modified the SimpleFlickr.cfc a bit to get the additional information needed for my display.  So now my display code looks something like this.

<cfloop list=”#photosetList#” index=”x”>

<cfloop from=”1″ to=”#arrayLen(photosets)#” index=”i”>

<cfif x EQ “#photosets[i].id#”>

<h2>#photosets[i].title# (#photosets[i].id#)</h2>

<p>#photosets[i].description#</p>

<cfset photos = getFlickrPhotoSetPhotos(#photosets[i].id#)/>

<cfloop from=”1″ to=”6″ index=”y”>

<div>

<a href=”#photos[y].link#” target=”_blank”><img src=”#photos[y].url#” alt=”#photos[y].title#”/></a>

</div>

</cfloop>

<br class=”clear”/>

</cfif>

</cfloop>

<a href=”http://www.flickr.com/photos/#application.flickr_user_id#/sets/#Trim(x)#/&#8221; target=”_blank”><strong>View All Snapshots in this Theme</strong></a>

</cfloop>

Ahh, that’s much better.  Less code. No logic in the display.  And any page in the future can call the api.  Of course the result is identical to the client.  I can live with that.

Nearly all of my modifications to the plugin were to the private methods that deal with manipulating the resultset from Flickr.  Chiefly, I worked on the $getPhotosFromJSON() method to build the link url that would be used in my display.  This also required me to add the photoset.owner and photoset.id into my return array.  I have to thank Craig again for building the plugin in the first place which allowed me to tweak it to my needs.  I really think this plugin is useful for those who need some basic functions from Flickr in their CFWheels apps.

Advertisements

CFWheels Forum and Calculated Properties

March 9, 2011 2 comments

Continuing with my CFWheels powered Forum application, I had a desire to include a thread count and a post count for each forum listed on the main forum page.  In my old spaghetti coding days, I would first have used a retrieveForums query.  Then in my display code, while looping over the retrieveForums recordset, I would then query the threads table passing in the forumID foreign key to obtain a thread count for each forumID.  In a similar fashion, I would get a post count for each forumID.  The code below illustrates this scenario.

<cfquery name="getForums" datasource="myDSN">

 

SELECT * FROM forums

<cfquery>

<cfloop query="getForums">

<cfquery name="getThreadCount" datasource="myDSN">

SELECT COUNT(*)

FROM threads

WHERE threads.forumID = #getForums.id#

</cfquery>

 

</cfloop>

While this is not the CFWheels way, I found out that it is very easy to convert this code into CFWheels syntax with the same results.

Enter Calculated Properties.  Searching the CFWheels blog and documentation, I was able to find this little gem which allows me to assign additional properties to a given object based on a SQL query.  In this manner, property then becomes part of that object without the need to loop over a query to retrieve it as in the above code block.  This property can then be called just like any other property of that object.  Honestly, I’m not entirely sure I worded that correctly, but the bottom line is the result is the same as my spaghetti code example.  Let’s look at the new code in my forum model.


<cfcomponent extends="Model" output="false">

<cffunction name="init">

<!--- Associations --->

<cfset hasMany("threads")/>

<!--- Properties --->

<cfset property(name="postCount", sql="(SELECT COUNT(posts.id) FROM posts INNER JOIN threads ON posts.threadid = threads.id WHERE threads.forumID = forums.id)")/>

<cfset property(name="threadCount", sql="SELECT COUNT(threads.id) FROM threads WHERE threads.forumID = forums.id")/>

<!--- Validations --->

<cfset validatesPresenceOf(property="forumName", message="Forum name is required.")/>

<cfset validatesPresenceOf(property="forumDescription", message="Description is required.")/>

</cffunction>

</cfcomponent>

And the new display code.

<tbody>

<cfoutput query="forums">

<!--- Here we are outputting the forums query.  The forums query will return every forum with a post count --->

<tr height="35" <cfif currentRow MOD 2>bgcolor="##ebebeb"</cfif>>

<td><br/></td>

<td> #linkTo(text="#forumName#", controller="forums", action="viewForum", key="#id#")#<br/> #ParagraphFormat(forumDescription)# </td>

<td><br/></td>

<td>#val(threadCount)#</td>

<td align="center">#val(postCount)#</td>

</tr>

</cfoutput>

</tbody>

My new calculated properties–threadCount and postCount are now part of the forums object and can be used just like any other field/property in that object.

I hope my explanation makes sense.  Calculated properties will come in handy as I move forward with this project. CFWheels makes another programming task so much simpler.

Late to the game. CFWheels 1.1x

March 9, 2011 1 comment

I know I’m really late, but I’m just now getting around to switching to CFWheels 1.1. I guess being over forty, I’ve become set in my ways.  I love CFWheels already.  Why does it have to change?  Enough already.  I’m taking the plunge.  A while back I had started on a very simple forum application for work.  The forum is based on an old tutorial project I had worked through on EasyCFM.com.  I thought it would be a good idea to do it using CFWheels.  Due to legacy code issues, I had to abandon that effort and use spaghetti CF code, but I kept the work I had completed in CFWheels 1.0 thinking I could come back to it later one day.  That day is here, but I think before I resume, I will update to CFWheels 1.1 and then work to finish the forum.

Forum Application Built on CFWheels 1.0

Forum Application Built on CFWheels 1.0

First up, download the new framework code.  Simple enough. Visit http://cfwheels.org and download the files.  I notice that I’m so late, they’re already up to 1.1.2.  I’ve got some catching up to do.  They also have provide an Upgrading to Wheels 1.1.x guide which states that all that is really necessary to upgrade is “replace the wheels folder with the new one from the 1.1 download.”

My first step will be to upgrade the application to CFWheels 1.1.2.  Once I have it back up and running, I will then continue with development.  The goal is to create a forum with many of the common features we have come to expect in a forum application.  I hope to learn about the new features of CFWheels as well as to create a useful application.  I’ll add new blog posts throughout development.

LitePost on CFWheels – Done!!

October 14, 2010 4 comments

It seems like it’s been forever since I started working to create my own CFWheels version of the LitePost blog application.  Work and life interrupted me along the way, but I managed to finish what I’ll call a first version.  Ironically, the hardest  part seems to have been trying to get it into some sort of version control and accessible for others.  Figured that out, I think, and it is now available on GitHub. I will share some highlights and thoughts of the project.

 

LitePost using CFWheels

LitePost using CFWheels

 

Worry about functionality first. The design can be worked out later.

Early on, I decided to work with text only.  However, I found myself thinking, “This doesn’t look like a blog.”  I then interrupted coding the blog to integrate a layout.  I then went back to coding the application.  What I found was that I began to get more consumed with the output and how it looked rather than the fact that it worked.  I found I was programming for shorter durations of time.

Eventually, I actually took a step back and got rid of the layout altogether so I could just focus on the code.  I  found that I would work longer and with less distraction since I had no design elements to worry about.

Know when to use the scaffold plugin

Immediately upon getting the database created, I set about running the Scaffold plugin for each table.  The Scaffold plugin, which is a wonderful bit of code by Raul Riera, creates the model, view, and controller with CRUD functions for whatever db table you point it to.  I thought this would be a quick way to get up and running so I could concentrate on the more complex code.  It certainly got the application running very quickly, but I found that a lot of the generated code got in my way or caused distractions for me.  This is not any kind of judgement of the plugin itself.  Honestly it could just be me.  Again, I took a step backward and began to code my models, views, and controllers from scratch by hand.  Ironically, this step backward actually resulted in my pace picking up.

What’s next?

I have to admit I feel a tremendous sense of accomplishment at finishing any project and this one was no different even though it is simply a personal project that likely no one will use.  I learned a lot about CFWheels during the course of building LitePost.  I intend to tweak it with additional features and improvements.  My hope is that by making the code public, others in the CFWheels community, the ColdFusion community, or both will  take a look and offer up constructive criticism.  I  feel this is how  I can learn to be a better programmer.

At the top of my list of things I’d like to do is add a rich text editor instead of the plain old  textareas that are currently in use.  I’d also like to come up with a better RSS feed.  Currently the feed is done using the <cffeed> code straight from the CFWACK.  The query is hard coded with no paramaters and the XML is generated at the end all on the same page.  I’d like to do it using a controller and possibly a custom layout that is XML rather than HTML/CFML.

LitePost on CFWheels pt. 2 – Integrating a Layout

September 20, 2010 Leave a comment

Previously, I took care of most of the set up for the LitePost blog application.  The CFWheels core files are in place, the DB created, the Scaffold plugin installed and executed.  I also downloaded the TechJunkie layout from styleshout.com for the look and feel.  It’s time now to apply the layout to LitePost.

Inside the views/ folder is the layout.cfm which is the main layout for all my view files.  This is where I will be making my revisions.  Looking at the index.html file from the TechJunkie layout, I found where the body content begins and ends.  The author of the layout conveniently commented the exact spot and wrapped it in <div> tags for me.  Then, I copied and pasted everything above the <div id=”main”> into layout.cfm just above #contentForLayout#, while copying and pasting everything after the closing </div> after it.  I then added <cfoutput> tags around everything.

Now I needed to take care of a few last steps to get TechJunkie fully integrated into LitePost.  First, Icopied the entire contents of TechJunkie images/ folder into the images/ of LitePost.  Finally I added a stylesheet link tag just after the <title> tag in layout.cfm.  CFWheels has a nice helper function to get this done.  My code looks like this:

#stylesheetLinkTag("TechJunkie")#

CFWheels knows automatically to look in the stylesheets/ folder for stylesheets.  Similarly, CFWheels already knows to look in the images/ folder for all the images I added from the layout earlier.

Thanks to CFWheels, I have spent more time writing this blog entry than I have coding so far.  Next I’ll start coding the main blog page, the entry listing page, and individual entry display page.

LitePost on CFWheels – Getting Started

September 14, 2010 1 comment

Several months ago, the good folks at CFWheels ran a contest to create a version of LitePost using CFWheels.  LitePost is a simple proof-of-concept ColdFusion blog application built using various CF frameworks.  You can learn more at the LitePost project.  Although the contest ended a long time ago, I decided I would build my own CFWheels port of LitePost as a way to get more familiar with the framework.  This will be the first in a series of blog posts of the experience.

Getting started was pretty simple.  I just downloaded the CFWheels framework files and drop them in a project folder under my local webroot.  The I downloaded the LitePost database script and ran it on my local MySQL server.  I also added the Scaffold plugin from the CFWheels plugins directory.  3 steps and I was ready to begin.  But not so fast.  I decided rather than code, to take a step back and think about how a blog should work.  Sounds strange since I use a blog regularly.  But that is precisely the point.  I’ve used a blog before, but I’ve never coded a blog application.  So I’m looking at this blog and how it works so I have a good idea about how things should work in my version of LitePost.

Things I’ve noticed:

  • Blog entries are public, everyone can see them.
  • Everyone can post comments on a blog entry
  • Logged in users can create, edit, and delete entries.
  • The blog main page contains the 5 latest entries with a link to the full list of entries.
  • The category links in a blog post links to a list of blog entries in that category
  • The author link leads to a list of entries by that author

I think I have a fairly good idea now how my blog should work and can begin coding.  That brings me to my first coding task, and I didn’t write a single line of code to do it.  I ran the Scaffold plugin on each of my DB tables to create my models, views, and controllers for my CRUD functions.  That’s a lot of code generated automatically.  Now I can concentrate on customizing the generated code to work similarly to my WordPress blog.

As a last step to getting started, I browsed the styleshout.com site for a suitable layout for my LitePost blog application.  This is a collection of open source html templates you can download and customize for your own site.  I chose the TechJunkie template for my blog.  This template is designed for blogs and I like the color scheme and layout.

That’s it for the initial set up.  In my next post, I will integrate the TechJunkie layout template into the CFWheels framework.

    Learning CFWheels – CRUD and My All-in-One View

    August 19, 2010 3 comments

    In a previous life, I was a Fusebox 4.1 developer.  We had a pretty standard way of making an interface for Creating, Retrieving, Updating, and Deleting records.  All records would be displayed in a table, the last column of which was called the actions column.  In this column, next to each record would be links for Edit and Delete. In the bottom row of the table, would be an empty form with a Add button in the Actions column.  It’s pretty simple, which is probably why we used it over and over again.  We just add a parameter to the form with a default of zero.  We also add it to the two links and change the value to equal that of the current record id.  If the two match, our page knows we are editing this row and the display changes to a form for this row, with a submit button in our actions column.  Clicking submit updates the record and returns us to our table with the updates visible.  This may not be the best way to do this, but it worked and our customers liked it.  The result looks something like this:

    add_edit_delete_interface

    Our all-in-one CRUD interface

    I thought it would be a worthwhile exercise to recreate this using CFWheels for a couple of reasons.  First, it gets me using CFWheels in a real-world situation helping me improve my skills.  Second, I wanted to use the code generated by the Scaffold plugin as a starting point for creating my interface.

    Scaffolding

    The first thing I did was run the scaffold plugin to generate the model, view, and controller files.  Then left me with index, new, show, and edit view files.  Index lists all records, while show displays a single record.  I used the  index view as a jumping off point.  My display actually requires a foreign key to show all the records for a given foreign key.  This made is necessary to modify my index action in the controller as follows:

    <cfset myObject = model("myObject").findAll(where="foreignKeyID=#params.foreignKeyID#")/>

    Creating the all-in-one view

    This retrieves all the records I need for display in my data table.  I also need to set a parameter which we’ll call vCount and we’ll default it to zero.  I then build the table header row and leave one last blank column for our actions.  Now I loop over the myObject recordset to create rows for my data.  Within the loop I need an if block.  First well handle the rows we are simply displaying, so we’ll check to see if vCount does not equal foreignKeyID.  If it does not, simply create a row with each table cell containing a data field for our record.  In the action column, let’s add an edit link like so:

    #linkTo(text="Edit", action="edit", key="#params.key#", params="vCount=#params.key#)#

    Notice we set our vCount parameter equal to the key of the current row.  This leads to our else block, still within the loop.  This time we are checking to see if vCount is equal to the key.  If it is, we create a form for that row only with the appropriate form elements for each field.  In the figure above, the record in row 2 of our table has been selected for editing. In the last cell of the row, instead of putting an edit link, we need a submit button to update the record.

    Now let’s add a delete link.  It’s very similar to our edit link but we’ll add a confirmation like so:

    #linkTo(text='Delete', action='delete', key=id, confirm='Are you sure?', params="vCount=#params.key#")#

    This link will cause a confirmation popup to appear with the text Are you sure. Clicking OK executes the delete action in our controller.  We taken care of the R, U, and D in CRUD.  Let’s handle that create now.

    After our loop, let’s add a new form to create a new row in our table.  In my case, I needed to add in a hidden field for the foreign key value, but that’s about it.   Add a submit button in the last cell of the row, test and we’re done.  A single view handles all the CRUD.

    This interface is probably not useful in all cases, but in our case we were doing a lot of repetitive actions.  We were almost always working with records on a foreign key.  This method provided a quick way to handle that and it was relatively simple to code.  It proved fairly simple to code using CFWheels and I would certainly use it in the  future.  I found that using the scaffold to generate the basic code worked great.  I then customized the generated files to fit my needs in a real world situation.

    I hope this brief write up helps someone who might be considering using the same type of interface to combine the CRUD functions into a single view.  It was certainly a useful learning exercise for me and I think it will prove useful in work in the future.