Tuesday, June 23, 2009

Updated 2009-06-24: Ramaze and Etanni Templating (String Interpolation Version)

In a comment in my last post Phrogz suggested that perhaps I should talk a bit more about Ruby string interpolation which is used by Etanni in templating. We've only used it in very simple ways but you can put any Ruby code inside of the #{} and the result will have a to_s() called on it. We can use this to do some interesting things in Etanni without needing the form. Note that the examples I'm giving here are pretty contrived but should give you some ideas on the sorts of things you can (possibly not should) do.

Here's our start.rb:


require 'rubygems'
require 'ramaze'

class MainController < Ramaze::Controller

# Use page.xhtml in the layout directory for layout
layout :page

# You can access it now with http://localhost:7000/
# All we're going to do is set the title in here and
# everything else will come from our view/index.xhtml file.
def index
# The title is used by the layout/page.xhtml file to set the title
# for the page.
@title = "Index Page"

# We'll use this boolean to decide what to show.
@saw_dog = true

# The number of dogs we've seen.
@dog_count = 3
end

end

Ramaze.start



Pretty simple this time around. We set the title, whether we saw any dogs, and the number of dogs we saw. The dogs came from Phrogz' example and I thought in his honor, we should go ahead and stick with them.

Here's the view/index.xhtml code (where the interesting stuff is going on in this example):


<!-- String interpolation version with if/then/else. -->
<br/>
#{if @saw_dog then "I saw a dog!" else "I didn't see any dogs!" end}

<!-- Using the ternary operator -->
<br/>
#{@saw_dog ? "I saw a dog!" : "I didn't see any dogs!" }

<!-- Check the count, if the count is anything but 1 add an "s" at the end. -->
<br/>I saw #{@dog_count} dog#{"s" unless @dog_count==1} at the park

<!-- Put the number of dogs seen -->
<br/>
#{"dog<br/>"*@dog_count}

<!-- Put the number of dogs seen by creating a list. -->
<br/>
<ul>
#{ d=''; 1.upto(@dog_count) do d << "<li>dog</li>" end; d}
</ul>

<!-- Put the number of dogs seen by creating an array and using join (from ^manveru)-->
<br/>
<ul>
#{Array.new(@dog_count){ "<li>dog</li>" }.join}
</ul>




First off, we use an if/then/else to display whether we saw a dog or not. Through all of these examples, remember that Ruby will return the last thing calculated for the expression. In this case, either the result of the "then" or the "else". Next we have the same thing using the ternary operator. I first saw this in C and it's a pretty handy tool to have lying around. After this, we have Phrogz' example where we put the dog_count and then if it is not 1, we add the "s" on the end of "dog". He used the ":s" form (an identifier) of this, but this may be a bit more readable for the non-experts among us. Next we put out the number of dogs we saw using the "*" operator of a string. In this case we add the br tag to put each of them on a separate line. Finally, we do things the hard way. Instead of using our as we did in the last post, we use only string interpolation to create the list. Like I said, this is not the way I'd recommend doing it, but it may give you some ideas. Update: Even more finally, we create the same list by creating an array and doing a join on it. This comes from ^manveru and will probably be faster and use less memory than the previous version.

The other files, layout/page.xhtml and public/page.css are the same as earlier, so just grab them from our last post.

As always, let me know if you have any questions or comments.

Sunday, June 21, 2009

Etanni Templating

Etanni has replaced Ezamar as the default templating engine for Ramaze and if anything it is even simpler. There are only a very few lines of code for the entire thing shown here. Etanni really only supports two things. The first is standard Ruby interpolation such as #{@x} which can go in your template and also for sections where the result should not be put into the output stream. We've used both of these in previous posts, especially the interpolation, but we haven't really talked about them too much. I decided that I needed to learn a bit more about it after this series of emails on Etanni (ignore the Subject and especially read Michael's final post on the subject where he explains things pretty well (at least it helped me out quite a bit).

Here's a bit of code that uses both types. We'll start out with our start.rb code:


require 'rubygems'
require 'ramaze'

class MainController < Ramaze::Controller

# Use page.xhtml in the layout directory for layout
layout :page

# You can access it now with http://localhost:7000/
# All we're going to do is set the title in here and
# everything else will come from our view/index.xhtml file.
def index
# The title is used by the layout/page.xhtml file to set the title
# for the page.
@title = "Index Page"

# Some simple text to just place on the page in view/index.xhtml.
@text_1 = "Hello World"

# We'll put this text (text_2) out count (5) times.
@count = 5
@text_2 = "Goodbye World"

# We'll create a list with these elements.
@arr_title = "List Elements"
@arr = [ "some", "list", "elements" ]

# We'll use this boolean to decide what to show.
@bool = true
end

end

Ramaze.start



There are five sections in here. The first sets the title which will be interpolated in the layout/page.xhtml file. We've already seen this usage a number of times. The second piece just sets a text value to "Hello World" and this will be interpolated in the view/index.xhtml file (as will all of the rest of the pieces). In the next part we set two things a count equal to five and another string to "Goodbye World". We'll use these to print out "Goodbye World" five times in the output. Next we set an array title and an array with three elements which we'll use to generate a list in the output. Finally, we have a boolean, bool, set to true which will be used to decide which text to display.

Here's the view/index.xhtml file:


<!-- Put out the text in text_1 -->
#{@text_1} <br/> <br/>

<!-- Use count to put out text_2 count times. -->
<?r 1.upto(@count) do ?>
#{@text_2} <br/>
<?r end ?>
<br/> <br/>


<!-- Put out the array title and then each element in the array. -->
#{@arr_title} <br/>
<ul>
<?r @arr.each do |a| ?>
<li>#{a}</li>
<?r end ?>
</ul>

<!-- If the bool is true then print that out otherwise print out that it was false. -->
<?r if (@bool == true) then ?>
bool was true!
<?r else ?>
bool was false!
<?r end ?>



This is pretty straight forward and mirrors the start.rb from earlier. We first put out the text in text_1. Next we use count to put out text_2 five times and then we put the arr_title and then the arr as a list. Finally, we check bool and print out whether it is true or false.

Here's the layout/page.xhtml:


<!-- view/page.xhtml -->

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<!-- Use the page.css in the public directory and set title based on
what's set in the associated method.
-->

<link rel="stylesheet" type="text/css" href="/page.css"/>
<title>#@title</title>
</head>
<div id="header">
<h1>SteamCode</h1>
</div>
<body>
<!-- Display the actual content. This will come from the method or the
associated view/*.xhtml file
-->

#@content

<!-- Set the footer in the center of the screen. -->
<div id="footer" style="text-align: center;">
<h5> Powered by Ramaze </h5>
</div>
</body>
</html>


You can grab the public/page.css from an earlier post.

I'd definitely recommend reading the emails that started this with Michael's observations and also the actual code (both linked to above).

As always, if you have questions or comments, let me know.

Monday, June 8, 2009

Using the js method and the XHTML Helper

In my last post on Ajax, I had some JavaScript code in the layout, that really shouldn't have been there. After I started looking at it, I came up with a solution that would have worked, but after discussing it on the Ramaze list, I was pointed towards a nicer solution. This involves using the XHTML helper. There's not a lot of documentation around it, but you can find the source code here. I'm just going to show the use of the js method, but the usage of the css is simiar and there are also js_for and css_for that take arrays (I haven't tested these, so you might not want to take my word for it).

Here's our start.rb

# start.rb
#
# This is the main program for the example. It loads the controller and model,
# and then starts up Ramaze.
#
require 'rubygems'
require 'ramaze'

class MainController < Ramaze::Controller
# Use page.xhtml in the layout directory for layout
layout :page

# Add the xhtml helper so that we can use the js() method in our views.
helper(:xhtml)

# You can access it now with http://localhost:7000/
def index
# We'll set the page_javascript to be public/js/index.js
@page_javascript = "index"
@title = "Using the js method"
end

# You can access it now with http://localhost:7000/page1.
def page1
# We'll set the page_javascript to be public/js/page1.js
@page_javascript = "page1"
@title = "Using the js method - Page 1"
end
end

Ramaze.start



There's mostly just our normal things in there, setting the layout and a couple of methods. The one unusual, actually just new, is the helper(:xhtml). What this will do is allow us to use the js method in our views to create a JavaScript simply. The two methods, index and page1 really don't do anything except set the @title and the @page_javascript variables. These will get picked up and used in our page.xhtml layout. Here's the code for that:


<!-- view/index.xhtml -->

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<!-- Our jQuery is in the public/js directory -->
<script src="js/jquery-1.3.2.js" type="text/javascript"></script>

<!-- Use the js method from the xhtml helper to add the javascript for this page -->
#{ js @page_javascript }

<title>#@title</title>
</head>
<body>
#@content
</body>
</html>


Once again, this is quite simple. We do have a script tag to include the jQuery library. The next line is where we use the js method that we discussed earlier. What will be produced for this line from index is <script src="/js/index.js" type="text/javascript"></script>. It will be similar for the page1 line.

Our two views are also very simple. The only thing in them that we're really going to use is the <div id="page_container"></div> page_container div. Here is view/index.xhtml:


<!-- view/index.xhtml -->
<h2>Hello World</h2>
<div id="page_container"></div>


and view/page1.xhtml:


<h2>Page 1</h2>
<div id="page_container"></div>


Finally, we have our two JavaScript files. Once again, very little. All we're going to do is grab the page_container div and set it's html value. This isn't a very good use of JavaScript in general and jQuery specifically, but it should at least work.

Here's public/js/index.js:


// public/js/index.js

// For jQuery put everything inside of the document ready code.
$(document).ready(function() {
// Add markup to page_container
$("#page_container").html("Index from Javascript");
}
);


and public/js/page1.js:


// public/js/page1.js

// For jQuery put everything inside of the document ready code.
$(document).ready(function() {
// Add markup to page_container
$("#page_container").html("Page 1 from Javascript");
}
);

This really is pretty simple, but I did want to show how the js method could be used. As I noted above, there's also a similar command for css as well as the js_for and css_for noted above. Sorry about the lack of formatting on the JavaScript.

Let me know if you have any questions or comments.