Hi Doug,

 

Some good features been added there, nice work.  Just one comment that I can think of immediately, in your post you say…

 

“(Note, calling user.getAddress().delete() will delete the user because the user can’t exist without the address, but calling user.delete() will not delete the address)”

 

This seems to be back to front, I would expect deleting the address to set the user’s addressId to “” or zero, and deleting the user to cascade the delete to the address.

 

Maybe you could just clarify this point

 

Cheers,

Chris

 


From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Doug Hughes
Sent: 18 April 2006 21:38
To: [email protected]
Subject: [Reactor For CF] New Commit committed

 

All-

 

Just a quick email to let you know that the latest revision is out and should be mostly functional.  Now, there are a few things that will break.  The two biggest off the top of my mind are:

 

1)       The event model is gone (sorry sean, you need to update your preso again!).  This has been replaced in favor of another feature.

 

2)       As of now, iterator can’t be re-sorted once they’re sorted or filtered the first time.  This might actually be a serious problem.  I ran into issues already in reactor blog, but I just commented out the code and the app looks ok.  This was done to add support for one much-requested feature.  I’ll look into ways to change this behavior (at least a little) soon.

 

So what can you do with reactor now?  Well, let’s use a few examples based on a user and address.  For the first example, a user hasOne address.  (user.addressId = address.addressId).  Given that you can now do this:

 

<cfset user = reactorFactor.createRecord(“User”) />

<!--- … populate user … --->

 

<cfset user.getAddress().setStreet(“1234 happy”) />

<!--- populate address… --->

 

<cfset user.save() />

 

That will create a new user and address and save them when the user is saved. 

 

(Note, calling user.getAddress().delete() will delete the user because the user can’t exist without the address, but calling user.delete() will not delete the address)

 

(Another important note: validation only validates the current object now because I removed the event model.  I’m hoping Paul can make quick work of validation so we can add that into the mix too.)

 

(Last note, calling user.getAddress().save() does not save the user, just the address.)

 

On the user, if you call setAddressId(123), next time you call getAddress it will reflect the new address.  If you pass a new address into setAddress(), getAddressId() will reflect the ID of that address.  If you pass an empty string into setAddressId the address will be removed from the user.

 

Now, on to the more-fun details.  Let’s say you have a user that hasMany addresses.  (user.userId = address.userId).  The iterator object now has add and delete methods.  Add will add an object into the iterator and return it.  It will not save the record till you call save on the record or save on the iterator (another new method!).  If you call delete on the iterator or the record it immediately deletes the record.  Also, the getArray and getQuery methods on the iterator reflect the changes made to the iterator!

 

The add method accepts three styles of arguments.

1)       Nothing

2)       A record.

3)       A name/value set of arguments.  IE add(addressId=1,foo=”bar”,etc=123)

 

Add also returns the added record.

 

So, these are all valid:

 

<cfset Address = user.getAddressIterator().add() />

<cfset Address.setStreet(“123 foo”) />

<!--- etc --->

 

<cfset user.save() />

 

OR:

 

<cfset address = reactor.createRecord(“address”) .load(addressId=123) />

<cfset user.getAddressIterator().add(address) />

 

<cfset user.save() />

 

OR:

 

<cfset user.getAddressIterator().add(addressId=123) />

 

<cfset user.save() />

 

Delete accepts three styles of arguments.

1)       an index of the item to delete

2)       A record (from the iterator)

3)       A name/value set of arguments.  IE add(addressId=1,foo=”bar”,etc=123)  (This deletes anything it matches)

 

 So, here are some examples:

 

<cfset user.getAddressIterator().delete(1) />

 

OR

 

<cfset Address = user.getAddressIterator().getAt(2) />

<cfset User.getAddressIterator().delete(Address) />

 

OR

 

<cfset user.getAddressIterator().delete(state=”MI”) />

 

Oh this should work for linking relationships too.  IE: User, UserAddress, Address where user.userId = UserAddress.userId and UserAddress.addressId = address.addressId

 

If you linking table has any columns in it which are not automatically populated you might run into issues (but there’s a work around for it).  If you’re using a multi-step link, this won’t work and will throw errors.  (The errors should be helpful, if not that’s a bug)

 

So, given the above structure and assuming a user only has one record (because I’m explicitly getting the index), the following is true:

 

user.getAddressIterator().getAt(1) == user.getUserAddressIterator().getAt(1).getAddress()

 

That is to say, the instance returned by both calls is the exact same instance.  So, if you modify an address via a linking relationship the unlinked relationship reflects the changes (because they are literally the same object).

 

Also, given the above….

 

User.getAddressIterator().getQuery() will return a 1 row query.

 

User.getUserAddressIterator().getQuery() will also return a 1 row query (the record that relates a user to an address)

 

And, if you were to run the following code:

 

User.getAddressIterator().delete(1)

User.getUserAddressIterator().getQuery() will now return 0 rows.  The relating record was deleted because it can’t exist without the address (which you deleted).

 

This should work exactly the same way:

 

User.getAddressIterator().getAt(1).delete()

 

Now, let’s say that instead you had run this code:

 

User.getUserAddressIterator().delete(1)

 

User.getAddressIterator().getQuery() will return 0 rows because you deleted the only relationship (so will User.getUserAddressIterator().getQuery(), btw).  The address, however, remains in the database… it can exist without the link.

 

Let’s see… what else is new?

 

Once a record is deleted you can’t (or shouldn’t) reuse it and reuse will throw an error.  This is to support the automatic removal of deleted items from iterators without the iterator being told the item was deleted.

 

Records have an isDirty method.  This basically compares the current state of the object to the initial state of the object (or the state after initing, loading, or saving the record).  You can manually call the clean method to clean a dirty record.  Don’t do this though. ;)

 

Records have an isDeleted method.  This indicates if the record was deleted (and can save you from thrown errors).

 

Records also have beforeSave(), afterSave(), beforeDelete(), afterDelete() and beforeLoad() and afterLoad() methods.   I suspect theses can be overridden, but be sure to call the super method!  (they’re all private so you can’t manually call them.)

 

Iterators now have a get method which, like add and delete accept either an index or a set of name/value pairs.  This returns an array of matching records in the iterator.

 

Iterators have a delete method (documented above)

 

Iterators have a deleteAll method which just calls delete several times.

 

Let’s say you’re using the address/useraddress/user linking relationship above.  You call user.getAddressIterator()  From the AddressIterator you can call getLinkIterator which will return the results of user.getAddressIterator from the user.

 

That seems to be it. 

 

I’m going to take a break and then work on implementing some of these updates in my applications and the samples.

 

Doug

-- Reactor for ColdFusion Mailing List -- [email protected] -- Archives at http://www.mail-archive.com/reactor%40doughughes.net/ -- Reactor for ColdFusion Mailing List -- [email protected] -- Archives at http://www.mail-archive.com/reactor%40doughughes.net/

Reply via email to