Forum OpenACS Development: Better support for the <tcl> tag in templating

The recent thread discussion on the addition of the switch tag reminded me of a frequent annoyance of using the <tcl> tag inside a <multiple> tag. The problem I run into has to do with the changing name of the array holding the variables and the use of an array var to name the row number currently being processed.

Here is some example tcl code I am forced to use:

<tcl>
set array_row shipments:$shipments(rownum);
set tracking_number [set ${array_row}(tracking_number)];
set track_url [subst [set ${array_row}(tracking_url)]];
</tcl>

Would it be useful if multiple had an additional attribute that specified a constant named array to copy the row into? Should the multiple_name(rownum) variable be replace with something like multiple_name:rownum in a fashion similar to multiple_name:rowcount?

Collapse
Posted by Jeff Davis on
Why are you putting tcl in the adp in the first place? I think it would be a mistake to add overhead to the multiple tag to facilitate what I think is generally a bad practice (mixing code and markup). Are you sure you would not be better off with the code in the .tcl file to begin with?

In this specific case I guess you are trying to interpolate a url var with another var but wouldn't this be clearer:

 
db_foreach get_shipping_url {select tracking_url,tracking_number ... } { 
    set tracking_url [subst $tracking_url]
}
or something similiar...
Collapse
Posted by Tom Jackson on

Does db_multirow have the ability to execute code for each row? That would be the best place to do this. If I use db_foreach, I have to build the arrays by hand. My query is something like:

select
 s.shipment_id,
 s.tracking_number,
 ... (other fields),
 sm.tracking_url
from
 ms_shipments s,
 ms_shipping_methods sm
...

The main cause of the problem is requiring the use of an array variable to access the current array name. Having a tcl code block in db_multirow would also solve the problem. I agree 100% using tcl in the adp template is very bad.

Collapse
Posted by Roberto Mello on
db_multirow does allow a code block. I think that feature was undocummented until I revamped the db api docs for 4.6 (several months ago). It also allows for an -if_no_rows code block.

https://openacs.org/api-doc/proc-view?proc=db%5fmultirow

-Roberto

Collapse
Posted by Tom Jackson on

So it looks like db_multirow does support the tcl code block, which solves my problem. I guess I should read the current docs before spewing nonsense. I still wonder why the current rownum is an array var.

Collapse
Posted by Don Baccus on
Remember to use -extend to make the variables you set visible to the template ...
db_multirow -extend foo_plus_bar stuff get_stuff {select foo, bar from fubar} {
    set foo_plus_bar [expr {$foo+$bar}]
    set invisible ""
}
In this example "foo_plus_bar" will be placed into the array made visible to your template, while "invisible" will not.

I think it was Lars that added this to db_multirow ...

As to why rownum's part of the array ... why not? :)

Collapse
Posted by Tom Jackson on

Don,

Well thanks a million to Lars then, I started developing with ACS at version 4.1 and I don't know if it was working this way, or just undocumented, but this is the natural solution to my specific problem. I just carried over old developing habits to a new project without updating my knowledge of the API.

The reason I ask about the rownum array element is that multirow_name:rowcount isn't an array element, and when I thought I had to use tcl on the template page, the array var for the rownum lead to needing extra code to get what I wanted. Doesn't seem to matter too much any more.