Would you want to do it via the name of the class.. or would you prefer to
ignore by the name of the composition?

Mark

On Sat, Jun 20, 2009 at 3:36 AM, whostheJBoss <[email protected]>wrote:

>
> Well, I had wanted to be able to do this with all my deletes by
> default so I would be able to cascade delete and provide a list of
> objects to ignore without writing custom methods to loop and drill
> through all of the objects. Anyway, I hacked up the change myself if
> anyone is interested in actually adding it to Transfer.
>
> The changes are below (comments are provided where there changes are,
> I only provided snippets showing the portion of the code that contains
> changes). I'm sure I could have put the skip list in the visitingargs,
> but I didn't delve that deeply into it. This works as expected though.
> You call cascadeDelete with an additional argument, which is a comma-
> delimited list of objects to ignore.
>
> I call it this way:
>
>                deleteThis = instance.Transfer.get("users.posts",
> arguments.postID);
>                cdArgs = structNew();
>                cdArgs.transfer = deleteThis;
>                cdArgs.skip = "users.user";
>                instance.Transfer.cascadeDelete(argumentCollection=cdArgs);
>
> This deletes everything on both sides of the post except the
> users.user object.
>
> Here are the changes:
>
>
>
> Transfer.cfc:
> ---------------------------------------------
> <cffunction name="cascadeDelete" hint="does a cascade down the object
> hierarchy, calling delete() as it goes" access="public"
> returntype="void" output="false">
>        <cfargument name="transfer" hint="The transferObject to create"
> type="TransferObject" required="Yes">
>        <cfargument name="depth" hint="the number of levels in which to
> cascade, 0 is unlimited" type="numeric" required="No" default="0">
>        <cfargument name="useTransaction" hint="deprecated: use
> TransferFactory.getTransaction for transaction management. Whether or
> not to use an internal transaction block" type="boolean" required="No"
> default="true">
>        // ******** ADDED SKIP ARGUMENT ********
>        <cfargument name="skip" type="string" required="No">
>
>
>
>
>
> <cffunction name="visitObjectGraph" hint="visit each of the objects in
> the graph, calling 'visit({transfer:transferObject, visitArgs1...})'
> on the visitor for each TransferObject in the graph" access="public"
> returntype="void" output="false">
>        <cfargument name="transfer" hint="the starting object to visit"
> type="transfer.com.TransferObject" required="Yes">
>        <cfargument name="visitor" hint="the visitor object" type="any"
> required="Yes">
>        <cfargument name="visitingMethod" hint="the name of the method that
> is being visited" type="string" required="Yes">
>        <cfargument name="visitArgs" hint="visiting arguments, if there are
> any" type="struct" required="No" default="#StructNew()#">
>        <cfargument name="depth" hint="the max depth to go to"
> type="numeric"
> required="no" default="0">
>        <cfargument name="topDown" hint="travel top down, rather than bottom
> up" type="boolean" required="No" default="true">
>        <cfargument name="forceLoading" hint="if not loaded, force loading"
> type="boolean" required="No" default="false">
>        // ******** ADDED SKIP ARGUMENT ********
>        <cfargument name="skip" type="string" required="No">
> ---------------------------------------------
>
>
>
> DynamicManager.cfc:
> ---------------------------------------------
> <cffunction name="visitObjectGraph" hint="visit each of the objects in
> the graph, calling 'visit({transfer:transferObject, visitArgs1...})'
> on the visitor for each TransferObject in the graph" access="public"
> returntype="void" output="false">
>        <cfargument name="transfer" hint="the starting object to visit"
> type="transfer.com.TransferObject" required="Yes">
>        <cfargument name="visitor" hint="the visitor object" type="any"
> required="Yes">
>        <cfargument name="visitingMethod" hint="the name of the method that
> is being visited" type="string" required="Yes">
>        <cfargument name="visitArgs" hint="visiting arguments, if there are
> any" type="struct" required="Yes">
>        <cfargument name="depth" hint="the max depth to go to"
> type="numeric"
> required="no" default="0">
>        <cfargument name="topDown" hint="travel top down, rather than bottom
> up" type="boolean" required="No" default="true">
>        <cfargument name="forceLoading" hint="if not loaded, force loading"
> type="boolean" required="No" default="false">
>        // ******** ADDED SKIP ARGUMENT ********
>        <cfargument name="skip" type="string" required="No">
> ---------------------------------------------
>
>
>
> ObjectTreeWalker.cfc:
> ---------------------------------------------
> <cffunction name="visit" hint="visit each of the objects in the graph"
> access="public" returntype="void" output="false">
>        <cfargument name="transfer" hint="the starting object to visit"
> type="transfer.com.TransferObject" required="Yes">
>        <cfargument name="visitor" hint="the visitor object" type="any"
> required="Yes">
>        <cfargument name="visitingMethod" hint="the name of the method that
> is being visited" type="string" required="Yes">
>        <cfargument name="visitArgs" hint="visiting arguments, if there are
> any" type="struct" required="Yes">
>        <cfargument name="depth" hint="the max depth to go to"
> type="numeric"
> required="no" default="0">
>        <cfargument name="topDown" hint="travel top down, rather than bottom
> up" type="boolean" required="No" default="true">
>        <cfargument name="forceLoading" hint="if not loaded, force loading"
> type="boolean" required="No" default="false">
>        // ******** ADDED SKIP ARGUMENT ********
>        <cfargument name="skip" type="string" required="No" default="">
>
>        <cfscript>
>                // ******** ADDED SKIP ARGUMENT AND 0 and structNew() for
> currentDepth and visitedHashs to be passed to traverse() ********
>                // ******** traverse() is expecting the argument after
> forceLoading to be depth, I supplied the default value here ********
>                // ******** and did the same with visitedHashs ********
>                traverse(arguments.transfer,
>                                arguments.visitor,
>                                arguments.visitingMethod,
>                                arguments.visitArgs,
>                                arguments.depth,
>                                arguments.topDown,
>                                arguments.forceLoading,
>                                0,
>                                structNew(),
>                                arguments.skip
>                                );
>        </cfscript>
>
>
>
>
>
> <cffunction name="traverse" hint="traverses the object graph"
> access="private" returntype="void" output="false">
>        <cfargument name="transfer" hint="the starting object to visit"
> type="transfer.com.TransferObject" required="Yes">
>        <cfargument name="visitor" hint="the visitor object" type="any"
> required="Yes">
>        <cfargument name="visitingMethod" hint="the name of the method that
> is being visited" type="string" required="Yes">
>        <cfargument name="visitArgs" hint="visiting arguments, if there are
> any" type="struct" required="Yes">
>        <cfargument name="maxDepth" hint="the max depth to go to"
> type="numeric" required="yes">
>        <cfargument name="topDown" hint="travel top down, rather than bottom
> up" type="boolean" required="yes">
>        <cfargument name="forceLoading" hint="if not loaded, force loading"
> type="boolean" required="yes">
>        <cfargument name="currentDepth" hint="the max depth to go to"
> type="numeric" required="no" default="0">
>        <cfargument name="visitedHashs" hint="A struct of the identity hash
> codes, so we know what has been hit" type="struct" required="No"
> default="#StructNew()#">
>        // ******** ADDED SKIP ARGUMENT ********
>        <cfargument name="skip" type="string" required="No">
>
>
>
>
>
> <cffunction name="visitTransfer" hint="visit a single object with the
> method that is provided" access="private" returntype="void"
> output="false">
>        <cfargument name="transfer" hint="the starting object to visit"
> type="transfer.com.TransferObject" required="Yes">
>        <cfargument name="visitor" hint="the visitor object" type="any"
> required="Yes">
>        <cfargument name="visitingMethod" hint="the name of the method that
> is being visited" type="string" required="Yes">
>        <cfargument name="visitArgs" hint="visiting arguments, if there are
> any" type="struct" required="Yes">
>        // ******** ADDED SKIP ARGUMENT ********
>        <cfargument name="skip" type="string" required="No">
>
>
>        <cfscript>
>                arguments.visitArgs.transfer = arguments.transfer;
>        </cfscript>
>
> // SET CLASSNAME OF OBJECT FOR CHECKING AGAINST SKIP LIST
> <cfif #isDefined("arguments.visitargs.transfer")#>
> <cfset skipThis = "#arguments.visitargs.transfer.getClassName()#">
> <cfelse>
> <cfset skipThis = "none">
> </cfif>
>
> // ******** CHECK CLASSNAME AGAINST SKIPLIST TO ALLOW OR DENY DELETE
> ********
>        <cfscript>
> if (NOT isDefined("arguments.skip") or (isDefined("arguments.skip")
> AND listFindNoCase(arguments.skip, "#skipThis#") eq 0)) {
>                getMethodInvoker().invokeMethod(arguments.visitor,
> arguments.visitingMethod, arguments.visitArgs);
> }
>        </cfscript>
> </cffunction>
>
>
> On Jun 19, 8:59 am, Chris Peterson <[email protected]> wrote:
> > Why not write a decorator method to handle it, so you can do
> post.delete(),
> > then have your method troll down the tree and clean up all the related
> > objects?
> >
> > I <3 decorators =)
> >
> > Chris Peterson
> >
> > On 6/19/09 10:26 AM, "whostheJBoss" <[email protected]> wrote:
> >
> >
> >
> > > Has anyone here come up with a way (or written a custom method) to use
> > > cascadeDelete() and specify a list of objects to ignore? (on the way
> > > "up" and "down")
> >
> > > My basic issue is this (example):
> >
> > > I have table of users who can make posts. The posts can have comments.
> > > The comments can have multiple responses, the responses can have
> > > ratings, etc
> >
> > > Basically, lots of relationships between objects.
> >
> > > The posts are tied to users via onetomany, so multiple posts per user.
> >
> > > I have a function for a user to delete a specific post. Of course,
> > > there are all kinds of other things I want to delete when this post is
> > > deleted (the comments, responses, raitings, etc)
> >
> > > If I use cascadeDelete() it works... except that it wipes out the user
> > > object too since it's related to the post. Obviously I don't want to
> > > delete my user, just the post.
> >
> > > Writing a custom function to dig down through and find all the
> > > comments and run delete on each one, then dig down and find the
> > > responses to the comments and delete each one, and so on seems like an
> > > awful lot of extra work when cascadeDelete() ALMOST pulls this off.
> >
> > > I need something like an additional argument to specify objects NOT to
> > > delete during the cascade. Basically to do something like this:
> >
> > > Transfer.cascadeDelete(post, "users.user");
> >
> > > where "users.user" is the object (or comma-delimited list of objects)
> > > to skip over in the delete process.
> >
> > > Has anyone else got an elegant solution for this? Thanks!
> >
>


-- 
E: [email protected]
W: www.compoundtheory.com

--~--~---------~--~----~------------~-------~--~----~
Before posting questions to the group please read:
http://groups.google.com/group/transfer-dev/web/how-to-ask-support-questions-on-transfer

You received this message because you are subscribed to the Google Groups 
"transfer-dev" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/transfer-dev?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to