nested properties and many-to-many models

148 views
Skip to first unread message

Daniel

unread,
Aug 21, 2012, 1:45:58 PM8/21/12
to cfwh...@googlegroups.com
This is the single most frustrating thing I keep coming up against in cfwheels.

I'm doing a multilingual app, and end up dealing with a lot of models that have a nested property with and without composite keys.

It seems like there is no way of getting cfwheels to handle the object creation, form presentation, and model saving with using one object, and the only way to get it to work is to use names that don't conflict with cfwheels objects, and parse each separately and build the model and the nested properties one by one, using the key of the generated object. My problem with that is that I end up with a lot of code that I cannot reuse, so I end up writing a lot of code, and that if the save fails at a later stage, I have to delete models already created.

I've looked at https://github.com/talltroym/cfwheels-nested-properties-demo/ and see that talltroym is building the model and adding the nested properties in the controller of the new action. I've tried this approach, but it doesn't work for a composite key model, which expects two ids in the position.

Has anyone come up with an elegant way of dealing with this?

Chris Peters

unread,
Aug 21, 2012, 2:49:05 PM8/21/12
to cfwh...@googlegroups.com
Nested properties will not work fully with a belongsTo association, so that's probably where you're running into trouble with your many-to-many situation.

I recommend letting nested properties handle the hasMany, but then create a beforeSave callback on the child class that saves the belongsTo children manually. For each save, be sure to return true or false on whether or not the save was successful because you want to interrupt the callback chain if there are problems.


--
You received this message because you are subscribed to the Google Groups "ColdFusion on Wheels" group.
To view this discussion on the web visit https://groups.google.com/d/msg/cfwheels/-/wbuL1EIyxogJ.
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.

Chris Peters

unread,
Aug 21, 2012, 2:50:46 PM8/21/12
to cfwh...@googlegroups.com
One other note: set up the belongsTo nested property to have autoSave=false because your callback will save the records manually. You can leave the autoSave=true default on the hasMany association.

Daniel

unread,
Aug 21, 2012, 3:18:06 PM8/21/12
to cfwh...@googlegroups.com
Hey Chris, thanks for the suggestions.

After posting this I tried a different approach, that I've ended up making into a function. Seems like the problem is the structures' key name. If there was a way to use the key (the way it is in hasManyCheckbox) instead of position, this would not be necessary.



http://snipplr.com/view/66841/renameforcompositekey/

<cffunction name="renameForCompositeKey" returntype="struct">
    <cfargument name="structure" required="yes">
    <cfargument name="keyPosition" required="yes" type="numeric">
    <cfset LOCAL = StructNew()>
   
    <!--- create temporary structure copy --->
    <cfset LOCAL.temp = structure>
   
    <!--- clear structure --->
    <cfset structure = StructNew()>
   
    <!--- loop through keys, and repopulate struct --->
    <cfloop collection="#LOCAL.temp#" item="key">
        <cfif keyPosition EQ 1>
            <cfset structure["#key#,"] = LOCAL.temp[key]>
        <cfelse>
            <cfset structure[",#key#"] = LOCAL.temp[key]>
        </cfif>
    </cfloop>
    <cfreturn structure>
</cffunction>

and I would call it this way
<cfset params.Item.Names = renameForCompositeKey(structure = params.Item.Names, keyPosition = 2 )>

I'll see how well it works once I use it in more controllers, but it worked in my application.

Daniel

unread,
Aug 21, 2012, 4:31:18 PM8/21/12
to cfwh...@googlegroups.com
spoke too soon :(

when it comes to updating the prams structure it's fine, but saving the model fails with

Invalid data '' for CFSQLTYPE CF_SQL_INTEGER.


I thought it would know to use the proper key

is it possible to to do this somehow?

Chris Peters

unread,
Aug 21, 2012, 4:35:51 PM8/21/12
to cfwh...@googlegroups.com
Are there any other columns other than the composite key in this join table?

--
You received this message because you are subscribed to the Google Groups "ColdFusion on Wheels" group.
To view this discussion on the web visit https://groups.google.com/d/msg/cfwheels/-/Yc00Ap_S7CAJ.

Daniel

unread,
Aug 21, 2012, 5:01:10 PM8/21/12
to cfwh...@googlegroups.com

yes, if an item has a name, the record is created, with other fields, since the item is limited to one name and description per language I thought that this would be the most fitting way. Is there another way you'd suggest to set this up?


I've also got another table/model/controller etc that allows multiple names in the same language, so it uses a different identity key. I find that one is tricky to manage, and ended up deleting all records that match the item id and language id and re-creating every time.

Daniel

unread,
Aug 21, 2012, 5:24:20 PM8/21/12
to cfwh...@googlegroups.com
I just did some more testing, it looks like it was a different nested property that was causing the error.
using the function to rename the keys, leaving a blank value for one of the IDs still works.

I've been thinking of ways to tackle this problem for a while now, I think this might be how I'll handle this from here on until cfwheels can handle this sort of situation.

Thanks for your time Chris.
Reply all
Reply to author
Forward
0 new messages