A macro is an ERB expression in your page object or template. ERB is called to process the page after the page object has been poured into the template (unless you specify that the
:processmacros scalar directive is
false, which would be a very unusual thing to do).
If you don’t know about ERB, you should study it in order to understand the syntax. Basically, a typical macro expression in a page object looks like this:
<%= imageref("myimage") %>
The thing to notice there is the equal-sign. That means that the result of evaluating the contents of the expression will be substituted for the expression. If the equal-sign were not there, the contents of the expression would be evaluated, with any side effects, but there would be no substitution; the expression is simply deleted from the output.
Macros are evaluated under a special set of evaluation rules called macro scoping. (Also, outline renderers are run under macro scoping.) You will want to understand macro scoping in order to write your own macros (plus tools, plus outline renderers, etc.).
In Frontier, when a macro runs, certain abbreviated modes of expression are enabled. This is mostly just a way of making things easier on the programmer writing the macro. For compatibility, RubyFrontier provides a similar mechanism. Linguistically, underneath the hood, the implementation is performed very differently: Frontier uses the dreaded
with, whereas RubyFrontier, being Ruby, uses bindings,
method_missing, introspection, and a lot of other cool stuff. But you don’t need to worry about that. You just need to know the rules for these abbreviated modes of expression. So here they are.
The page table is in scope, under the name
Class methods of
UserLand::Html are in scope, as methods of the name
So, for example, to call
UserLand::Html::everyPageOfSite(), you can just say
adr is the required parameter).
Instance methods of the
UserLand::Html::PageMaker object that is rendering the page are in scope, also as methods of the name
So, for example, to call
UserLand::Html::PageMaker#getTitleAndPaths, you can just say
id is the required first parameter; this is the PageMaker object that is rendering the current page, so the page table is automatically supplied as the second parameter).
Macro scripts (scripts in the
#tools folder) are in scope, under the names of any top-level methods they may contain. So, for example, if a
#tools folder contains a script (
.rb) file that defines a top-level method
homelink, you can call it by saying
homelink(). How many parameters such a top-level method takes and what they mean is entirely up to you. Remember, the macro script itself is running under macro scoping, so it has access to the page table, other tools, and everything else listed here.
[Warning: Be careful to keep macro script top-level method names unique. The reason is that all macro scripts are loaded via
instance_eval into a single object (a
BindingMaker instance), so same-named top-level method names can trample one another.]
Standard macros (instance methods of the
UserLand::Html::StandardMacros module) are in scope, under their unqualified method names.
So, for example, a macro can say
bodytag() and the method
UserLand::Html::StandardMacros#bodytag will be called. Furthermore, the
StandardMacros module is
included in the
PageMaker instance that is rendering the page, so a standard macro has access to the page table and can directly call
PageMaker instance methods.
Finally, as a last-ditch effort, keys in the page table hash are themselves in scope, both as symbols and as strings.
For example, if you say
title, and there is no local variable or known method
title, then (if we call the page table
pt[:title] will be sought, and if that isn’t found,
pt["title"] will be sought.
However, unlike Frontier, this works only for getting; you cannot set a key in the page table hash in this way. The reason is that the
with mechanism that permitted this in Frontier was dangerous; it was all too easy to set a value in the page table (or elsewhere in the “database”) accidentally. This limitation is no inconvenience, however, because if you want to set a key in the page table hash, you can do so easily through your access to the page table as
Note that you can add your own methods to the repertory of things that can be accessed via macro scoping, by defining them in a
user.rb file. For example,
user.rb could define a standard macro as an instance method of
UserLand::Html::StandardMacros, and a macro could then call it directly by name. Or,
user.rb could define a
PageMaker method as an instance method of
UserLand::Html::PageMaker, and a macro could then call it as a method of
This documentation prepared
by Matt Neuburg, phd = matt at tidbits dot com
Download RubyFrontier from GitHub.