Embedded Ruby and Tag Libs

A

Adam Van Den Hoven

Hey guys,

I've been dabbling with ruby on and off for a year or so and recently
more often. At work we do Java development and I keep thinking that
it would be nice to be able to bring some of the stuff I designed
there into my own work, which I want to do in ruby.

I was wondering if anyone had thought about adding something like the
Java TagLibs to ruby (I guess it would embedded ruby). In my case, it
would make long term maintenance of files MUCH easier as I can give
it to a non-technical person without much documentation. In most
cases people who don't understand programming do understand parts of
HTML markup. If I could hide what is currently inline code behind
things that look like tags, its easier to give maintenance over to
non-technical folks.

Here's a simple example. Often you want to do tiger striping on
tables (alternate background color on each row). Because there isn't
sufficiently wide spread support for CSS2 and CSS3 selectors, you
tend to do the following:

<table>
<tr class="odd"><td>...</td></tr>
<tr class="even"><td>...</td></tr>
<tr class="odd"><td>...</td></tr>
<tr class="even"><td>...</td></tr>
<tr class="odd"><td>...</td></tr>
<tr class="even last"><td>...</td></tr>
</table>

Unfortunately, if you want to add something between rows 4 and 5 you
need to reset all your classes. This can get complicated. However, if
I had a taglib I could ask my content authors to write the following:

<av:table>
<av:trow><td>...</td></av:trow >
<av:trow><td>...</td></av:trow >
<av:trow><td>...</td></av:trow >
<av:trow><td>...</td></av:trow >
<av:trow><td>...</td></av:trow >
<av:trow><td>...</td></av:trow >
</av:table>

And leave the generation up to the code.

I can think of hundreds of specific tags I might create, depending on
the situation, which would make authoring content easier and would
give me better control over the rendering of a page. It could also
make writing code easier in general. It would also be useful to have
many of the tags defined in the JSTL.

Just a thought I had.
Adam
 
A

Austin Ziegler

I've been dabbling with ruby on and off for a year or so and recently
more often. At work we do Java development and I keep thinking that it
would be nice to be able to bring some of the stuff I designed there
into my own work, which I want to do in ruby.

I was wondering if anyone had thought about adding something like the
Java TagLibs to ruby (I guess it would embedded ruby). In my case, it
would make long term maintenance of files MUCH easier as I can give it
to a non-technical person without much documentation. In most cases
people who don't understand programming do understand parts of HTML
markup. If I could hide what is currently inline code behind things
that look like tags, its easier to give maintenance over to
non-technical folks.

Frankly, I think that TagLibs are overblown nonsense ;) You can
implement much of this with Amrita, I think, which completely separates
code from data. Even with erb/eruby, though, you could do something
like:

<table>
<% max =3D data.size
data.each_with_index do |el, ix| %>
<tr class=3D"<%=3D (((ix % 2) =3D=3D 0) ? "even" : "odd") +
=09=09 ((ix =3D=3D max) ? " last" : "") %>">
<td><%=3D el %></td>
</tr>
<% end %>
</table>

There's other ways to do this, but as I don't really do a lot of stuff
that needs this, this is simple enough.

-austin
 
A

Adam Van Den Hoven

Austin.

I think you missed my point.

I used the example of a table only because it was an easy example,
not because its not solvable in other ways.

In general, you're right; all three of those technologies CAN do
exactly what I'm trying to do. Its very trivial for you or I to write
that markup and I would be inclined to do it if I was going to be the
person responsible for maintaining the site. The thing is I really
hate maintaining clients sites for them. Its a lot of overhead for a
change that they can do themselves. I tend to build a site once then
provide a style guide and show them how to update their content.
There is no way I'm going to be able to document for my client the
mechanic how to create a table on some arbitrary page using the code
you have below. I can just tell him what markup to use but the amount
of markup he has to remember far exceeds the data he want to add. A
taglib is an EXCELLENT way of hiding that complexity. It also allows
me to change the behaviour of that tag after the fact, as
requirements change, without editing content.

Or lets say that the site I'm making is about the history of salmon
fishing in British Columbia. For various reasons, I want to markup
photographs as follows:

<div class="photo">
<div class="title">Fishermen at the Steveston docks, circa 1843</
div>
<img href="..." />
<div class="caption"><p>Yadda yadda yadda.</p><p>Blah blah blah</
p></div>
<div class="cite"><spand class="photographer">James Tyson</
span><span class="publication">Steveston Chronicle</span><span
class="year">1983</span></div>
</div>

Now, I could ask my content authors to simply write that out every
time. The problem is that I perhaps I want to do something a little
different in certain circumstances, add a different class if its the
first one on the page, for instance. Now I have to write out a lot of
rules for authors to remember. Its a lot simpler, IMHO, if I just
told them to write the following:

<x:photo imghref="someurl">
<x:title>Fishermen at the <a href="/steveston.rsp">Steveston
docs</a>, circa 1843</x:title>
<x:caption><p>Yadda yadda yadda.</p><p>Blah blah blah</p></
x:caption>
<x:cite photographer="James Tyson" publication="Steveston
Chronicle" year="1983" />
</x:photo>

I can then write my markup from that.

Now lets say that it was decided to change the format so that the
citations were all done in foot notes. pretty much all I'd have to do
is change the behavior of my <x:photo> and <x:cite> tags and the
change would be made.

In my opinion tag libraries are most useful when they are used to
reduce complexity for content authors.

Adam
 
J

James Edward Gray II

I tend to build a site once then provide a style guide and show
them how to update their content. There is no way I'm going to be
able to document for my client the mechanic how to create a table
on some arbitrary page using the code you have below.

I bet you could use ERb and some helper methods to great affect for
something like this.
Its a lot simpler, IMHO, if I just told them to write the following:

<x:photo imghref="someurl">
<x:title>Fishermen at the <a href="/steveston.rsp">Steveston
docs</a>, circa 1843</x:title>
<x:caption><p>Yadda yadda yadda.</p><p>Blah blah blah</p></
x:caption>
<x:cite photographer="James Tyson" publication="Steveston
Chronicle" year="1983" />
</x:photo>

I can then write my markup from that.

An example of what I'm thinking:

<%= photo :imgref => "someurl",
:title => "Fishermen at the...",
:caption => "<p>Yadda yadda yadda...",
:photographer => "James Tyson",
:publication => "Steveston Chronicle",
:year => 1983 %>

That's trivial to implement as a simple Ruby method call where you
will have the full language at your command to build up whatever
return value you need.

Just a thought.

James Edward Gray II
 
D

Devin Mullins

Hi, Adam,

First, DHH's opinion on this matter might be of interest to you:
http://www.loudthinking.com/arc/000408.html
(DHH = The Rails Guy, btw)

Second, the best way I can think of to achieve something like what
you're talking about in ERB would look like this:

class AvTable
def initialize(out)
@out = out; @side = :eek:dd
end
def trow
@out << %Q{<tr class="#@side">}
yield
@out << "</tr>\n"
@side = (@side == :eek:dd) ? :even : :eek:dd
end
end

def av_table(out)
out << "<table>\n"
yield AvTable.new(out)
out << "</table>\n"
end

a = ERB.new <<RHTML
<% av_table(_erbout) do |av| %>
<% av.trow do %><td>...</td><% end %>
<% av.trow do %><td>...</td><% end %>
<% av.trow do %><td>...</td><% end %>
<% av.trow do %><td>...</td><% end %>
<% av.trow do %><td>...</td><% end %>
<% end %>
RHTML

a.result.display

Not sure how you would take care of "last", though (without writing an
internal iterator for your data), but I'm no expert, and this is
probably a crappy way of achieving what you're after. (I, for instance,
am not a fan of passing around _erbout.)

Devin
 
A

Adam Van Den Hoven

I agree with DHH for the most part (I have to read it in more detail
but for now, I'll grant the argument). However, he's talking about
web applications that follow a MVC pattern. As it turns out, that's
not the ONLY type of problem to solve with ruby.

My problem is primarily one of content management. I have a client
who sells widgets. They're not selling widgets online they're just
doing promotional marketing pieces. Normally you'd just write the
HTML directly and be done with it. However, sometimes, as a web
developer, you have to write fairly complex markup in order to make
things work out the way you want to. Unless you want to maintain the
site yourself, a general pain in the neck, you need some mechanism to
hide complexity from your clients yet allow them to edit the content
themselves. In some ways this is what textile does (hiding the
complexity of HTML from authors) but I need to be able to create more
complex behaviors than what textile does.

Actually DHH says something that I think supports my point:
Extracting complex view logic is painful: With tag libraries, it's
possible to be a good programmer and rid the views of complex logic
by extracting code and replace it by tags. That is a noble and
right path to follow. The problem is when the effort required to do
the right thing is so intense that its basically a project in
itself. Then its not something you're gently invited to do. It's a
huge barrier and easy source of procrastination ("I'll extract
later...") and guilt ("If only I had extracted sooner...").

I simply have a different view of complexity. I want to extract those
things that are simple from my point of view but complex from the
point of view of content authors.

Adam
 
D

Devin Mullins

Devin said:
Hi, Adam,

(I, for instance, am not a fan of passing around _erbout.)

I cleaned up the syntax, btw, with a dependency on my favorite Rails
support class:

require 'rubygems'
require 'binding_of_caller'

class AvTable
def initialize(out)
@out = out; @side = :eek:dd
end
def av_trow
@out << %Q{<tr class="#@side">}
yield
@out << "</tr>"
@side = (@side == :eek:dd) ? :even : :eek:dd
end
end

def av_table(&blk)
Binding.of_caller do |b|
out = eval '_erbout', b
out << "<table>"
AvTable.new(out).instance_eval &blk
out << "</table>"
end
end

ERB.new( <<RHTML ).result.display
<% av_table do %>
<% av_trow do %><td>...</td><% end %>
<% av_trow do %><td>...</td><% end %>
<% av_trow do %><td>...</td><% end %>
<% av_trow do %><td>...</td><% end %>
<% av_trow do %><td>...</td><% end %>
<% end %>
RHTML

__END__

And, of course, you can replace do ... end with { ... } if you prefer.

Yeah, you might need/want a different templating framework than yet
exists for Ruby. I dunno. I hope somebody else responds who has
experience in some of the other templating systems, 'cause I'm pretty
much clueless. :)

Devin
 
A

Adam Van Den Hoven

James,

I agree, except that it starts to fall apart as you get more complex.

Lets take an example from rails that REALLY annoys me: form_tag. It
follows largely the same form you suggest.

Right now to make a form in rails you do the following:

<%= form_tag :controller=>"foo" :action=>"bar" %>
Name:
<%= text_field "person", "name", "size" => 20 %>
Password:
<%= password_field "person", "password", "maxsize" => 20 %>
Single?:
<%= check_box "person", "single" %>
Description:
<%= text_area "person", "description", "cols" => 20 %>
<input type="submit" value="Save">
<%= end_form_tag %>

There's no easy way to encapsulate this into a single method,
although Devin (as I'm writting this) has some good suggestions.
 
A

Adam Van Den Hoven

That's excellent.

Now "all" we need is a parser to convert

<av_table> ...</av_table>

into


av_table do

...

end
 
J

James Edward Gray II

James,

I agree, except that it starts to fall apart as you get more complex.

Lets take an example from rails that REALLY annoys me: form_tag. It
follows largely the same form you suggest.

Right now to make a form in rails you do the following:

<%= form_tag :controller=>"foo" :action=>"bar" %>
Name:
<%= text_field "person", "name", "size" => 20 %>
Password:
<%= password_field "person", "password", "maxsize" => 20 %>
Single?:
<%= check_box "person", "single" %>
Description:
<%= text_area "person", "description", "cols" => 20 %>
<input type="submit" value="Save">
<%= end_form_tag %>

There's no easy way to encapsulate this into a single method,
although Devin (as I'm writting this) has some good suggestions.

Would you mind showing how you would clean this up with an XML syntax?

I personally find XML very wordy.

James Edward Gray II
 
J

James Edward Gray II

That's excellent.

Now "all" we need is a parser to convert

<av_table> ...</av_table>

into


av_table do

...

end

If you can count on valid XML, REXML (a standard Ruby library) makes
everything you are asking for pretty easy.

James Edward Gray II
 
A

Adam Van Den Hoven

The problem is that I LOVE XML, and find it easy to work with, mostly
because its easy to abstract complex things with it... which is how I
think.

Without thinking of MUCH better ways to do this, I submit the following:

<av:form model="person">
<av:field name="name" />
<av:field name="password" />
<av:field name="single" />
<av:field name="description" />
</av:form>

I would then do much the same thing that rails does now where you
would assume (but provide ways to explicitly set) things like
localization key for the label, the controller to call etc. I would
look at the model, "figure out" that name is a string, password is
secret, person is boolean and description is text and render the
correct markup that I define for each of those field types. Look to
see if a Person is already provided (and assume an update) otherwise
create one (and assume a New).

In rough hand waving.

Keep in mind that I'm looking for a way to define my tag, not for
someone to define my tag.

I'm assuming that whatever parser converts <%= ... %> in to ruby
code can just as easily be setup to do the same thing with tags,
maybe using REXML (or what ever its called). It just needs to be more
precise.

Adam
 
J

James Edward Gray II

The problem is that I LOVE XML, and find it easy to work with,
mostly because its easy to abstract complex things with it... which
is how I think.

Oh well. I'm fine with it if with disagree on that. I really am
only trying to help, not rob you of your favorite tool, I promise. ;)
Without thinking of MUCH better ways to do this, I submit the
following:

<av:form model="person">
<av:field name="name" />
<av:field name="password" />
<av:field name="single" />
<av:field name="description" />
</av:form>

My offer to that would be similar to my last one, though I think this
one is much easier:

<%= person %w{name password single description} %>

We don't have to do things the Rails' way. ;) I don't know about
you, but I know which one of those I would rather be typing a lot of.

I'll stop trying to convince you now though and see if I can't
provide some information you would consider useful...
I'm assuming that whatever parser converts <%= ... %> in to ruby
code can just as easily be setup to do the same thing with tags

No, I don't think ERb is going to meet your needs here.
, maybe using REXML (or what ever its called). It just needs to be
more precise.

I really believe REXML is what you are looking for. Everything you
have asked for is pretty easy with it. It will let you do all these
transformations with a combination of XPath and Ruby which I assume
you will find quite comfortable. You can learn more from the
documentation:

http://www.germane-software.com/software/rexml/docs/tutorial.html

Hope that helps.

James Edward Gray II
 
D

Devin Mullins

Adam said:
That's excellent.
Thanks.

Now "all" we need is a parser to convert

<av_table> ...</av_table>

into

av_table do ... end

You're on your own for that one. I don't really see the light of making
them XML tags, myself, outside of that they're punctuationally cleaner
in this example. It doesn't seem to me like "web developers" are going
to have any more difficulting learning the second syntax than the first.

It was pretty wacky to write that thing, though. I can see the benefit
of a higher-order abstraction in a templating language, but I doubt
you're going to find that in ERb any time soon, as it caters to much
more than HTMLers.

You might want to take a look at Amrita. It takes an entirely different
approach to your problem, but does solve it. http://amrita.sourceforge.jp/

Devin
 
W

Warren Seltzer

I'm not sure, but I *think* what you want is a Content Management System (CMS). They
enable non-techies to maintain their websites. See:

http://www.eweek.com/article2/0,1895,1855201,00.asp
http://www.cmswatch.com/
http://sourceforge.net/search/?type=soft&exact=0&q=content+AND+management&offset=25

To see if I've guessed right.

Warren Seltzer


-----Original Message-----
From: Adam Van Den Hoven [mailto:[email protected]]
Sent: Tuesday, September 27, 2005 12:26 AM
To: ruby-talk ML
Subject: Re: Embedded Ruby and Tag Libs

... Stuff about salmon fishing and Tag Libs elided...
 
A

Adam Van Den Hoven

Yes.

I've been working with Content Management Systems for 6 years, both
developing them and in deploying them for clients.

If I had a way to use tags instead of code, I would be a long way
towards building a simple CMS.
==> SFTP & Text Editor for authoring.
==> RSP & Taglibs for rendering

Adam
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top