Forum OpenACS Q&A: New template tag: include-optional

Collapse
Posted by Lars Pind on
I've implemented a new template tag, <include-optional>.

The idea is that if you want to wrap a template with a label,
perhaps a table, and some other tags, but only if the included
template has something to say, you wrap the whole thing in an
<include-optional> tag, put an <include-output> tag where you want
the output of the template to appear, and that's exactly how it
works.

For example:

<include-optional src="..." arg="...">
  <tr>
    <td>More stuff:</td>
    <td><include-output></td>
  </tr>
</include-optional>

Don has the patch, and I'm sure he'll include it in the toolkit soon.

Any comments? Suggestions for better names?

Collapse
Posted by Tom Jackson on

I have a new tag that I called read, but maybe source would be a better term. It works similarly to include, but you don't have to pass any variables to the include. One downside to this tag is that if you change the sourced file, the templating system doesn't pick up the change unless you touch the parent template adp. Here is the source which I put in acs-templating/tcl/tag-init.tcl:

template_tag read { params } {
 
   set source [ns_set iget $params src]
   if {![string match "absolute" [file pathtype $source]]} {
      set source [ns_normalizepath [ad_conn adp_root]/$source]
   }
   
   set chunk [template::util::read_file $source]
   template::adp_compile_chunk $chunk
}  

I also had to work around a 'bug' in the master tag, and maybe others that refer to filenames. You cannot specify an absolute file path in the original system. I used [ad_conn adp_root] to specify an absolute path. For the current system this should probably be pageroot?

Collapse
Posted by Don Baccus on
include actually requires you to pass extra args?  If that's true it should be fixed.  I don't really like the idea of having an extra tag just to handle this case ...

As far as path issues in the ATS go ... I assume you want to move them out from under page root so you can easily guarantee they're only executed when they're included by one of your templates?

Collapse
Posted by Tom Jackson on

Actually the template root, as I am calling it, depended on the host (for mydomain.com or dnsix.namesdirect.com and others), and the templates which were different were kept separate, and someplace safe for graphics folks to work. I didn't fix the include tag, because I didn't want to investigate if anything else would break.

Collapse
Posted by Lars Pind on
Include only requires the src attribute, nothing else. I'm not sure what else you're thinking it needs?

As far as the directory goes, you can easily specify an absolute filename. The caveat is simply that it's rooted at [acs_root_dir] (e.g., /web/myserver/), so you'd typically want to say something like /packages/my-package/www/my-include, or /packages/my-package/www/lib/my-include, or even /packages/my-package/inlcude/my-include.

This works just fine, and I actually think it's quite desirable, as you don't want to allow people to source stuff from random places on your server's disk drive.

Collapse
Posted by Tom Jackson on

for { set i 0 } { $i < [ns_set size $params] } { incr i } {

  set key [ns_set key $params $i]
  if { [string equal $key src] } { continue }
    
  set value [ns_set value $params $i]

  append command " $key "$value"";# is $value quoted sufficiently?
}
 

The 'for', sets passed in vars. I believe if the included file uses vars set in the parent template or parent tcl file, you have to pass them in.

Collapse
Posted by Lars Pind on
Tom,

You you *can* pass vars to the included template, but you don't *have* to ... I still don't see the problem with the include tag as it exists.

/Lars

Collapse
Posted by Don Baccus on
I understand what Tom's saying now, his wording wasn't clear.

What he means is that his "read" tag works like a C (or most languages) "include" - the included file is interpreted in the same scope/stackframe rather than in a new stackframe.

Collapse
Posted by Lars Pind on
Ah, I see.

Whereas the existing include tag works like a procedure call.

/Lars

Collapse
Posted by Don Baccus on
Exactly .. which is contradictory to the traditional meaning of "include" ...

But (as you well know!) the ATS makes things more complicated, since ATS proc calls all circumvent the nesting by slamming vars at the "template level".  It's only when you call normal ACS procs that you hit the problem.

One more reason to vote for seamless integration of the ATS with the toolkit.  The need for which better software engineering management could've prevented in the first place.  Sigh ... $38M was needed to implement this problem, and we've got to fix it with $0 ... so it goes!

Collapse
Posted by Tom Jackson on

AOLserver's tcl api includes ns_adp_include. It used to have a switch -sameframe, however this was dropped at some point, thus breaking some of my code. Without the switch, the tcl proc worked pretty much like the ATS include tag. My version works like the proc with the switch. This might be where the naming and the semantics of the tag came from.

The include tag is actually doing something a little different in that the include tag will also source any associated tcl file (I think), whereas, my tag will not.

I used my tag to simplify the adp template, by separating out big chunks into separate files. Here is the link to ns_adp_include: http://aolserver.com/docs/devel/tcl/api/adp.html#ns_adp_include

Collapse
Posted by Don Baccus on
Tom ... yes the include tag executes the associated .tcl file if it exists.  Your tag is interesting ...