CFWheels Tutorial #2 - Database example

254 views
Skip to first unread message

GregO

unread,
Oct 20, 2010, 4:17:54 PM10/20/10
to ColdFusion on Wheels
I'm trying to use CFWheels after a failed attempt with another
framework.
I'm running into a couple of snags and am hoping one of you can point
me in the right direction so I can figure out on my own what I'm doing
wrong.
I was able to get the first tutorial to work, and am stuck on the
database tutorial.

 1.  Is there a place I can download the code samples to compare what
I have? I'm doing something wrong but it's not clear where my mistake
was made. I'm still not clear if there is supposed to be both an "Add"
and a "Create" within the code sample, but at least think I have the
right place for creating the new "User" object within the Controller;
doesn't look like I did something right though because it doesn't
bring up my view.  I looked in the Subversion trunk but didn't notice
the code for the DB sample. [ I also had a problem with settings.cfm ;
I was using the wrong one (design, development, production, et. al.),
but got that figured out. ]

 2.  What are the correct URLs for invocation?  I used this to bring
up the index and be able to click to the "Add" but that's where it
dies: http://localhost:8500/cfwheels/index.cfm/users

 3.  For your deployments do you use the URL re-writes that are
suggested and only deploy one CFWheels directory or do you deploy
multiple occurrences of the CFWheels code bundled with each
application you are deploying on your website?

Any clues you can provide would be appreciated. I was looking at
another framework that was too heavy and complicated, and I like this
one better and the tutorials are great, but need to make it work so I
can start developing a prototype application and I'm missing some
things from the DB Tutorial.

For what it's worth,  here's my error:

Element USER.NAME <http://USER.NAME> <http://user.name/>  is
undefined in PARAMS.

So I'm not sure if my order for the object creation is correct, or in
the right place. That's why I wanted to compare against a working
version.

I am NOT, I repeat NOT asking you to debug my code.

I'm hoping to find a code sample that's a complete and working version
of the Tutorial so I can see what I did wrong; or a working sample
that persists data using forms so I can see how to wire up my own code
using the CFWheels framework. or fix my tutorial example.  If I get it
working I'd love to update the tutorial on the cfwheels site.

Thanks in advance for any help any of you can provide

Joey

unread,
Oct 20, 2010, 6:40:43 PM10/20/10
to ColdFusion on Wheels
Hey GregO,

Great that you're getting stuck into CFWheels, it took me 5mins to say
"THIS IS MY FRAMEWORK!", but taken me 5 months to completely
understand it, in fact I'm still learning haha.

The best way I tend to learn is by looking at sample code, check out
http://cfwheels.org/docs/1-0/chapter/administration-sample

Hopefully that'll help!

Simon Allard

unread,
Oct 20, 2010, 7:03:16 PM10/20/10
to cfwh...@googlegroups.com
I suggest that you look at the screencasts at cfwheels.org, they are the best way tot start. Chris Peters did a great job!

A+
Simon

2010/10/20 GregO <greg.os...@gmail.com>

--
You received this message because you are subscribed to the Google Groups "ColdFusion on Wheels" group.
To post to this group, send email to cfwh...@googlegroups.com.
To unsubscribe from this group, send email to cfwheels+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/cfwheels?hl=en.


Joey

unread,
Oct 20, 2010, 7:06:05 PM10/20/10
to ColdFusion on Wheels
Oh yeah forgot about those! I keep bugging Chris to make more :x

On Oct 21, 10:03 am, Simon Allard <ellor1...@gmail.com> wrote:
> I suggest that you look at the screencasts at cfwheels.org, they are the
> best way tot start. Chris Peters did a great job!
>
> A+
> Simon
>
> 2010/10/20 GregO <greg.ostrav...@gmail.com>
> > cfwheels+u...@googlegroups.com<cfwheels%2Bunsubscribe@googlegroups.c om>
> > .

GregO

unread,
Oct 20, 2010, 7:50:56 PM10/20/10
to ColdFusion on Wheels
First, thanks for the code sample.
I think I found out what I was doing wrong.
My Add in the controller looked like this:

<cffunction name="add">
<cfset user = model("user").new()>
<cfset flashInsert(success="User #params.user.name# created
successfully.")>
<cfset redirectTo(action="index")>
</cffunction>

And I changed it to this:

<cffunction name="add">
<cfset user = model("user").new()>
</cffunction>

With this as my "create" method:

<cffunction name="create">
<cfset user = model("user").new()>
<cfset model("user").create(params.user)>
<cfset flashInsert(success="User #params.user.name# created
successfully.")>
<cfset redirectTo(action="index")>
</cffunction>

And now it's letting me enter data. The data isn't actually being
posted into my MySQL database but this is huge progress. The fact
it's not being posted also explains why I'm not seeing anything on the
Index so I'll troubleshoot to see why it's not posting.

I also started to watch the ScreenCasts and they are great.

I'll update when I get it working but thanks for your help so far.

Clarke Bishop

unread,
Oct 20, 2010, 7:54:07 PM10/20/10
to cfwh...@googlegroups.com
Another helpful tool for learning Wheels is Raul's scaffolding plugin. Point
it to the database and it writes working starter code for you!

--

You received this message because you are subscribed to the Google Groups
"ColdFusion on Wheels" group.
To post to this group, send email to cfwh...@googlegroups.com.
To unsubscribe from this group, send email to

cfwheels+u...@googlegroups.com.

Mohamad El-Husseini

unread,
Oct 20, 2010, 9:59:09 PM10/20/10
to ColdFusion on Wheels
Why not do this?

<cffunction name="create">
<cfset user = model("user").new(params.user)>
<cfset user.save()>

<cfif user.save()>
flashInsert....
<cfelse>
flashInsert....

Chris Peters

unread,
Oct 20, 2010, 10:04:36 PM10/20/10
to cfwh...@googlegroups.com
That would work too, except without the <cfset user.save()> line.

--
You received this message because you are subscribed to the Google Groups "ColdFusion on Wheels" group.
To post to this group, send email to cfwh...@googlegroups.com.
To unsubscribe from this group, send email to cfwheels+u...@googlegroups.com.

Andy Bellenie

unread,
Oct 21, 2010, 6:42:45 AM10/21/10
to cfwh...@googlegroups.com
Darn, the first comment in the code sample is on the wrong line... it should be the line above :)

On 21 October 2010 11:42, Andy Bellenie <andybe...@gmail.com> wrote:
Hi Greg,

One thing you might find useful is to combine the new and create functions into a single action, that way the user remains on the same url and the code ends up much simpler overall. 

Here's an example:

<cffunction name="new">
<cfif StructKeyExists(params, "user")>
<cfset user = model("User").new(params.user)> <!--- this checks to see if the form has been submitted --->
<cfif user.save()>
<cfset flashInsert(success="User has been created.")>
<cfset redirectTo(action="index")>
</cfif>
<cfelse>
<cfset user = model("User").new()> <!--- no form submission, so just create a new blank user --->
</cfif>
</cffunction>

Andy

Andy Bellenie

unread,
Oct 21, 2010, 6:42:04 AM10/21/10
to cfwh...@googlegroups.com
Hi Greg,

One thing you might find useful is to combine the new and create functions into a single action, that way the user remains on the same url and the code ends up much simpler overall. 

Here's an example:

<cffunction name="new">
<cfif StructKeyExists(params, "user")>
<cfset user = model("User").new(params.user)> <!--- this checks to see if the form has been submitted --->
<cfif user.save()>
<cfset flashInsert(success="User has been created.")>
<cfset redirectTo(action="index")>
</cfif>
<cfelse>
<cfset user = model("User").new()> <!--- no form submission, so just create a new blank user --->
</cfif>
</cffunction>

Andy



On 21 October 2010 03:04, Chris Peters <ch...@clearcrystalmedia.com> wrote:

GregO

unread,
Oct 21, 2010, 12:08:11 PM10/21/10
to ColdFusion on Wheels
Andy -

I love this. I just took the example code though, and did wonder why
there were two separate functions. I'll incorporate these changes
into my sample and try it this way; then I"ll look at the scaffolding
plug-in recommended.

For what it's worth, I've inserted an entry manually into the database
and I can see it *and* edit it successfully, but on adding new ones
they are not persisting. I did add a "User.save() in the create
function but still no go.
> >> cfwheels+u...@googlegroups.com<cfwheels%2Bunsubscribe@googlegroups.c om>
> >> .
> >> For more options, visit this group at
> >>http://groups.google.com/group/cfwheels?hl=en.
>
> >  --
> > You received this message because you are subscribed to the Google Groups
> > "ColdFusion on Wheels" group.
> > To post to this group, send email to cfwh...@googlegroups.com.
> > To unsubscribe from this group, send email to
> > cfwheels+u...@googlegroups.com<cfwheels%2Bunsubscribe@googlegroups.c om>
> > .

Andy Bellenie

unread,
Oct 21, 2010, 12:32:11 PM10/21/10
to cfwh...@googlegroups.com
Post your controller code and let's see what we can do to help.

To unsubscribe from this group, send email to cfwheels+u...@googlegroups.com.

GregO

unread,
Oct 21, 2010, 12:41:29 PM10/21/10
to ColdFusion on Wheels

My controller from the demo is Users.cfc - here it is; I modified for
the cfif in the Administrator sample code but I'm still not saving new
entries.

Should I call it "User" instead of "Users" or would it never be that
and would be something like "Admin" anyway? I want to abide by
whatever naming standard there is within the framework.

<cfcomponent displayname="users" hint="Controller for User Management"
extends="Controller" output="false">


<cffunction name="add">
<cfset set(automaticValidations=false)>
<cfset user = model("user").new()>
</cffunction>

<cffunction name="create">
<cfset user = model("user").new(params.newUser)>
<cfif user.save()>
<!--- The save worked so let's add a message to the "Flash" here to
inform the site visitor that a change was made (the "Flash" is a
session variable that only lasts from one page view to the next). --->
<cfset flashInsert(message="User added!")>
<!--- Redirect back to the "index" action (it's recommended to
redirect after a "POST" request has been made to avoid the site
visitor clicking refresh in their browser and submitting the page
again). --->
<cfset redirectTo(action="index")>
<cfelse>
<!--- Looks like the save failed so we simply render the view page
for the "add" action again. --->
<cfset renderPage(action="add")>
</cfif>
</cffunction>

<cffunction name="index">
<cfset users = model("user").findAll(order="name")>
</cffunction>

<cffunction name="edit">
<cfset user = model("user").findByKey(params.key)>
</cffunction>

<cffunction name="update">
<cfset user = model("user").findByKey(params.user.id)>
<cfset user.update(params.user)>
<cfset flashInsert(success="User #user.name# updated
successfully.")>
<cfset redirectTo(action="edit", key=user.id)>
</cffunction>


<cffunction name="delete">
<cfset user = model("user").findByKey(params.key)>
<cfset user.delete()>
<cfset flashInsert(success="#user.name# was successfully deleted.")>
<cfset redirectTo(action="index")>
</cffunction>
</cfcomponent>


Andy Bellenie

unread,
Oct 21, 2010, 1:11:22 PM10/21/10
to cfwh...@googlegroups.com
Hi Greg,

Replace your controller code with the following:

<cffunction name="index">
<cfset users = model("user").findAll(order="name")>
</cffunction>

<cffunction name="add">
<cfif StructKeyExists(params, "user")>
<cfset user = model("User").new(params.user)>
<cfif user.save()>
<cfset flashInsert("#user.name# was successfully added.")>
<cfset redirectTo(action="index")>
</cfif>
<cfelse>
<cfset user = model("User").new()>
</cfif>
<cfset renderPage(template="edit")>
</cffunction>

<cffunction name="edit">
<cfset user = model("User").findByKey(params.key)>
<cfif IsObject(user) and StructKeyExists(params, "user") and user.update(properties=params.user)>
<cfset flashInsert(success="#user.name# was successfully updated")>
<cfset redirectTo(action="index")>
</cfif>
</cffunction>


<cffunction name="delete">
<cfset user = model("user").findByKey(params.key)>
<cfif IsObject(user) and user.delete()>
<cfset flashInsert(success="#user.name# was successfully deleted.")>
<cfelse>
<cfset flashInsert(error="#user.name# could not be deleted.")>
</cfif>
<cfset redirectTo(action="index")>
</cffunction>

Then you have a single edit.cfm in your users view folder that handles both updates and deletes and you don't have to worry about posting away after double submissions as the redirect is built into the add/edit functions.

One note, the <cfset set(automaticValidations=false)> you have in your add function is a global setting, so it needs to go in /config/settings.cfm - although it's a bloody useful feature so I'd leave it on (assuming you're running on 1.1 RC)

Andy






--

GregO

unread,
Oct 21, 2010, 1:19:51 PM10/21/10
to ColdFusion on Wheels
I moved the set into my config; and replaced my controller with the
suggested code, but now I get that error I was getting before that had
gone away:
"Element NAME is undefined in USER."

I'm seeing that on the "Add"

Thomas DeLoreto

unread,
Oct 21, 2010, 1:19:03 PM10/21/10
to cfwh...@googlegroups.com
In your create function I believe it should read:

<cffunction name="create">
   <cfset user = model("user").new(params.user)>

Unless you changed the object name to newUser somewhere.



--

Andy Bellenie

unread,
Oct 21, 2010, 1:22:02 PM10/21/10
to cfwh...@googlegroups.com
Have you got a textField in the edit form called name?

#textField(objectName="user", property="name")#

GregO

unread,
Oct 21, 2010, 3:45:19 PM10/21/10
to ColdFusion on Wheels
I did change the "newUser" to "user" and I do have the property for
name on my form but my EDIT is now busted too. I get this error
message now when I try to edit (add is still busted now too):

Element KEY is undefined in PARAMS.

Here's those two views:

edit.cfm

<cfoutput>

<h1>Edit User #user.name#</h1>

<cfif flashKeyExists("success")>
<p class="success">#flash("success")#</p>
</cfif>

#startFormTag(action="edit")#

<div>#hiddenField(objectName="user", property="id")#</div>

<div>#textField(objectName="user", property="name", label="Name")#</
div>

<div>#textField(objectName="user", property="email", label="Email")#</
div>

<div>
#passwordField(objectName="user", property="password",
label="Password")#
</div>

<div>#submitTag()#</div>

#endFormTag()#

</cfoutput>

======================

add.cfm

<cfoutput>

<h1>Create a New User</h1>

#startFormTag(action="add")#

<div>#textField(objectName="user", property="name", label="Name")#</
div>

<div>#textField(objectName="user", property="email", label="Email")#</
div>

<div>#passwordField(objectName="user", property="password",
label="Password")#</div>

<div>#submitTag()#</div>

#endFormTag()#

<p>#linkTo(text="+ View Users", action="index")#</p>
</cfoutput>

Mohamad El-Husseini

unread,
Oct 21, 2010, 4:15:24 PM10/21/10
to ColdFusion on Wheels
@ Andy,

<cfset user = model("User").new(params.user)>
<cfif user.save()>

Looking at the above code you posted, I thought .new() did not save to
the database, so how can you check cfif user.save() ? Am I missing
something?

Chris Peters

unread,
Oct 21, 2010, 4:33:01 PM10/21/10
to cfwh...@googlegroups.com
user.save() does the save to the database. It returns true if the save was successful, false if not. That's why it can be included in the if condition.

Mohamad El-Husseini

unread,
Oct 21, 2010, 5:11:06 PM10/21/10
to ColdFusion on Wheels
ahhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh..........

So by doing cfif user.save() we're automatically saving ? and in other
words we don't need a <cfset user.save()> ???

DOOOOOOOHHHHHHHHHHHHHHHHHH! I had no idea!

On Oct 21, 6:33 pm, Chris Peters <ch...@clearcrystalmedia.com> wrote:
> user.save() does the save to the database. It returns true if the save was
> successful, false if not. That's why it can be included in the if condition.
>
> On Thu, Oct 21, 2010 at 4:15 PM, Mohamad El-Husseini
> <abitdo...@hotmail.com>wrote:
> > cfwheels+u...@googlegroups.com<cfwheels%2Bunsubscribe@googlegroups.c om>
> > .

Chris Peters

unread,
Oct 21, 2010, 5:15:04 PM10/21/10
to cfwh...@googlegroups.com
There are a lot of ways to do it, but the way I just suggested requires the least amount of code.

Here are alternative approaches for shits-n-giggles:

Number 1
<cfset user = model("user").new(params.user)>
<cfset user.save()>
<cfif not user.hasErrors()>

Number 2
<cfset user = model("user").new()>
<cfif user.create(params.user)>

To unsubscribe from this group, send email to cfwheels+u...@googlegroups.com.

Andy Bellenie

unread,
Oct 21, 2010, 5:17:50 PM10/21/10
to cfwh...@googlegroups.com
Way to confuse things, Chris :)

Mohamad El-Husseini

unread,
Oct 21, 2010, 6:17:40 PM10/21/10
to ColdFusion on Wheels
hehehehe!

Is it also possible to do <cfif user.delete()> and <cfif
user.update() ??
> >> <cfwheels%2Bunsubscr...@googlegroups.c om>

Chris Peters

unread,
Oct 21, 2010, 6:21:33 PM10/21/10
to cfwh...@googlegroups.com
Yes. Another thing to keep in mind is that save() is smart enough to know whether it should do a create() or update() behind the scenes.

To unsubscribe from this group, send email to cfwheels+u...@googlegroups.com.

GregO

unread,
Oct 21, 2010, 7:26:36 PM10/21/10
to ColdFusion on Wheels
Thanks for all your help everybody.
It's really helping me get a clue on how the framework works.

Andy - I didn't end-up using the refactored version that you and Chris
helped with yet. I would like to do that after I check out the
scaffolding plug-in that was mentioned above.

I did get my code working by going back and make sure my code matched
the sample code after I repaired the issues with what I did in my add.

So my last question is, can I, or somebody else, update the cfwheels
documentation for this tutorial to mention these things:

1) In newer versions of the framework, there is an "environment.cfm"
file that is loaded and determines your environment for your config/
settings.cfm file. Before you set the data source names please check
which environment is selected and modify the appropriate settings.cfm
in the config directory for that environment, for example design,
development, testing, maintenance, or production.

2) The only code that needs to be in your add function within the
controller is to create the new user object because the framework and
the view that you've defined will handle the rest.

<cffunction name="add">
<cfset user = model("user").new()>
</cffunction>

If I'm mischaracterizing how the "add" is coded within the controller
please correct me so I understand what's happening.

I was also looking at the code from the demo again; since I don't have
the "save" on the user model, what forces it to persist to the
database? Is it inherent in the "create" on the object?

Here's the final version of the tutorial code for my controller that
ended up working:

<cfcomponent displayname="users" hint="Controller for User Management"
extends="Controller" output="false">

<cffunction name="index">
<cfset users = model("user").findAll(order="name")>
</cffunction>

<cffunction name="add">
<cfset user = model("user").new()>
</cffunction>

<cffunction name="create">
<cfset model("user").create(params.user)>
<cfset flashInsert(success="User #params.user.name# created
successfully.")>
<cfset redirectTo(action="index")>
</cffunction>

<cffunction name="update">
<cfset user = model("user").findByKey(params.user.id)>
<cfset user.update(params.user)>
<cfset
flashInsert(
success="User #user.name# updated successfully."
)
>
<cfset redirectTo(action="edit", key=user.id)>
</cffunction>

<cffunction name="edit">
<cfset user = model("user").findByKey(params.key)>
<cfif IsObject(user) and StructKeyExists(params, "user") and
user.update(properties=params.user)>
<cfset flashInsert(success="#user.name# was successfully
updated")>
<cfset redirectTo(action="index")>
</cfif>
</cffunction>

<cffunction name="delete">
<cfset user = model("user").findByKey(params.key)>
<cfif IsObject(user) and user.delete()>
<cfset flashInsert(success="#user.name# was successfully
deleted.")>
<cfelse>
<cfset flashInsert(error="#user.name# could not be deleted.")>
</cfif>
Reply all
Reply to author
Forward
0 new messages