Perusion

Interchange Tips from Mike Heins and Perusion

Hello. As many of you know, Mike Heins is a walking wealth of knowledge when it comes to Interchange, Perl, and database access and control. I have decided to try and assemble tips that may be helpful to our clients on this and upcoming pages. At some point I will index and organize them. But first I will assemble them as they become available to me. Some will simply be quick references to functions or things that are little known about Interchange, and may be difficult if not impossible to find in the Documentation. So without further ado....



Date Tip Added Master Category Title Description
20050107 Tags Display meta label for column Ever need to display the meta label for a column in your interchange page?  Use the display tag, heres how:

[display table=table column=column key=key label=1 type=display]
20060109 Database Database Reserved Words Reserved words - Postgres, as well as many other SQL databases have many "reserved words", which are never allowed as identifiers. In other words you cannot use them for column names! In addition, another little known fact about Interchange is that "ID" is a type of "interchange reserved word" and also cannot be used to name a column. Interchange will generally not display a very informative error message when you try to create a new table and use a reserved word for a column name, and often error out with the error :"table <yourtablename> failed: list_fields execute on <yourtablename>. So be familiar with the reserved names, you can find a list here
http://www.postgresql.org/docs/7.2/interactive/sql-keywords-appendix.html (one that will not work with mysql is "group")
20050107 Catalog Configuration Multiple Error Log Locations Did you know that you can customize which errors from Interchange land in the error log, and even direct specific errors to specific locations? Suppose you are getting multiple "Attempt to order missing product code:" errors, and you want to redirect them from the error.log to a file "<catroot>/logs/missing_product.log" so that you can

a. Make the error log more efficient and readable
b. Isolate the missing product information for further and easier review.

Just add this to the catalog.cfg:

ErrorDestination "Attempt to order missing product code: %s" logs/missing_product.log

20060325 Tags Usertag creation tips This is an excerpt from an email Kevin Walsh sent to the userlist on March 25, 2006. It is an excellent description of how usertags can be created properly. Appended to the end of the message is a comment added by Mike in the same thread.

If you have a UserTag like this:

UserTag foobar Order foo bar baz

then you have three named arguments, which you can use like this:

[foobar foo="aaa" bar="bbb" baz="ccc"]

You can put the args in any order you like. The tag code will receive
them in the order you specified in the UserTag "Order" config.

In your UserTag code, you can collect the args like this:

my ($foo,$bar,$baz) = @_;

The variable names are irrelevant, but it's useful to name them after
the Order values.

If you make your UserTag into a container, like this:

UserTag foobar HasEndTag 1
UserTag foobar Order foo bar baz

then you can use your tag like this:

[foobar foo="aaa" bar="bbb" baz="ccc"] Tag body [/foobar]

Now you have an extra argument, which you collect like this:

my ($foo,$bar,$baz,$body) = @_;

If you want your tag body to be interpolated by default (no need
to specify interpolate=1) then you define it like this:

UserTag foobar HasEndTag 1
UserTag foobar Interpolate 1
UserTag foobar Order foo bar baz

You can also create "on the fly" tag arguments, like this:

UserTag foobar HasEndTag 1
UserTag foobar Interpolate 1
UserTag foobar AddAttr 1
UserTag foobar Order foo bar baz

Your collection for the above should look like this:

my ($foo,$bar,$baz,$body,$opt) = @_; ## See Mikes note below.

With AddAttr, you can pass an argument that's not in your "Order"
list and see it in your tag code, for instance:

[foobar foo="aaa" kevin="bbb"] Tag body [/foobar]

In the above case, $foo will be "aaa", $bar and $baz will be undef.
$body will be " Tag body " and $opt->{kevin} will be "bbb". Note that
$opt is a hashref.
Kevins reply was prompted by a question, and Mikes followup  addendum answered a few more questions:

[foobar foo="aaa" bar="bbb" baz="ccc"] Tag body [/foobar]
> my ($foo,$bar,$baz,$body,$opt) = @_;
>

Slight problem with that -- it is actually:

my($foo, $bar, $baz, $opt, $body) = @_;

(Whitespace doesn't cost money.)

> Is the variable $body specific  ?

No -- Perl applies in this case. The arguments are passed to
the subroutine.

> In other words could $Body or $MyStuff be used in place $body ?

Yes, whatever you happen to name it.

> 
> Is it because of adding 'HasEndTag 1' to the UserTag definition
> that you can grab the 'Tag Body' information ?

Yes.

And a bit more from Kevin:

The "Order" defines two things:

1. The order in which positional parameters are expected:

2. The order in which the given parameters will be passed to
your code.

If I use the following example:

UserTag foobar Order foo bar baz

then the following tag calls are equivalent:

[foobar aaa bbb ccc]

[foobar baz="ccc" foo="aaa" bar="bbb"]

If the parameters are collected using the following code:

my ($one,$two,$three) = @_;

then above examples will will cause the following values to be set:

$one will be set to "aaa"
$two will be set to "bbb"
$three will be set to "ccc"

Of course, it's nicer to name the variables after the Order values,
like this:

my ($foo,$bar,$baz) = @_;
20090306 General Why does MSIE cache my pages?
FAQ: Why does MSIE cache my pages?

If the user has the settings in Internet options set to "Never", "Once
per session", or "Automatically", which is typical, then this might be
a problem. If you have the scratch value mv_no_count set (the default
in our demos, see catalog.cfg), then the URL will appear as a simple
.html page.

This is good in the general case, as caching can reduce load on your
system. If you want to have constantly changing dynamic content, however,
then it might be a problem.

You can get caching effects on any browser, if they have an analogous
function. Netscape/Mozilla does -- see the "Edit Preferences" under
Advanced->Cache. It is not quite as aggressive in its caching behavior,
however, and problems are fewer.

The way to defeat it for all browsers is to remove this line from
catalog.cfg:

ScratchDefault mv_no_count 1

This causes a unique integer to be appended to all URLs except
form POSTs. It defeats caching when that is at all possible.

A good way to do this is to only turn off caching for logged-in
users. If they don't have an account on your system, you may not
have much dynamic to show them. To do this, place

[set mv_no_count][/set]

on the destination page for logged in users.

If you prefer to keep the unique integer out of the URL, and you
trust proxy servers to honor the parameter (hah!), you can do:

Autoload <<EOA
[if session browser =~ /MSIE/]
[tag op=header]Pragma: no-cache[/tag]
[/if]
EOA

or even

Autoload <<EOA
[if session browser =~ /MSIE/]
$Variable->{NO_CACHE} = '<META HTTP-EQUIV="Pragma" content="no-cache">';
[/if]
EOA

with __NO_CACHE__ in the header for pages you don't want cached.

This may not work well for AOL, as their proxy servers are extremely
aggressive when there are no QUERY_STRING parameters.

On a busy system this method can place a bit of additional load on the
system and is not real desirable. For best performance you should define a
GlobalSub and just pass the routine name:

interchange.cfg:

GlobalSub <<EOS
sub standard_autoload {
if ($Session->{browser} =~ /MSIE/) {
$Tag->tag( { op => 'header', body => 'Pragma: no-cache' } );
}
}
EOS

catalog.cfg:

Autoload standard_autoload

TIP: It performs better because it is precompiled and is a simple
subroutine call -- very fast. It is the way to do very complicated
processing for every user without incurring lots of tag parse
overhead on every access. A few little tags in Autoload won't
kill you, but I wouldn't want to do a lot on a busy system.