Save Changes to a Record

Saving changes to a Record is extremely simple.  For instance, let's say I wanted to change the password on this record.  I could simply call the setPassword() method and pass in the new password like this:

 

<!--- let's change the password --->
<cfset UserRecord.setPassword("Foobar123") />

 

If you were to call getPassword() you would see that the object now reports the password as being "Foobar123".  However, if you look in the database you'll see that it hasn't yet been updated.  Committing this change to the database is as simple as this:

 

<!--- time to save the update --->
<cfset UserRecord.save() />

 

Now, if you look in the database, you'll see that the password field has been updated!

 

Creating records works the same way as updating them.  Let's review another quick example to demonstrate this.  We'll pull a few things together:

 

<!--- create the reactorFactory --->
<cfset Reactor = CreateObject("Component", "reactor.reactorFactory").init(expandPath("reactor.xml")) />

<!--- create a userRecord --->
<cfset UserRecord = Reactor.createRecord("User") />

<!--- populate the new record --->
<cfset UserRecord.setUsername("jschmoe") />
<cfset UserRecord.setPassword("foobar") />
<cfset UserRecord.setFirstName("Joe") />
<cfset UserRecord.setLastName("Schmoe") />

<!--- save the record --->
<cfset UserRecord.save() />

<!--- now, let's list all the records in the database --->
<cfset UserGateway = Reactor.createGateway("User") />

<!--- dump all of the users --->
<cfdump var="#UserGateway.getAll()#" />

 

The result of running this code would be:

 

We now have two rows in our database, just as we would have expected.

 

Let's stop here for a second.  I know that this example works for MSSQL.  However MySQL users probably received an error message indicating that the dateCreated value was not a valid date.  Why?  Well, not all database systems let you specify an expression as a default value for a column.  MSSQL does, MySQL doesn't.  Reactor is smart enough to translate a default value of getDate() to a default value of now() in the Record.  Because MySQL doesn't support this, the column doesn't have a default value and Reactor treats it as an empty string.

 

There are two solutions to this.  The quickest and easiest is to simply add a call to setDateCreated() and pass in a call to the ColdFusion now() function.  This works fine, but requires that you remember to do it everywhere.  What if you could do this one time and never have to worry about it again?  You can!  But first, a Reactor anatomy lesson…

 

Record Objects don't hold their own data.  (That would be too simple!)  Record Objects use Transfer Objects to hold their data.  Essentially Transfer Objects are a little smarter than a structure and significantly dumber than a Bean.

 

If you look in your data directory you'll note that there are now five folders.  One of these is "To," which is short for Transfer Object.  If you open the database agnostic UserTo.cfc object you will see this code:

 

<cfcomponent hint="I am the database agnostic custom TO object for the User object.  I am generated, but not overwritten if I exist.  You are safe to edit me."
    extends="reactor.project.Scratch.To.UserTo">
    <!--- Place custom code here, it will not be overwritten --->
</cfcomponent>

 

This looks quite a bit like the customizable UserGateway.cfc, doesn't it?  You may also note that this object extends a project UserTo.  Let's look at that too:

 

<cfcomponent hint="I am the base TO object for the User object.  I am generated.  DO NOT EDIT ME (but feel free to delete me)."
    extends="reactor.base.abstractTo" >

    <cfproperty name="userId" type="numeric" />
    <cfproperty name="username" type="string" />
    <cfproperty name="password" type="string" />
    <cfproperty name="firstname" type="string" />
    <cfproperty name="lastname" type="string" />
    <cfproperty name="dateCreated" type="date" />

    <cfset variables.signature = "D4D176D79148DF927D91FABA697888EB" />

    <cfset this.userId = "0" />
    <cfset this.username = "" />
    <cfset this.password = "" />
    <cfset this.firstname = "" />
    <cfset this.lastname = "" />
    <cfset this.dateCreated = "#Now()#" />
</cfcomponent>

 

I've reformatted the code to fit better in this document, but it's the same code.  You will note that my DateCreated value is being set to Now().  MySQL (and some others) users will see this set to an empty string.  That's the problem.

 

Pop Quiz: How do you set the User TO's DateCreated value to default to Now()?

I'll give you a minute to think about it…

… ok, now that that's done, I'm sure you gave this as your answer:

Override the default value in the customizable UserTo!

You're right!  That's exactly what you should do.

 

Here's what a customized UserTo.cfc would look like for MySQL. This example defaults the DateCreated value to now().

 

<cfcomponent hint="I am the database agnostic custom TO object for the User object.  I am generated, but not overwritten if I exist.  You are safe to edit me."
    extends="reactor.project.Scratch.To.UserTo">
    <!--- Place custom code here, it will not be overwritten --->
    <cfset this.DateCreated = now() />
</cfcomponent>

 

Well done!  MySQL users (and others) rerun your code and you'll see that you can easily add a record to the database.  

The only thing left to demonstrate is how to…