[coldbox3.7.0-BE] Passing rc as function attributes

I don’t understand how to pass rc as an argument of a function.

Let me explain with a example:

`


`

Here in the caller function, b will not be defined.

So how can I use ‘rc.b’ in the caller function? Do I need to return it in the called function?

Or do I need to write
<cfset var rc =Event.getCollection()>

and use rc like that? (Even if it is the old way).

Thank you

Regards

try arguments instead

If called() is contained in a model rather than in the controller, you'll
have to use the method you showed. If it is a handler, you can do something
like the below code. Note that I defined rc as a struct and made called() a
private function since it looks like you don't want anyone to call it
directly.

<cffunction name="caller">
    <cfargument name="Event" type="any">
    <cfargument name="rc" type="struct"><!---rc is a struct; prc is also
struct--->

    <cfset rc.a = 'a'>
    <cfset runEvent("called")><!---Use setNextEvent() if you want to
redirect there (execution would never return to your cfdump, though.--->

    <cfdump var = "#rc.b#">
</cffunction>

<cffunction name="called" name="private"><!---Private keeps anyone from
calling it directly. They must go through caller().--->
    <cfargument name="rc" type="struct">

    <cfset rc.b = 'b'>
</cffunction>

I'm pretty sure that if you call a function directly and pass an argument
directly, it will exist. Structs are passed by reference in coldfusion, so
it would work, but might not be what you want in most cases. In fact, if
you want something that looks less like coldbox and more like straight
coldfusion, you probably want/should consider putting it into a model
object of some kind.

Are you sure rc.b exists? In your example you set “a” but tried to access “b”. Put in a structkeyExists(), or param the value.

Do you mind explaining what you are trying to accomplish? Passing the rc struct (request collection) is valid CFML but there are often organizational reasons not to do it (in favor of other approaches).

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

Brad is correct. I was reading i_call_a_function() as meaning that you
called "called()".

You *can* pass rc just as you would pass any other value to a function.
Since it is a struct, you can set values. If you never set a key in it,
though, the key and value will not exist. Like Brad said, though, you may
want to use another approach instead of calling a function directly.

You are right! Something probably went wrong while testing. What do you mean by try to use another approach?

At my work, we do:

`

... //-------------- //But what about //--------------

//This if I understand correctly is not correct
<cfset a_function(arguments.rc) />

//Use arguments.rc.b here

//a function that use rc and set b

`

Writing each time ‘arguments.rc’ takes time (ahaha). Why I cannot (maybe I can) use ‘rc.a’ directly in the function handler. Is there a way to avoid defining ‘rc’ in argument of every handler functions and having it ‘global’ to the handler component (with injection?)?

Hope it was clearer :slight_smile:

Regards

Hi,

Can you check my last comment please?

Thanks

Regards

> What do you mean by try to use another approach?

Passing the entire rc struct may be desired, but it’s a little sloppy as it doesn’t create a very nice API. Consider, the following two methods:

function createUser( props ) {}

function createUser( firstName, lastName, age ) {}

Which of those two methods is better at documenting what data it requires to execute? (Correct answer: the second!)

//This if I understand correctly is not correct
<cfset a_function(arguments.rc) />

Well, it depends on what you’re doing. If a_function() does something with specific values in the rc, then pass them in by name. If it adds some sort of default, generic rc values, then there might not be anything wrong with that. Look into using some of the nice AOP methods like preHandler() or pre().

> Is there a way to avoid defining ‘rc’ in argument of every handler functions and having it ‘global’ to the handler component (with injection?)?

Well, you don’t want it to be global since handlers are cached and the request collection is specific to a particular page, but the whole rc = Event.getCollection() bit is not required and hasn’t been required since around version 3.1 I think. Every event gets event, rc, prc, and eventArgs passed into it and made available in the arguments scope. You don’t need to do anything for that to happen. You don’t even have to declare those arguments. This is a perfectly valid action in a handler:

function index() {
rc.foo = ‘bar’;
}

rc is being used out of the arguments scope whether or not you declare it.

Thank you very much for your time! You answered all my questions.

Regards

*> What do you mean by try to use another approach?*

Passing the entire rc struct may be desired, but it's a little sloppy as
it doesn't create a very nice API. Consider, the following two methods:

function createUser( props ) {}

function createUser( firstName, lastName, age ) {}

Which of those two methods is better at documenting what data it requires
to execute? (Correct answer: the second!)

As much as I agree with you, the approach he is trying to do is still
feasibly correct as well. There have been times, that if I followed that
approach the arguments would have over 120 arguments. There comes a time
when you have to say, this needs to be better organised.

Now keeping with that, it can still apply for the OP. For example.

function CreateUser(userInfo, userAddresss, userContact) { }​

​Now although maybe not the best example, but what I am saying is that the
user name, password are passed in one struct while their Address and
mailing address is passed in the second struct and all their preferred
contacts are then passed in the 3rd struct.

As I said maybe not the best example, but any time you want to pass a heap
of data, breaking it down to manageable structs is better than having 120
arguments being passed.

For the OP, what Brad is saying is that you want to break it all down and
segregate the data. You have to think of your services and models as tiers
constructed in black box scenarios, that means the models and services only
care about what they only care about. ​And passing the entire RC could be
problematic depending what you have in there for that request.

By the way, when I say Tiers, you should be able to remove that tier and
replace it with now code re-factoring in your handlers.

However, having said all that.

The Request Context is kept in memory for every request anyway, now
although I do not condone this as best practice, there has been a time or
two, where I have injected the Request Context Decorator (sorry if that is
not the right one) to then access the required information from either the
RC or PRC. I usually always use the PRC for my apps and leave the RC for
Coldbox and what it does, that means if I need to use the submitted form
data then I inject the decorator and then grab the required fields.

Now that comes with serious caveats, one of which is validation. You still
should use handlers to block any request that the services and models
should not care about. Validation is the same, it should not enter the
service or model unless it passes all that.

If it was me, I would take a step back and say what it is you're trying to
achieve with your handlers, services and models and code them accordingly,
with the view that these services and models should be factored for total
code reuse.

Regards,
Andrew Scott
WebSite: http://www.andyscott.id.au/
Google+: http://plus.google.com/113032480415921517411