TQL Custom Tags in SVN

0 views
Skip to first unread message

Mark Mandel

unread,
Jul 15, 2008, 9:51:53 PM7/15/08
to transf...@googlegroups.com
Elliot Sprehn has been kind enough to donate his TQL custom tags for
the Transfer project. Big thanks to Elliot!

This should ease some of the verbosity that is required when working with TQL.

Elliot provided be with several examples of their usage:

---

<!--- This would be /transfer/tags --->
<cfimport taglib="tags" prefix="t">

<!--- Do list operations --->
<cfset transfer = getTransfer()>

<t:query name="result" transfer="#transfer#">
select
u.firstName, u.lastName
from
user.User as u
where
u.email like <t:queryparam value="%foo.com" type="string">
</t:query>

<cfset application.transfer.myDatasource = getTransfer()>

<!--- By default datasources are stored in application scope --->
<t:query name="result" datasource="myDatasource">
select
u.firstName, u.lastName
from
user.User as u
where
u.email like <t:queryparam value="%foo.com" type="string">
</t:query>

<cfset request.transfer.myDatasource = getTransfer()>

<t:query name="result" datasource="myDatasource" scope="request">
select
u.firstName, u.lastName
from
user.User as u
where
u.email like <t:queryparam value="%foo.com" type="string">
</t:query>

<!--- Do read operations --->

<!--- Get a single record as a TransferObject --->
<t:query name="user" action="read" class="user.User" transfer="#getTransfer()#">
select
u.firstName, u.lastName
from
user.User as u
where
u.email like <t:queryparam value="%foo.com" type="string">
</t:query>

---

I think the examples pretty much speak for themselves, and the code
behind the tags is quite easy to understand, but let me know if there
are any questions.

Currently there is a limitation of the 'datasource' attribute only
being searched under application.transfer, or request.transfer, but
Elliot is working on allowing to be more flexible.

Side note: what do people think of the attribute 'datasource'? On one
hand, it makes it like <cfquery>, on the other, it makes it seem like
it should have the datasource bean. I was thinking 'scope' and 'key',
rather than 'scope' and 'datasource', but that has its con's as well.

What do you guys think?

Mark

--
E: mark....@gmail.com
W: www.compoundtheory.com

Bob Silverberg

unread,
Jul 15, 2008, 10:29:42 PM7/15/08
to transf...@googlegroups.com
Those tags sound great, Mark. I had taken a peek at them in the
repository - glad to hear they're ready for prime time. I'll admit I
was a bit confused about where the tag searches for Transfer, and by
the use of the term datasource.

Currently it looks in application.transfer.xxx, which suggests there's
a struct called application.transfer, in which you store the "real"
Transfer as a key. That's a bit confusing to me. Why not just store
Transfer in application.transfer? What else, in addition to Transfer,
would you store in the application.transfer struct?

I'll definitely play with these tags and see if I can make any
suggestions about what would seem clearer to me.

Cheers,
Bob

--
Bob Silverberg
www.silverwareconsulting.com

Elliott Sprehn

unread,
Jul 15, 2008, 11:06:30 PM7/15/08
to transfer-dev
On Jul 15, 10:29 pm, "Bob Silverberg" <bob.silverb...@gmail.com>
wrote:
> Those tags sound great, Mark.  I had taken a peek at them in the
> repository - glad to hear they're ready for prime time.  I'll admit I
> was a bit confused about where the tag searches for Transfer, and by
> the use of the term datasource.
>

Can you think of anything better? I thought maybe key="", but that
seems really weird/odd to read when scope="" is implicit? What about
overloading the transfer="" attribute to allow either a string or an
instance of Transfer ?

> Currently it looks in application.transfer.xxx, which suggests there's
> a struct called application.transfer, in which you store the "real"
> Transfer as a key.  That's a bit confusing to me.  Why not just store
> Transfer in application.transfer?  What else, in addition to Transfer,
> would you store in the application.transfer struct?

Some applications have more than one transfer instance, like using
more than one CF datasource. So I figured you'd just name your
datasources by appending them by name to the {scope}.transfer struct.

application.transfer.blog = blogDbTransfer;
application.transfer.main = mainTransfer;

Or a real use case (in one application we have) where you have two
databases, one is replicated and read only, but very fast, and the
other is read/write, but quite slow. So you'd have two transfer
instances in the app that share a cache.

Going to drop the requirement that they be clustered in a struct named
transfer though, so like you said, you could have just one transfer
stored in application.transfer. That probably agrees more with how
people write code now.

Thanks for the feedback Bob!

- Elliott

Bob Silverberg

unread,
Jul 15, 2008, 11:15:24 PM7/15/08
to transf...@googlegroups.com
On Tue, Jul 15, 2008 at 11:06 PM, Elliott Sprehn <esp...@gmail.com> wrote:
>
> Can you think of anything better? I thought maybe key="", but that
> seems really weird/odd to read when scope="" is implicit? What about
> overloading the transfer="" attribute to allow either a string or an
> instance of Transfer ?

Hmm, the overloading idea sounds interesting, but I can see that
ending up being even more confusing. In terms of a name for the
attribute, something like where="", or search="" sounds more
descriptive to me.

> Some applications have more than one transfer instance, like using
> more than one CF datasource. So I figured you'd just name your
> datasources by appending them by name to the {scope}.transfer struct.

Oh yeah. That all makes sense. I never have more than one instance,
so I didn't think of that.

> Going to drop the requirement that they be clustered in a struct named
> transfer though, so like you said, you could have just one transfer
> stored in application.transfer. That probably agrees more with how
> people write code now.

That would certainly make it more straightforward to me.

> Thanks for the feedback Bob!
>
> - Elliott

No problem. Thanks for the tags!

--
Bob Silverberg
www.silverwareconsulting.com

Mark Mandel

unread,
Jul 15, 2008, 11:23:44 PM7/15/08
to transf...@googlegroups.com
I'm leaning towards:

scope="application" key="foo.bar"

The only thing is, if the scope is implicitly 'application', you could
just end up with:

key="foo.bar"

And no real knowledge of knowledge of where it is looking.

It 'feels' like a better fit to me, but I can see issues with it too.

What do people think?

Mark

--
E: mark....@gmail.com
W: www.compoundtheory.com

Sean Corfield

unread,
Jul 16, 2008, 2:11:30 AM7/16/08
to transf...@googlegroups.com
On Tue, Jul 15, 2008 at 6:51 PM, Mark Mandel <mark....@gmail.com> wrote:
> Currently there is a limitation of the 'datasource' attribute only
> being searched under application.transfer, or request.transfer, but
> Elliot is working on allowing to be more flexible.

What exactly is the datasource attribute? Why is it looking in
application.transfer or request.transfer? That makes no sense for the
use cases I'm familiar with. I typically inject the Transfer
Datasource object directly into my data gateway objects if they need
to use SQL and then in my <cfquery> tag I use datasource.getName() /
getUserName() / getPassword() - but I don't see how that relates to
TQL at all. What Transfer variable is being used here? Re-reading the
example, it looks like it is using the Transfer object itself - that
has nothing to do with a datasource. Again, that would be something I
would inject.

If it is just the Transfer object, why not just use
transfer="#whatever#" instead of trying to do some sort of scope
lookup? I would have expected variables.transfer to be the most common
location anyway (certainly for folks who use ColdSpring with
Transfer).
--
Sean A Corfield -- (904) 302-SEAN
An Architect's View -- http://corfield.org/

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

Mark Mandel

unread,
Jul 16, 2008, 2:18:40 AM7/16/08
to transf...@googlegroups.com
Sean, you can see from the first example, that sort of scenario is covered:

<!--- Do list operations --->
<cfset transfer = getTransfer()>

<t:query name="result" transfer="#transfer#">
select
u.firstName, u.lastName
from
user.User as u
where
u.email like <t:queryparam value="%foo.com" type="string">
</t:query>

Maybe there should be no 'datasource' attribute, and simply must pass
in Transfer?

Mark

--
E: mark....@gmail.com
W: www.compoundtheory.com

Elliott Sprehn

unread,
Jul 16, 2008, 2:46:21 AM7/16/08
to transfer-dev
Thanks for the feedback Sean.

My intent was to make transfer as transparent as possible for the
general case of arbitrary code, not just applications that use a DI
engine, service layers, models etc.

My hope was to be able to push Transfer at the crowd of people who
aren't doing applications that use frameworks, DI, and lots of other
OO things. These people are using <cfquery> though, and if we can push
adoption of ORM systems, I think this is a really nice gateway (as in
drug, not as in pattern :P) to dealing with objects.

In discussions with Mark there was talk of expanding TQL to deal with
things like delete, insert, etc. too, so that'd make Transfer even
more transparent to new developers, and probably attract even more
adoption.

One of my hopes was also that when CF9 is released, that Transfer
wouldn't lose out on a chance to enter new segments of users.

You know: "Hey look, Transfer is just as easy to use as <cfquery> with
Hibernate support! Why not try it?".

Those were my hopes anyway.

- Elliott

On Jul 16, 2:11 am, "Sean Corfield" <seancorfi...@gmail.com> wrote:
> On Tue, Jul 15, 2008 at 6:51 PM, Mark Mandel <mark.man...@gmail.com> wrote:
> > Currently there is a limitation of the 'datasource' attribute only
> > being searched under application.transfer, or request.transfer, but
> > Elliot is working on allowing to be more flexible.
>
> What exactly is the datasource attribute? Why is it looking in
> application.transfer or request.transfer? That makes no sense for the
> use cases I'm familiar with. I typically inject the Transfer
> Datasource object directly into my data gateway objects if they need
> to use SQL and then in my <cfquery> tag I use datasource.getName() /
> getUserName() / getPassword() - but I don't see how that relates to
> TQL at all. What Transfer variable is being used here? Re-reading the
> example, it looks like it is using the Transfer object itself - that
> has nothing to do with a datasource. Again, that would be something I
> would inject.
>
> If it is just the Transfer object, why not just use
> transfer="#whatever#" instead of trying to do some sort of scope
> lookup? I would have expected variables.transfer to be the most common
> location anyway (certainly for folks who use ColdSpring with
> Transfer).
> --
> Sean A Corfield -- (904) 302-SEAN
> An Architect's View --http://corfield.org/

Elliott Sprehn

unread,
Jul 16, 2008, 3:11:06 AM7/16/08
to transfer-dev
The other option pointed out by Mark was to drop scope lookup entirely
and suggest:

<t:query transfer="#application.transfer#">

which makes tons of sense. Maybe I'm making this harder than it needs
to be.

I was trying really hard to make it as much like cfquery as possible
to hook new developers in that other segment, but then again, I don't
really know what would be the most transparent for them, and I guess
scope lookup is kind of complicated...

I doubt this list is really the users who I'm trying to target...

Definitely seems like we should ask someone not doing any of this OO
stuff already what they'd think is best rather than guessing. I don't
feel comfortable assuming.

I really want to try and foster some kind of community around transfer
that lets new developers take baby steps into OO. I think the
potential exists here because of the ubiquity of cfquery. If we sugar
coat it, I think transfer could be the keystone.

- Elliott

Bob Silverberg

unread,
Jul 16, 2008, 10:56:17 AM7/16/08
to transf...@googlegroups.com
Oh, now I understand what you're trying to do. Honestly, I didn't
even know why you were doing that scope thing. I thought it was just
a shortcut so we didn't have to specify the location of Transfer every
time we created a query. Now I see that there was a whole other
reason for doing it.

Regarding providing a shortcut, I made a mod to my copy of the tag
which does allow me to exclude transfer from the list of attributes.
It relies on a certain convention, which means it's not very flexible,
but I offer it as an example. I changed the "looking for Transfer"
code to this:

<cfif not isObject(attributes.transfer)>

<cfif StructKeyExists(caller.this,"getTransfer")>
<cfset attributes.transfer = caller.this.getTransfer() />
<cfelse>

<cfparam name="attributes.datasource" type="string">
<cfparam name="attributes.scope" type="string" default="application">

<cfset scope = structGet(attributes.scope & ".transfer")>
<cfif not structKeyExists(scope, attributes.datasource)>
<cfthrow
type="transfer.query.DatasourceMissing"
message="No Transfer found at
#attributes.scope#.transfer[#attributes.datasource#]"
>
</cfif>
<cfset attributes.transfer = scope[attributes.datasource]>
</cfif>

</cfif>

I will pretty much always be writing TQL code in a gateway, and I
inject Transfer into my Gateway via CS, so I know that Transfer will
always be available via getTransfer() in the caller. By adding that
line of code I don't have to specify anything about Transfer at all in
my <t:query> tag. This will also work if I want to write TQL in a
decorator, or even, gasp, a service. Obviously this will only work if
you have a getTransfer() method defined in the caller, which I know
not everyone does (many people just use variables.transfer directly).
Because this won't help everyone, it may not be a logical addition to
the shipping version of the tag, but I wanted to point out that it is
helpful to me.

Getting back to the question of how to make this easiest for folks not
familiar with Transfer, I totally agree with just doing away with
scope, and having the user pass in the Transfer object all the time.
Like in your example:

<t:query transfer="#application.transfer#">

In my opinion this actually mimics what many people who don't use
Transfer are already doing. They probably have something like:

<cfquery name="qryTemp" datasource="#application.DSN#">

or

<cfquery name="qryTemp" datasource="#request.DSN#">

So changing that to:

<t:query name="qryTemp" transfer="#application.transfer#">

Is about as similar as you can get.

Cheers,
Bob

--
Bob Silverberg
www.silverwareconsulting.com

Elliott Sprehn

unread,
Jul 16, 2008, 8:01:13 PM7/16/08
to transfer-dev
On Jul 16, 10:56 am, "Bob Silverberg" <bob.silverb...@gmail.com>
wrote:
>
> Regarding providing a shortcut, I made a mod to my copy of the tag
> which does allow me to exclude transfer from the list of attributes.
> It relies on a certain convention, which means it's not very flexible,
> but I offer it as an example.  I changed the "looking for Transfer"
> code to this:

Nice, that's a neat trick. Not sure I want to throw that much magic
into the tag by default, but as a mod it's pretty slick.

> <t:query transfer="#application.transfer#">
>
> In my opinion this actually mimics what many people who don't use
> Transfer are already doing.  They probably have something like:
>
> <cfquery name="qryTemp" datasource="#application.DSN#">

That's a really great point! I'm in favor of dropping this feature
entirely then and pushing that approach for adoption.

Thanks,
- Elliott

Beau

unread,
Jul 17, 2008, 7:37:54 PM7/17/08
to transfer-dev
Hi Everyone,

I haven't even started using transfer yet (properly)
So can give you the complete newbie to transfer perspective.

I ALWAYS use <cfquery name="qry_myQueryName"
datasource="#application.datasource#"

for all queries.
So your suggestions of dropping scope entirely and leaving it up to
the user - sits really comfortable with me.

Beau.

Mark Mandel

unread,
Jul 17, 2008, 7:39:26 PM7/17/08
to transf...@googlegroups.com
Elliot's sent me the new tags with the 'datasource' attribute taken out.

I'll commit them shortly.

Mark

--
E: mark....@gmail.com
W: www.compoundtheory.com

Reply all
Reply to author
Forward
0 new messages