Slightly OT - Question about global functions (eg. buildURL())

91 views
Skip to first unread message

Andrew

unread,
May 7, 2012, 10:03:48 PM5/7/12
to framew...@googlegroups.com
Hi,

This is not a FW/1 question per say, but more a question about stuff that FW/1 does that I'd like to be able to do in other projects. ;-)

One of the awesome things about FW/1 is how you can call functions like buildURL() from anywhere in your app.

How's it work though?  I can't seem to replicate this behaviour.  For example:

BaseThing.cfc
===========

<cfcomponent>

    <cfscript>
        function sayBoo() {
            return "Boo";
        }
    </cfscript>

</cfcomponent>

Application.cfc
===========

<cfcomponent extends="BaseThing">
    <cfscript>
        this.name =  hash( getCurrentTemplatePath() );
    </cfscript>
</cfcomponent>

index.cfm
=======

<cfoutput>I am going to say boo: #sayBoo()#</cfoutput>

Running index.cfm gives error: "Variable SAYBOO is undefined."

I've seen some suggestions on Ben Nadel's blog on how to achieve this behaviour: http://www.bennadel.com/blog/1776-Creating-Globally-Accessible-User-Defined-Functions-In-ColdFusion-Safer-Version-.htm

But I can't see any of these approaches being used in org.corfield.framework.cfc. 

I'm probably missing something that's staring me in the face though.  Care to share your magic, Sean? ;-)

Andrew.

Sean Corfield

unread,
May 7, 2012, 10:55:48 PM5/7/12
to framew...@googlegroups.com
On Mon, May 7, 2012 at 7:03 PM, Andrew <am2...@gmail.com> wrote:
> One of the awesome things about FW/1 is how you can call functions like
> buildURL() from anywhere in your app.
>
> How's it work though?  I can't seem to replicate this behaviour.

Views and layouts are rendered in the context of the CFC that contains
the methods - so the methods appear global.
--
Sean A Corfield -- (904) 302-SEAN
An Architect's View -- http://corfield.org/
World Singles, LLC. -- http://worldsingles.com/

"Perfection is the enemy of the good."
-- Gustave Flaubert, French realist novelist (1821-1880)

Andrew Myers

unread,
May 7, 2012, 11:27:48 PM5/7/12
to framew...@googlegroups.com
Ah ha. This is because they're cfinclude'd, yes?
> --
> FW/1 on RIAForge: http://fw1.riaforge.org/
>
> FW/1 on github: http://github.com/seancorfield/fw1
>
> FW/1 on Google Groups: http://groups.google.com/group/framework-one

Sean Corfield

unread,
May 7, 2012, 11:32:20 PM5/7/12
to framew...@googlegroups.com
On Mon, May 7, 2012 at 8:27 PM, Andrew Myers <am2...@gmail.com> wrote:
> Ah ha.  This is because they're cfinclude'd, yes?

Yup. But the important thing is that the CFC they're included into is
created afresh on every request - otherwise it wouldn't be thread
safe.

Andrew Myers

unread,
May 7, 2012, 11:47:50 PM5/7/12
to framew...@googlegroups.com
Thanks Sean.

Rgds,
Andrew.

Dave Merrill

unread,
May 8, 2012, 8:53:25 PM5/8/12
to framew...@googlegroups.com
Personally, I worried about this a lot more before I wholeheartedly adopted dependency injection. 

Whatever mechanism you use to do it (DI1, ColdSpring, LightWire, homebrew), if something injects required components into the places they're needed, it's not so bad to refer to main.buildURL, db.insertUpdate, datasource.getDbType, and so on. Having these kinds of methods scoped into different utility packages actually feels clean and focused to me, and isn't verbose enough to bum me out.

Injecting common utility cfcs into your controller or model base class (if you have one) works well too. Those db and datasource routines probably aren't needed anywhere but in your model components, for example, and they probably are needed by most of them. There are some completely generic functions that are essentially bits of the language they forgot (structMake, arrayMake...) that you may want really everywhere, and those could either go directly in your base base component (if you have one), or in a util cfc that gets injected into it, or into the most common location you have.

I know you're asking the FW1-specific version of this question, which as Sean points out, has a more specific answer. Frankly, I like and use FW1, and I'm nowhere near as smart or experienced as Sean, but that bit of its architecture has always made me kind of uncomfortable. Not that you asked...

Anyway, that's another way to look at it.

Dave Merrill

Nathan Dintenfass

unread,
May 8, 2012, 9:00:47 PM5/8/12
to framew...@googlegroups.com
I think of it as Application.cfc and all views/layouts operating in an
implicit namespace, where you then have that namespace explicitly
available (and separated) in your controllers (since the framework's
"scope" is passed in the init of your controllers).

I think one of the nice things about FW/1 is it alleviates all worries
about where in a file hierarchy you might be and disambiguates what is
and is not in a given context.

If you have global code that you want in your model use DI to get it
there cleanly, but it's nice that everything within the FW/1 context
itself has a shared scope (unless you want it not to be by doing things
like using the pseudo "local" of views, for instance). That feels more
idiomatic to ColdFusion and allows great flexibility without allowing
total spaghetti (assuming you're keeping your controllers lean).
> this.name <http://this.name> = hash( getCurrentTemplatePath() );
> </cfscript>
> </cfcomponent>
>
> index.cfm
> =======
>
> <cfoutput>I am going to say boo: #sayBoo()#</cfoutput>
>
> Running index.cfm gives error: "Variable SAYBOO is undefined."
>
> I've seen some suggestions on Ben Nadel's blog on how to achieve
> this behaviour:
> http://www.bennadel.com/blog/1776-Creating-Globally-Accessible-User-Defined-Functions-In-ColdFusion-Safer-Version-.htm
> <http://www.bennadel.com/blog/1776-Creating-Globally-Accessible-User-Defined-Functions-In-ColdFusion-Safer-Version-.htm>
>
> But I can't see any of these approaches being used in
> org.corfield.framework.cfc.
>
> I'm probably missing something that's staring me in the face though.
> Care to share your magic, Sean? ;-)
>
> Andrew.
>
Reply all
Reply to author
Forward
0 new messages