How to handle similar logic in a controller

38 views
Skip to first unread message

Raymond Camden

unread,
Feb 27, 2010, 2:04:07 PM2/27/10
to framework-one
Imagine for a moment we have 3 related events

blog.view
blog.addcomment
blog.edit

Each of these does something with a blog entry. For each then I need
to look at rc.blogid and load a blog entity. In Model-Glue, I'd have
all 3 events broadcast a getBlogEntry message. I'd have a controller
method that would get and validate event.getValue("blogid"). Each
event would run that first, then do what they need to.

In FW/1, I'm not sure how to get the same behavior. My best guess is
that I could make a private method in my controller to handle getting/
validating rc.blogid and setting rc.blog to the result of a service
call.

Does that seem sensible?

Dan Vega

unread,
Feb 27, 2010, 2:47:29 PM2/27/10
to framework-one
What are you trying to validate? That the id being passed is valid?
Here is my edit method

public void function edit(){
if(isNumeric(rc.id)){
rc.user = variables.fw.getService("User").load(rc.id);
if( isNull(rc.user)){
rc.error = "User not found";
} else {
rc.roles = variables.fw.getService("Role").list();
}
} else {
rc.error = "Invalid id";
}
}

It calls a load method.

public any function load(Numeric id){
if(arguments.id == 0){
return new();
} else {
return entityLoadByPK("User",arguments.id);
}
}

I guess I still don't understand your question, hope this helps at
all :)

Andrew

unread,
Feb 27, 2010, 3:37:10 PM2/27/10
to framew...@googlegroups.com

CFer

unread,
Feb 27, 2010, 3:38:09 PM2/27/10
to framework-one
I am not familiar with Model-Glue either but it seems like the
functionality you want can be handled in the "before" method in the
blog controller (controllers/blog.cfc)

The before method runs before any function in the section controller
so you could check if the "blogid" is defined and if it is, validate
it (invoking a function directly).

Hope that makes sense.

On Feb 27, 2:04 pm, Raymond Camden <rcam...@gmail.com> wrote:

Dutch Rapley

unread,
Feb 27, 2010, 3:58:08 PM2/27/10
to framew...@googlegroups.com
Ray,

IMO, this is a good example of where using a bean factory can come in handy. FW/1 integrates really well with bean factories, as it has the ability to auto wire bean factory beans directly into your controllers.

Let's say you have a bean called blogEntryDao. This bean will have a method called getBlogEntry().

In your blog controller, you would auto wire blogEntryDao with:

function setBlogEntryDao(blogEntryDao) {
    variables.blogEntryDao = blogEntryDao;
}

function getBlogEntryDao() {
    return variables.blogEntryDao;
}

In your view(), addComment(), and edit() controller() (or their accompanying start*) methods, you can call
var rc.blogEntry = getBlogEntryDao().getBlogEntry(rc.blogid);

That's just one way, and particularly how I would do it since I leverage ColdSpring in almost all of my projects.

-Dutch


--
You received this message because you are subscribed to the Google Groups "framework-one" group.
To post to this group, send email to framew...@googlegroups.com.
To unsubscribe from this group, send email to framework-on...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/framework-one?hl=en.




--
Dutch Rapley
www.dutchrapley.com

Raymond Camden

unread,
Feb 27, 2010, 5:35:25 PM2/27/10
to framework-one
Dan, your code is fine - but it is one method. Again, imagine you
wanted to validate ID for N methods.

Raymond Camden

unread,
Feb 27, 2010, 5:35:57 PM2/27/10
to framework-one
Interesting - that does seem like a valid way of doing it1

On Feb 27, 2:37 pm, Andrew <colossina...@gmail.com> wrote:
> Could you use doController?
>

> http://fw1.riaforge.org/wiki/index.cfm/ReferenceManual#private_void_f...

Raymond Camden

unread,
Feb 27, 2010, 5:36:34 PM2/27/10
to framework-one
I know about the before method. That isn't the problem. The problem is
that I have N controller methods with similar logic. Normally that
would have been handled by one broadcast in MG. I don't want to repeat
code in 3 or more before methods.

Raymond Camden

unread,
Feb 27, 2010, 5:37:54 PM2/27/10
to framework-one
But to me - this is an issue _before_ my service layer. I typically do
validation of URL params (event params really) at the controller
layer. ("If the ID is bad, go to some other event.") That way my
services are simpler. Your example explains how to get the data which
isn't my problem.

Dutch Rapley

unread,
Feb 27, 2010, 8:15:14 PM2/27/10
to framew...@googlegroups.com
Thanks for the clarification.

In that case and with your situation, I'd probably would start with having a controller method called

isBlogEntryIdValid() - which could contain fw.redirect()

and call it within the start*() methods where you need it.

Then you can use fw.doController().

-Dutch

--
You received this message because you are subscribed to the Google Groups "framework-one" group.
To post to this group, send email to framew...@googlegroups.com.
To unsubscribe from this group, send email to framework-on...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/framework-one?hl=en.




--
Dutch Rapley
www.dutchrapley.com

Dave Anderson

unread,
Feb 28, 2010, 9:12:19 AM2/28/10
to framework-one
Ray - I think your original answer to your own question is right on.
The only refinement I might suggest is that given you're in a 'blog'
controller, it's not unreasonable to assume that 'blogid' is going to
be passed in for many or most of the blog section's items, and
therefore it might make sense to check for a defined blogid in the
controller's before() function and write the getBlogEntry() logic
there. Perhaps the before() function would default rc.blogLoaded to
false and set to true if getBlogEntry() is successful.

Dave

Raymond Camden

unread,
Mar 1, 2010, 8:20:50 AM3/1/10
to framework-one
Now thats a good idea too. Thanks!

Sean Corfield

unread,
Mar 1, 2010, 6:09:21 PM3/1/10
to framew...@googlegroups.com
On Sat, Feb 27, 2010 at 2:36 PM, Raymond Camden <rca...@gmail.com> wrote:
> I know about the before method. That isn't the problem. The problem is
> that I have N controller methods with similar logic. Normally that
> would have been handled by one broadcast in MG. I don't want to repeat
> code in 3 or more before methods.

Remember that in Model-Glue you'd repeat the broadcast in three
events. In other words, you have the duplication already because
you're "calling" the getBlogEntry() method one way or another.

In FW/1, you have one line - var blogEntry =
variables.blogService.getBlogEntry( rc.id ); - in three controllers.
In Model-Glue, you have one line (of XML, broadcasting needBlogEntry)
in three event handlers. Exactly the same principle.
--
Sean A Corfield -- (904) 302-SEAN
Railo Technologies US -- http://getrailo.com/
An Architect's View -- http://corfield.org/

"If you're not annoying somebody, you're not really alive."
-- Margaret Atwood

Sean Corfield

unread,
Mar 1, 2010, 6:10:51 PM3/1/10
to framew...@googlegroups.com
I would strongly discourage use of doController() - see the Reference Manual:

"Although this is currently the documented way to invoke a specific
controller method within Application.cfc methods, a cleaner, supported
way to do this is likely to be provided in future (although these
methods will remain for backward compatibility - deprecated)."

John Allen

unread,
Mar 1, 2010, 10:12:28 PM3/1/10
to framew...@googlegroups.com
I'm finding that adding private methods to my controllers to handle duplicate code like this is very easy to work with.

Raymond Camden

unread,
Mar 2, 2010, 11:30:52 AM3/2/10
to framework-one
With doController being frowned upon I think then I'm well off with
the private method I'm using now in qBall.

On Mar 1, 9:12 pm, John Allen <johnfal...@gmail.com> wrote:
> I'm finding that adding private methods to my controllers to handle
> duplicate code like this is very easy to work with.
>

> On Mon, Mar 1, 2010 at 6:10 PM, Sean Corfield <seancorfi...@gmail.com>wrote:
>
>
>

Todd Rafferty

unread,
Mar 3, 2010, 6:53:20 PM3/3/10
to framework-one
With doController being frowned upon, does the FW/1 team remember that
their examples on the wiki still use it? or is this topic something
completely different scenario and legitmate?

http://fw1.riaforge.org/wiki/index.cfm/DevelopingApplicationsManual#Taking_Actions_on_Every_Request

Example:
function setupRequest() {
var security = getController('securityController');
doController( security, 'checkAuthorization' );
}

Ryan Cogswell

unread,
Mar 3, 2010, 7:22:00 PM3/3/10
to framew...@googlegroups.com
The wiki specifically mentions that this is OK for code that resides
within your Application.cfc since it is already tightly coupled to the
framework. I believe what Sean is particularly trying to discourage
is having "doController" and "getController" calls outside of
Application.cfc. Even for this security example, I would consider it
preferable to use a bean from your bean factory (if you're using one)
for this kind of functionality rather than putting it in a controller.

Ryan

Sean Corfield

unread,
Mar 4, 2010, 8:24:46 PM3/4/10
to framew...@googlegroups.com
I plan to provide a better way to do controller calls inside
Application.cfc as well at which point the wiki and examples will be
updated and doController() will be officially deprecated ("frowned
upon very strongly")...

Jamie Krug

unread,
Mar 9, 2010, 12:22:12 PM3/9/10
to framew...@googlegroups.com
There's already been some great feedback on this thread, which I've certainly benefited from, so thanks all! When Ray first brought up his question, I had pondered the same question, as I've done a good bit of Model-Glue work previously as well. Working on some FW/1 controller development recently, I found myself using private methods that are named much in the way I might name Model-Glue broadcast message. I like this style a lot so far, so I thought I'd share and seek feedback.

Let's use a simple user management app idea. For now, just consider a user.cfc controller that handles user.edit, user.delete and user.show actions. From my FW/1 convention-based controller methods, I'm calling private methods that are much like broadcasting messages in MG (e.g., needUser, requireUser). The user.edit action does not require that a user object be persisted, because the same action might be used to add a new user, in which case a new/empty user object will do. Check it out...

<cfcomponent output="false"><cfscript>

    /* CONSTRUCTOR */

    function init( framework )
    {
        variables.fw = arguments.framework;
        return this;
    }


    /* PUBLIC -- FRAMEWORK CONVENTION METHODS */

    function startDelete( rc )
    {
        needUser( arguments.rc );
        requireUser( arguments.rc );
    }

    function startEdit( rc )
    {
        needUser( arguments.rc );
    }

    function startShow( rc )
    {
        needUser( arguments.rc );
        requireUser( arguments.rc );
    }


    /* PRIVATE */

    private function needErrorRedirect( rc, msg )
    {
        arguments.rc.errorMessage = arguments.msg;
        variables.fw.redirect( action = 'error.show', append = 'errorMessage' );
    }

    private function needUser( rc )
    {
        if ( !structKeyExists( arguments.rc, 'userID' ) )
        {
            arguments.rc.userID = '';
        }

        arguments.rc.user = getUserService().getUser( arguments.rc.userID );
    }

    private function requireUser( rc )
    {
        if ( !( structKeyExists( arguments.rc, 'user' ) && arguments.rc.user.getIsPersisted() ) )
        {
            needErrorRedirect( arguments.rc, 'User not found (userID: #arguments.rc.userID#).' );
        }
    }


    /* BEANS (DI) */

    function getUserService() { return variables.beans.userService; }
    function setUserService( userService ) { variables.beans.userService = arguments.userService; }

</cfscript></cfcomponent>

Thoughts?

Best,
Jamie

Reply all
Reply to author
Forward
0 new messages