I'm working on a system where some code is dynamically generated and
then rendered. The only caveat is that you have write a file to the
disk and call cfinclude on it to get it to execute for ACF / Railo.
OpenBD has a "render()" function to works like evaluate() does but works
on blocks of code (including tags) whereas evaluate() only evals
expressions. I'd like my solution to be cross engine compatible so I'm
going to have to write to disk for ACF / Railo for now. However this
begs the question -- why isn't this feature construct part of the core
CFML language? Before submitting tickets to ACF / Railo it would be
nice to discuss this futher, but it seems like a feature defect to not
have the ability to execute arbitrary blocks of CFML code. Discuss!
Best,
.Peter
http://www.openbluedragon.org/manual/?/cfmlmanipulation
This is something we use a __lot__ when we are building solutions. The
render() function has been in the bluedragon family since pretty much
day one, where as <nocfml> is a recent addition.
I think this was discussed on the CFML Advisory Committee at point and
the thinking was: if you have the ram:// protocol for file operations
(which Railo has had since 2.0 and Adobe introduced in CF9), then the
easiest / fastest way to execute arbitrary code is write to a 'file'
in memory and include it.
It feels a little clunky though; the render() method definitely more
efficient with a lot less layers going on.
But at least there is at one path forward that all the engines support.
> Doesn't cover pulling code from a database though, which is handy in some
> cases. Guess you could pull from the DB and then write to "file" but still a
> bit of a round-about solution.
Hmm, can you give an example of when storing code in a db would be a good idea?
(as opposed to storing the code in a file and the filename in the db)
Also, is there a reason for having a separate render() function,
rather than letting evaluate() handle tags (and script) too?
Hmm, can you give an example of when storing code in a db would be a good idea?
(as opposed to storing the code in a file and the filename in the db)
A lot of CMSs generate the final HTML from templates with content being
dropped in via CMS tags. In ours we read the template via an include and
wrap the whole thing in a <cfsavecontent > to be able to then manipulate
it. It would be much easier to do it all in one go on the fly.
>> Doesn't cover pulling code from a database though, which is handy in some
>> cases. Guess you could pull from the DB and then write to "file" but still a
>> bit of a round-about solution.
> Hmm, can you give an example of when storing code in a db would be a good idea?
> (as opposed to storing the code in a file and the filename in the db)
A reporting engine where the user is generating the query?
--
Yours,
Kym
.pjf
Hmm, can you give an example of when storing code in a db would be a good idea?
(as opposed to storing the code in a file and the filename in the db)
Is there any reason why evaluate() wasn't originally made, or extended, to evaluate any cfml rather than just expressions?
Good to know, thanx Alan. I wasn't sure how quickly OpenBD was
adopting stuff like that. I know you've been very aggressive about
adding the cfscript enhancements. It's great to see such a high level
of compatibility, so quickly!
--
Sean A Corfield -- (904) 302-SEAN
Railo Technologies, Inc. -- http://getrailo.com/
An Architect's View -- http://corfield.org/
"If you're not annoying somebody, you're not really alive."
-- Margaret Atwood
I must admit, when I learned about OpenBD's render() function, I did
wonder why they didn't just enhance evaluate() to allow 'any' CFML as
the argument. From a language design point of view, I would rather
evaluate() accepted ANY CFML and returned the last value - if any - of
the evaluated code. Thoughts?
Regards
MD
> --
> CFML Conventional Wisdom
> http://groups.google.com/group/cfml-conventional-wisdom?hl=en?hl=en
Mark Drew
Railo Technologies UK
Professional Open Source
skype: mark_railo
email: ma...@getrailo.com
gtalk: ma...@getrailo.com
tel: +44 7971 85 22 96
web: http://www.getrailo.com
How does the engine know what to do with:
"X+Y"
With Evaluate it will of course perform it.
but if you are throwing in tags as well then it does not make sense. So say:
"Here is the result of x+y <Cfoutput>#x+y#</cfoutput>"
Its about context. So Evaluate in its raw form does not make sense.
When I first implement render() I played out these scenarios. As Matt says, better to add a new function.
Personnally I would ditch evaluate and go exclusively with render.
--
aw2.0 ltd www.aw20.co.uk
Evaluate() does expressions. Render() does blocks of code. Inheritly,
evaluate() is going to a bit more "secure". Consider expressions that
are derived from user input -- evaluate would choke on anything injected
whereas you have to way more careful when using render(). What if
somebody injects a <cfquery> with drop tables into a string used in
Evaluate()? So just the "restriction" of scope in what evaluate
inherently can do is good thing in my mind.
.pjf
(Render) sends the text "3+4" to the browser
(Render) sends the text "3+4" to the browserHmm, I'm not sure that's my favorite - why have render() automatically output to screen on your behalf, rather than just cfoutputting a moment later if that's what you want? What about if you needed to use it as an intermediate step, rather than the final destination? Or what if you needed to evaluate non display stuff? Or perhaps you needed to use the result of a render() in another render()? Or what if you dynamically generated your model from a config file and now needed to instantiate the objects for use in the system? Seems like all that should be legal.
Just so I'm clear on how render() actually works, can you confirm the following:
<cfset x = 3 />
<cfset y = 4 />
evaluate( 'x+y' ) == 7
evaluate( '#x+y#' ) == 7 <!--- evaluated before calling evaluate() --->
evaluate( '##x+y##' ) == 7 <!--- evaluates #x+y# or is this illegal? --->
render( 'x+y' ) == ? The string "x+y" ?
render( '#x+y#' ) == 7 <!--- because #x+y# is evaluated before the call --->
render( '##x+y##' ) == 7 <!--- ? --->
render( '<cfoutput>##x+y##</cfoutput>' ) == 7
> Personnally I would ditch evaluate and go exclusively with render.
Did you consider extending evaluate() with an optional argument to
indicate code vs expression? Either a boolean or a string.
<cfset aa = render( '##x+y##' )>
then aa will be : "#x+y#". If you do:
<cfset aa = render( '<cfoutput>##x+y##</cfoutput>' )>
then aa will be : "7". Now i say "nearly" because any output is not
sent to the request output stream, but caught, and given back as a
string. If that was a true CFINCLUDE then it would of course make it
back to the browser (or whatever the client was).
So Render() is more controlled. Like i said early, the vast majority
of my CFML apps has render() in it somewhere, its been a very powerful
addition.
Just so I'm clear on how render() actually works, can you confirm the following:
<cfset x = 3 />
<cfset y = 4 />
evaluate( 'x+y' ) == 7
evaluate( '#x+y#' ) == 7 <!--- evaluated before calling evaluate() --->
evaluate( '##x+y##' ) == 7 <!--- evaluates #x+y# or is this illegal? --->
render( 'x+y' ) == ? The string "x+y" ?
render( '#x+y#' ) == 7 <!--- because #x+y# is evaluated before the call --->
render( '##x+y##' ) == 7 <!--- ? --->
render( '<cfoutput>##x+y##</cfoutput>' ) == 7
Did you consider extending evaluate() with an optional argument to
indicate code vs expression? Either a boolean or a string.
We build a lot of tools that are in themselves tools. So we have a system for example that let's users build webservices and we store their code snippets in a db before it gets published to a farm of machines. This is for a large internal app and has a lot of workflow/process associated with it. That's but one example.
Hope that helps.
a
--
aw2.0 ltd www.aw20.co.uk