# ERB in snippets or pages?

**URL:** <https://www.ruby-forum.com/t/erb-in-snippets-or-pages/98435>\
**Category:** Radiant CMS\
**Created:** [July 14, 2006, 7:09pm UTC](https://www.ruby-forum.com/t/erb-in-snippets-or-pages/98435 "2006-07-14T19:09:16Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![pond](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/7ab992/32.png) [@pond](https://www.ruby-forum.com/u/pond)\
**Post date:** [July 14, 2006, 7:09pm UTC](https://www.ruby-forum.com/t/erb-in-snippets-or-pages/98435/1 "2006-07-14T19:09:16Z")

</div>

The short version: Is it possible to use ERB within Radiant snippets or  
pages? (By filters maybe?)

The long version: I’ve a whole bunch of Rails applications within a same  
domain including forum, wiki and so-on. They use a common template,  
implemented by putting together a bunch of common partials, symlinking  
to their physical location, then including those partials within the  
default layout for each application. Repetition is minimised with in  
general only application-specific variations in layouts. Ultimately  
they’ll also share a secondary, common database with a superset of  
authorisation/account details for single sign-on purposes.

Radiant is used for various reasons, for sections of the site that  
aren’t publically editable. I’ve expressed the template partials through  
snippets in Radiant with a default layout. It works well. I’ve extended  
the snippet “new.rhtml” to include a “more/less”-style panel that takes  
a filename; the database and table have an “auto\_export” field validated  
in the model; finally, a custom save method in the snippet controller  
exports the snippet to the given filename if provided whenever that  
snippet is updated.

This lets me export snippets as partials to the shared directory thus  
providing control over the look and feel across multiple Rails  
applications all from within Radiant. Only one problem; no ERB. The  
snippets use it. In certain cases I’ve been able to hack an equivalent  
using cunning but hideous arrangements of comments; application-specific  
partials or snippets are included by commented-out ERB or Radiant tags,  
then depending on whether Radiant or another app is running, one of  
those two tags gets expanded so the snippet or partial gets included.  
The included item closes off the open comment, does its thing, then  
re-opens the comment again. I said it was hideous… Commented out bits  
of ERB or Radiant tag end up in the served documents too, which is nasty  
and it’s an extraordinarily limited approach compared to simply using  
ERB directly.

Any recommendations - is this a job for a filter?

---

<div class="post-metadata">

**Author:** ![pond](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/7ab992/32.png) [@pond](https://www.ruby-forum.com/u/pond)\
**Post date:** [July 14, 2006, 8:01pm UTC](https://www.ruby-forum.com/t/erb-in-snippets-or-pages/98435/2 "2006-07-14T20:01:58Z")

</div>

Andrew H. wrote:

> The short version: Is it possible to use ERB within Radiant snippets or  
> pages? (By filters maybe?)
> 
> …
> 
> Any recommendations - is this a job for a filter?

A filter may not be the best choice here. Filters don’t have any concept  
of where they are being used (the page or snippet). Instead they just  
filter text. You could make an ERB filter work, but it wouldn’t know  
anything about where it was being rendered.

You may need to resort to doing something with a behavior. Behaviors can  
control every aspect of how a page is rendered (look at #process on  
Behavior::Base). You should be able to add a hook in there for  
evaluating ERB within the context of a page.

–  
John L.  
[http://wiseheartdesign.com](http://wiseheartdesign.com)

---

<div class="post-metadata">

**Author:** ![pond](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/7ab992/32.png) [@pond](https://www.ruby-forum.com/u/pond)\
**Post date:** [July 16, 2006, 11:54pm UTC](https://www.ruby-forum.com/t/erb-in-snippets-or-pages/98435/3 "2006-07-16T23:54:33Z")

</div>

John W. Long wrote:

> A filter may not be the best choice here. Filters don’t have any concept  
> of where they are being used (the page or snippet). [Use behaviors]

Well, I’ve written a simple Filter very quickly that doesn’t have any  
ERB context around it. ActionView uses much magic to get instance  
variables into the ERB execution context so that you can use @session et  
al in your .rhtml files. My Filter doesn’t have that, so it’s quite  
limited although you can use self-contained ERB quite happily. The ERB  
parser only works on the bit of text (Snippet, Part) that specifies such  
a Filter should be run, by definition of how Filters are implemented.

I then worked on a Behavior, which has reached its first version that  
really does inject the local variables in using a similar mechanism to  
ActionView. This means I can do a footer snippet, say, which includes  
this (ignoring the line wrapping); angle brackets removed and ‘href’  
changed to ‘refh’ to try and get the RForum list gateway to stop  
saying my message contains spam! Doh!

a refh=“[W3C CSS Validator results for http: (CSS level 3 + SVG)](http://jigsaw.w3.org/css-validator/validator?uri=)\<%=  
url\_encode(@request.protocol + @request.host + @request.request\_uri)  
%\>” …link text…

That’ll produce a valid CSS validation (sic.) URL for any application  
including Radiant. If included in a Part with the ERB Behavior, it gets  
parsed. The Snippet or Part that includes such text must, of course, not  
have any Filters defined which would destructively alter the ERB, so no  
(say) Textile if you wanted ERB via the Behavior. Then again you can’t  
have two Filters anyway; at least with an ERB Behaviour you could  
additionally use a Filter which did not escape or otherwise mangle the  
ERB code.

Now for the catch.

Provided all pages using the snippet (via a layout or directly) use the  
ERB behaviour, all is well. However, what about a Not Found page or an  
archive? That would probably use the same layout as other pages in a  
site, which wants directly or via a Snippet to include ERB. But it  
already has the Not Found Behavior, so it can’t have ERB Behavior too.  
So, suddenly, I’m back at wanting an ERB filter; the fact that you use  
ERB somewhere really is something specific to that block of text,  
whereas a behavior seems to imply application of a concept globally, to  
the whole compiled page.

I’ll look into what instance variables are available for Filter objects  
tomorrow maybe, but for now you can look at the in-progress code here:

[Pond's Place: Ruby software](http://pond.org.uk/ruby/)

---

<div class="post-metadata">

**Author:** ![pond](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/7ab992/32.png) [@pond](https://www.ruby-forum.com/u/pond)\
**Post date:** [July 17, 2006, 6:02pm UTC](https://www.ruby-forum.com/t/erb-in-snippets-or-pages/98435/4 "2006-07-17T18:02:32Z")

</div>

Andrew H. wrote:

> the whole compiled page.  
> You should consider overriding Behavior::Base#render\_page in a plugin.  
> This would be the easiest way to give all pages and snippets global  
> access to ERB.

–  
John

---

<div class="post-metadata">

**Author:** ![pond](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/7ab992/32.png) [@pond](https://www.ruby-forum.com/u/pond)\
**Post date:** [July 19, 2006, 3:05pm UTC](https://www.ruby-forum.com/t/erb-in-snippets-or-pages/98435/5 "2006-07-19T15:05:15Z")

</div>

Oliver B. wrote:

> What I have done in the past is to create a page with the particular  
> behavior and then create a snippet that includes the page, this snippet  
> can then be included into every other page, while original page with  
> the ERB behavior is executed in the ERB behavior context and the current  
> page you are looking at in its own behavior context.

This sounds potentially cunning but I don’t quite follow; how do you  
include a particular page from a snippet? Is it possible to manage  
layouts in this context, given the layout includes the ERB and parsed  
layouts are included within the scope of Behaviors?

> Of course, instead  
> of going the way through a snippet you can use \<r:include\> directly.

My installation of Radiant 0.50 doen’t recognise \<r:include … /\> in  
pages or snippets.

---

<div class="post-metadata">

**Author:** ![pond](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/7ab992/32.png) [@pond](https://www.ruby-forum.com/u/pond)\
**Post date:** [July 19, 2006, 6:10am UTC](https://www.ruby-forum.com/t/erb-in-snippets-or-pages/98435/6 "2006-07-19T06:10:55Z")

</div>

On 16-Jul-2006 23:54 +0200, Andrew H. was heard to say:

> John W. Long wrote:
> 
> > A filter may not be the best choice here. Filters don’t have any concept  
> > of where they are being used (the page or snippet). [Use behaviors]
> 
> Provided all pages using the snippet (via a layout or directly) use the  
> ERB behaviour, all is well. However, what about a Not Found page or an  
> archive? That would probably use the same layout as other pages in a  
> site, which wants directly or via a Snippet to include ERB. But it  
> already has the Not Found Behavior, so it can’t have ERB Behavior too.

What I have done in the past is to create a page with the particular  
behavior and then create a snippet that includes the page, this snippet  
can  
then be included into every other page, while original page with the ERB  
behavior is executed in the ERB behavior context and the current page  
you  
are looking at in its own behavior context. Of course, instead of going  
the  
way through a snippet you can use \<r:include\> directly.

Oliver

---

<div class="post-metadata">

**Author:** ![pond](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/7ab992/32.png) [@pond](https://www.ruby-forum.com/u/pond)\
**Post date:** [July 19, 2006, 3:43pm UTC](https://www.ruby-forum.com/t/erb-in-snippets-or-pages/98435/7 "2006-07-19T15:43:46Z")

</div>

On 19-Jul-2006 15:05 +0200, Andrew H. was heard to say:

> layouts in this context, given the layout includes the ERB and parsed  
> layouts are included within the scope of Behaviors?

Yes, that should be possible. You should be able to include the content  
of  
a specific page into a layout, while this included page is rendered  
within  
its own behavior context.

> > Of course, instead  
> > of going the way through a snippet you can use \<r:include\> directly.
> 
> My installation of Radiant 0.50 doen’t recognise \<r:include … /\> in  
> pages or snippets.

Ooops, I ment \<r:find\>\<r:content/\>\</r:find\> so for example:

\<r:find url="/search"\>  
\<r:content part=“form”/\>  
\</r:find\>

That is how I am including live search in my sidebar.

Cheers,  
Oliver

---

<div class="post-metadata">

**Author:** ![pond](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/7ab992/32.png) [@pond](https://www.ruby-forum.com/u/pond)\
**Post date:** [July 19, 2006, 7:47pm UTC](https://www.ruby-forum.com/t/erb-in-snippets-or-pages/98435/8 "2006-07-19T19:47:12Z")

</div>

You wrote:

> What I have done in the past is to create a page with the particular  
> behavior and then create a snippet that includes the page, this snippet  
> can then be included into every other page, while original page with the  
> ERB behavior is executed in the ERB behavior context and the current page  
> you are looking at in its own behavior context.

Thanks for your help with this. Unfortunately I tried it using ‘find’ to  
build what you suggest and it didn’t work. This is almost certainly  
because a “Not found” behavior page gets automatically selected whenever  
something else cannot be found. That page gets parsed, inserts a  
snippet, the snippet inserts the actual “Not found” page - however, it  
is the _first_ page in that set which gets incorporated into a layout,  
which means the ERB in the snippets that the layout includes does not  
get executed since the first page does not have ERB behavior. It it is  
impossible to get a page with the ERB behavior included _first_ because  
a “Not found” page is automatically chosen.

For other behavior types your suggestion should work though it will  
always be the case that the first page in a set of pages is the one that  
dominates the behavioral context since its layout will be the one that  
is used for the final rendered result. Including page parts thereafter,  
by any mechanism, does not include anything that goes around those  
parts.

I still believe that the only way to achieve the specific result I  
wanted originally would be to use a text filter but it would need  
knowledge of the wider application environmet - @controller, @session,  
@request and so-on - indeed, this thread is perilously similar in  
fundamental concept to another one where somebody is trying to get  
ActionController::Base included in a behavior so that Rails helper  
methods are available to that behavior code. The argument seems to be  
that behaviors and filters need access to application environmental  
variables - if it’s good enough for .rhtml files in Rails applications  
it ought to be good enough for page components in Radiant.

Given that Radiant is meant to be a lightweight CMS, of course, this  
might be considered unnecessary application bloat. That would defeat  
what I’m trying to do, but would be an entirely understandable position.

It should at least not be too big a job to modify my own Radiant  
installation to pass similar variables to a Filter-derived class as are  
already available to Behavior-derived classes; this wouldn’t let me do  
Rails helper methods but would provide enough for the limited ERB I have  
in mind.
