One of my favorite methods in Model-Glue is makeEventBean(). For those who may not know about makeEventBean() here is the definition of makeEventBean() from the Model-Glue documentation:
Loops over a CFC instance, looking for any methods whose names start with set. For any setter methods where a like-named value exists in the viewstate, the setter will be called, passing this value.
For example, lets say you have a user object, and that user object has methods named setFirstname() and setlastName(). When you want to update this user through the use of a form submission, if you label to the form fields the same as the property they represent, then makeEventBean( user ) (where user is an instance of your user object) will call the setFirstname() and setLastName() methods, passing in the correct values, on the user object.
This is an example of code that might exist in your controller.
<cfset var user = getUserService().getUser( arguments.event.getValue( "userId", 0 ) ) /> <cfset arguments.event.makeEventBean( user ) />
MakeEventBean() is really handy when you have large forms to process as it eliminates the need to call all the setters manually.
When using Transfer, if you have relationships defined (such as a manyToOne) you must set those relationships before you can save the original object. For example, if you are creating a new user, but this user has a property that is another object (company for example), you will need to set the company property in your user Transfer object before you can save the user.
In this case, your code may look like this.
<cfset var user = getUserService().getUser( arguments.event.getValue( userId, 0 ) ) /> <cfset var company = getCompanyService().getCompany( arguments.event.getValue( "companyID", 0 ) ) /> <cfset user.setCompany( company) /> <cfset arguments.event.makeEventBean( user ) />
I will admit that this does not add a lot of code, but if you have a lot of these kind of relationships defined it can get burdensome. Also, to me, it feels like some logic or business process is creeping into our controller that maybe should not be there.
One solution I have started to implement on objects that have manyToOne relationships defined is to make use of Transfer decorators to simplify setting the properties that are other objects. I create methods in the user decorator with names like setCompanyId() that would get executed when makeEventBean() is called. These methods then take responsibility of setting the appropriate property with the corresponding object.
Here is an example of what the setCompanyId() method in our user decorator might look like:
<cffunction name="setCompanyId" access="public" returntype="void" output="false"> <cfargument name="companyId" type="numeric" required="true" /> <cfset var company = getTransfer().get("company",arguments.companyId)> <cfset setCompany(Company)> </cffunction>
Now, when makeEventBean() is called for the user, and companyID exists in the event this new method will take that value and set the correct company object inside of our user object.
This has been working well on a fairly large and complex project I am invovled in and I plan on using this technique moving forward on projects that will utilize Transfer. It has saved us quite a bit if time, and code.
Comments on: "Transfer, Model-Glue and makeEventBean()" (4)
Great tip. I do a lot of surveys and this will be greatly helpful. One question, where would(should) I call makeEventBean()? Assuming using MG, in my controller function for saveForm or the my service layer?
Also, based on your Transfer example, I could use a decorator to do any form field manipulation (like for checkboxes)??
This is a very useful technique, thanks for posting it. It is also possible to achieve the same results without adding any methods (e.g., setCompanyId) to your decorators.
I use a populate() method in my abstract Transfer decorator which makes use of Transfer’s built-in metadata to automatically address any manyToOne and parentOneToMany relationships. It also deals with setting nulls and invalid data. I actually haven’t used makeEventBean with Transfer (only with Reactor in the past), so I’m not sure how it would behave with invalid data. For example, if it tried to put character data into a numeric field, would it throw an error?
I also use that technique, but I’ve found coding my own setXXXid() is repetitive and it slows down my progress dramatically. Any other more elegant solution?
Check out this cool mini fighting game