So you want to create a CFWheels application? ( Part 3 )
This CFWheels series is heavily borrowed from Dan Wilson's "So You Want to" series about Model Glue:Unity. This entry matches to this post.
Previously in this series, we installed CFWheels, discussed some basic conventions over configuration and concepts in CFWheels, and added our basic flow and navigation. Our Contact-O-Matic is moving right along (this last sentence was borrowed from Dan's post.)
In this segment of our regularly scheduled programming (again borrowed), we will setup a Contactomatic database with tables, add the contact form, and contact list.
Database Setup
CFWheels 0.9.3 supports SQL Server 7 or later, Oracle 10g or later, PostgreSQL, and MySQL 5. You will need to setup a database and a simple table. Here is my code for MySQL 5. Please post your creation code in the comments if you are using a different database system.
DROP TABLE IF EXISTS 'contactomatic'.'contacts';
CREATE TABLE 'contactomatic'.'contacts' (
'id' int(10) unsigned NOT NULL AUTO_INCREMENT,
'name' varchar(45) NOT NULL,
'type' varchar(45) NOT NULL,
PRIMARY KEY ('id')
) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=latin1;
Add a datasource called "contactomatic" to our new database through the ColdFusion Administrator
Config
CFWheels simplifies alot of time consuming steps we have gotten use to in developing ColdFusion application using conventions (or assumptions) of our database and naming. Don't worry, we can override these assumptions/conventions if needed.
Our first convention we encounter in CFWheels assumes our datasource name is the same as the webroot folder name. We will override that in config/development/settings.cfm . Place this code in that file.
<cfset set(dataSourceName="contactomatic")>
More on configuration and defaults.
Environment
We will make sure our CFWheels environment is pointing to development. Check the enviroment.cfm file in the config folder has this.
<cfset set(environment="development")>
More on switching environments.
Model
The Model folder is where we will create cfc files that map to tables. One cfc per table. Since we created a contact table, we will create a contact.cfc and place this code in it:
<cfcomponent extends="Model" output="false">
</cfcomponent>
New Action
We will add the new action in our contact.cfc file in the controller. Add this code to in the Controllers/contact.cfc .
<cffunction name="new">
<cfset newContact = model("contact").new() />
<cfset newContact.name = "Mike Henke" />
<cfset newContact.type = "Friend" />
<cfset newContact.save() />
<cfset renderNothing() />
</cffunction>
And run the page, remember your URL maybe different depending on your URL Rewriting setting.
URL Rewriting On = http://localhost/contact/new
URL Rewriting Partial = http://localhost/index.cfm/contact/new
URL Rewriting Off = http://localhost/index.cfm?controller=contact&action=new
You should see nothing in the browser but check our contacts table.
select * from contacts
Pretty neat, look mamma no SQL!!! What we did was create an object called newContact to represent our Contact table, then added properties that map to our columns.
Create View
Lets drive on and create the new view page. It will have a form to add new contacts, but before we do that let's modify the new action by commenting out this code.
<!---
<cfset newContact.name = "Mike Henke" />
<cfset newContact.type = "Friend" />
<cfset newContact.save() />
<cfset renderNothing() />
--->
Now lets add new.cfm in the Views folder and place this code in it.
<cfoutput>
#includePartial("banner")#
<p><cfoutput>#flash("success")#</cfoutput></p>
#startFormTag(action="create")#
<div>#textField(objectName="newContact", property="name", label="Contact")#</div>
<div>#textField(objectName="newContact", property="type", label="Type")#</div>
<div>#submitTag()#</div>
#endFormTag()#
</cfoutput>
You may remember the includePartial from Part 2. It acts a cfinclude with special powers. We added our banner for navigation this way. The rest of the code looks like ColdFusion functions. They are actually CFWheels Helpers. startFormTag() starts the form tag with an action of create. Pretty intuitive, huh. Take a guess on what textField() does.
Bingo. It creates a text field. You can figure out the rest hopefully :-)
textField() takes the blank newContact object we created in new action and matches the property (column name) and gives it a label.
Run the page and you should see this.
URL Rewriting On = http://localhost/contact/new
URL Rewriting Partial = http://localhost/index.cfm/contact/new
URL Rewriting Off = http://localhost/index.cfm?controller=contact&action=new
Adding Create Action
Lets add the create action in controllers/contact.cfc .
Add this code:
<cfoutput>
#includePartial("banner")#
<p><cfoutput>#flash("success")#</cfoutput></p>
#startFormTag(action="create")#
<div>#textField(objectName="newContact", property="name", label="Contact")#</div>
<div>#textField(objectName="newContact", property="type", label="Type")#</div>
<div>#submitTag()#</div>
#endFormTag()#
</cfoutput>
Enter some data into our form and submit it.
Delete <cfset redirectTo(action="new")> and uncomment <cfset redirectTo(action="list")> in our create action.
List
Lets create our list action and view, then take a break and get a drink. We will go more indepth what we did in the next posts.
Add this code in controllers/contract.cfc, it creates the sql and get a list of our contacts.
<cffunction name="list">
<cfset allContacts = model("contact").findAll() />
</cffunction>
Add list.cfm in the views/contact folder with this code:
<cfoutput>
#includePartial("banner")#
<p><cfoutput>#flash("success")#</cfoutput></p>
<cfif allContacts.recordcount EQ 0 >
-No Saved Contacts-<br />
<cfelse>
<table>
<tr>
<th>Name</th>
<th>Type</th>
</tr>
<cfloop query="allContacts">
<tr>
<td>#allContacts.name#</td>
<td>#allContacts.type#</td>
</tr>
</cfloop>
</table>
</cfif>
</cfoutput>
Add another contact and you should now see something like this.
By now, you should have an appreciation for what CFWheels can do. You should be very impressed by the power of built in ORM and Conventions over Configuration. You should be proud of yourself for making it through these verbose tutorials. In the following series, we will add database access, some ajax and some other interesting pieces to our Contact-O-Matic (again this paragraph was borrowed heavy from Dan's post)




Posted under: 


Nice write-up, Mike! This does a good job of capturing the essence of what you can do rapidly with Wheels. Looking forward to reading the rest of the series.
Pretty nice, you can spoil them and just Scaffold the table, that would really speed things up :D
Hey, people need to know what they're really doing before they use your fancy toys, Raul. ;)
Thanks guys. @Raul I'll probably show the Scaffolding tool when I cover plugins maybe part 7.
I lost you at "Adding Create Action
Lets add the create action in controllers/contact.cfc ." then you use the same cfoutput code previously used in new.cfm
Presumably in contact.cfc it should be some <cffunction name="new"> rather than output?
Thanks Saul, some reason editing this post is a pain :-) here is the actual code
<cffunction name= "new">
<cfset newContact = model("contact").new() />
<cfset newContact.name = "Mike Henke" />
<cfset newContact.type = "Friend" />
<cfset newContact.save() />
<cfset renderNothing() />
</cffunction>
Sorry, completely losing my marbles now, it's the "create" function I'm missing I think Mike.
I understand :-) Looks like that code is wrong also. I probably need to bite the bullet and re-correct this post.
<cffunction name="create">
<cfset model("Contact").create(params.newContact)>
<cfset flashInsert(success="User #params.newContact.name# created successfully.")>
<cfset redirectTo(action="new")>
<!--- <cfset redirectTo(action="list")> --->
</cffunction>
Yes Mike - please correct the "Add this code" example under the "Adding Create Action" header as I TOTALLY got lost until I saw the comments at the bottom.
I know I'm not going to be the last.
A great write-up! Thanks for your work on this!!!
I would like to mention that case really matters. If the Contact.cfc files in the controllers and models folders doesn't have the first letter uppercase, then you will get some errors which will give a beginner (like myself) a really frustrating time trying to follow this tutorial.
Daniel - Are you running on Windows, Mac, or Linux?
I am running on a Mac, but I have my Cold Fusion server setup on a local virtual machine that's running on Debian Linux. I've got Eclipse setup to copy the files I save to a samba share from that Linux virtual machine.
Now that you bring it up, I remember that you can get away with all lowercase in Windows... but Linux isn't so forgiving. I believe from the little bit that I read on the cfwheels documentation page that the convention is to keep the first letter uppercase on the file names of the cfc's.
Sounds like you figured it out. Linux being case sensitive and Wheels does favor Conventions over Configuration so you should try to follow the conventions. Are you in the http://groups.google.com/group/cfwheels it is a great place for questions? And Welcome to Wheels :-)
Mike,
The create action in controllers/contact.cfc is still incorrect. I saw your correction in the comments. You may want to update that. thanks again!