Why I like Ruby: String Interpolation & "here" docs

There are many reasons to like Ruby. String interpolation and "here docs" are two of them. This post shows how they would improve JSP syntax, in particular.


This is one of those "get it off my chest" articles. If I were writing rhtml pages (Ruby HTML), there wouldn't be an issue. But I'm writing for a JSP server, so I need to write JSP pages. In essence, JSP puts Java code in the HTML page. And mostly that's good. But when you're trying to generate a complex tag, Ruby's string processing features would really come in handy.

Note:
Just to be sure we're on the same page, the two features I'm talking about are string interpolation and "here" documents. String interpolation lets you insert one string into another merely by referencing it. So if name="Fred" and salutation="Dear #{name}," you get "Dear Fred," when you output the salutation. "Here" documents, meanwhile, let you define multi-line strings, like this:

letter = <<HERE
  Dear #{name},
  I'm writing to let you know...
  ...
HERE

At the moment, I need to dynamically generate an object tag in an HTML page, using data from the query string. In order to behave properly on IE, as well as every other browser in the world, the end result has to look like this:

<script type="text/javascript">
  AC_AX_RunContent( 'data','file_path', 
        'style','height:65em;width:100%' 
  ); //end AC code
</script>
<noscript>
  <object data="file_path" style="height:65em;width:100%" />
</noscript>
Note:
I'm not a whiz at this sort of thing. All I originally had in my page was the W3C standard <object> tag. When I opened the file in DreamWeaver 8, it gave me the option of generating code that would work in IE, too. That was pretty cool.

The highlighted parts are the variables in the equation. In JSP, they're defined something like this:

<%
  String file_path = request.getParameter("topic");
  if (file_path == null) file_path = default;
  String style = "height:65em;width:100%";
%>
 
  

Here's the way I would write the code I need using Ruby's string interpolation & "here" documents:

print <<TAG_END
<script type="text/javascript">
  AC_AX_RunContent( 'data','#{file_path}','style','#{style}' 
  ); //end AC code
</script>
<noscript>
  <object data="#{file_path}" style="#{style}" />
</noscript> 
TAG_END

Something of that sort ought to work, at any rate. I might need to escape some of the quotes, but that's about as much as I would need to do to generate the correct code. The important thing is that you can pretty much tell at a glance whether or not you got it right.

Now, I have to admit that my Java is getting a little rusty. So there may be a better way to do the same thing in JSP code. But here's what I have so far:

  out.println("<script type="text/javascript\\">" );
  out.print(  "  AC_AX_RunContent( 'data','" );
  out.print(       file_path + "'," );
  out.print(       "'style','" + style + "'" );
  out.println("  ); //end AC code" );
  out.println("</script>" );
  out.println("<noscript>" );
  out.println("  <object " ); 
  out.print(       "data=\\""  + file_path + "\\" "); 
  out.print(       "style=\\"" + style + "\\"/>" );
  out.println("</noscript>" );

Is that correct? I'm not sure. I hope so. I've looked at it for all I'm worth, and I think it's correct. If it doesn't work, I'm going to have a devil of a time debugging it, because JSP doesn't give you much in the way of error messages. Keep your fingers crossed. I have to use that syntax to generate multiple tags of similar complexity, so it could take a while to get things right.

Follow Up

As Abraham Tehrani suggested, I tried generating the code using String.format. Here are the results:

  out.println( "<script type=\\"text/javascript\\">" );
  out.println(String.format( 
               "  AC_AX_RunContent( 'name','content','data','%s','style','%s'",
                                    content_path, content_style ));
  out.println( "  ); //end AC code" );
  out.println( "</script>" );
  out.println( "<noscript>" );
  out.println(String.format( 
               "  <object name=\\"content\\" data=\\"%s\\" style=\\"%s\\"/>", 
                          content_path, content_style ));
  out.println( "</noscript>" );

This is pretty much the best formatting I could manage for a narrow window like this one. It's a little better, but it still isn't very readable.

It can be made slightly better by making everything line up to the right of "String.format(", but the results still aren't anywhere near readable.

Note:
System.out has a printf statement that would have made things somewhat better, as well. But it isn't supported by the "out" device that JSP is using.

Comments:

String.format(...)?

Posted by Abraham Tehrani on November 24, 2008 at 09:54 AM PST #

Abraham Tehrani wrote:
>
> String.format(...)?
>
Nice! (Slapping forehead)
Nice, succinct, and embarrassing.
I've used that maybe once in the last 10 years.

I've had it so strongly cataloged under "numeric formatting" (to make decimals line up, for example), that it never even occurred.

You're right. It could be a reasonable solution for this problem. (I'm about to revisit that code, which will give me a chance to try it.)

Thanks much for bringing me to my senses.
:_)

Posted by guest on December 05, 2008 at 07:24 AM PST #

I don't get it. If you're using JSP, why not use something like this:

%>
<script type="text/javascript">
AC_AX_RunContent( 'data','<%=file_path%>','style','<%=style%>'
); //end AC code
</script>
<noscript>
<object data="<%=file_path%>" style="<%=style%>" />
</noscript>
<%

Posted by Ovesh on December 17, 2008 at 05:07 PM PST #

Ovesh said:
>
>Why not use something like this:
>
>AC_AX_RunContent( 'data','<%=file_path%>...
>
That's brilliant! Thank you.

I picked up just enough JavaScript and JSP to be dangerous--both in a couple of weeks, to get our web pages working. So while I knew that dynamic Ruby pages (rshtml) had the <%= idiom, and while I even (now) remember reading it in the JSP overview I scanned, it never stuck in my head, somehow. It is, of course, exactly the right solution for string interpolation.

The good news is that there's a blog coming on the interesting bits that makes things work. The bad news is that are some idiocies like the one you just corrected. (Thanks again.)

I wish I could say the same that the activeX bit worked, though. I never got that structure to load anything when I put it into a page. (It might require extra startup-javascript to drive it.)

I wound up using the iframes solution that Charles Reace posted. He needed it to transclude a page from an external site. In the end, it was the /only/ thing I found that worked reliably.
http://www.charles-reace.com/PHP_and_MySQL/Object_Tag_Hack_for_IE/

Posted by Eric Armstrong on December 18, 2008 at 06:37 AM PST #

HERE Docs are a Perl thing, and perl also permits you to turn variable interpolation on and off in the HERE Doc as well. Ruby string interpolation is better than perl but not at all for the reasons you give here, ruby interpolation is better because it permits method calls and more complex structures to be interpolated.

"foo #{foo.bar} baz"

I would argue a templating solution is better for this problem though, and I would argue Perl's TT is the best at this.

TT's delimiters are custom though they default to square-brakets. I find this advantageous because I /want/ my variables to stand out distinctly from the html (precludes subtle interpolation), and I want them to be descriptive (precludes sprintf).

All pseudo code -- but I believe it is very close.

## In caller.pl
$template->process({ variable => $variable });

## In test.tt
<very>
<complex>
<code>
[% variable %]
</code>
</complex>
</very>

Posted by Evan Carroll on November 10, 2009 at 06:57 AM PST #

Post a Comment:
  • HTML Syntax: NOT allowed
Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today