Friday, May 22, 2009

Templates, Sequel, and Ramaze (Redux)

After I posted this morning, Jeremy Evans of Sequel fame pointed out a few issues. First he suggested that instead of using datasets in the controller as I had done, that I use the Model instead and showed me how to do it. Second, he suggested that instead of using the User.find(id) in the personal(id) method, I use instead User[id] as more idiomatic. Finally, in the view/index.xhtml view, he noted that Rs has been deprecated in favor of r. So with that, here's the three new files (I neglected to post the models/user.rb earlier anyway).

Here's the new main_controller.rb

# controllers/main_controller.rb
class MainController < Ramaze::Controller
# Use page.xhtml in the view directory for layout
layout :page

# You can access it now with http://localhost:7000/ This should display a
# welcome message. This is the home page.
def index
# Get all of the user's ids and names from the User model. We're going
# to display all of them on the index/home page.
@users = User.id_and_names
@title = "Welcome to SteamCode"

def personal(id)
# Find the user with the given id. This will come from the link created on the
# index/home page.
@user = User[id]

# Create the title with first name / last name 's Home Page.
@title = "#{@user[:first_name].capitalize} #{@user[:last_name].capitalize}'s Home Page"

Here's the new view/index.xhtml

<!-- view/index.xhtml -->
<h2> Users <h2>
<!-- Loop through each of the users (from MainController/index and
Create a link from MainController/personal and the "id" of the user.
This will then call MainController/personal/id and the id will be used
as a parameter to personal. This in turn will allow us to find the user
and go to their "home" page. The "angle bracket question mark r" are
used to put ruby code inside the template and any valid ruby code can
go here.

<?r @users.each do | user | ?>
<li> <a href="#{r(:personal)}/#{user[:id]}">#{user[:first_name].capitalize} #{user[:last_name].capitalize}</a> </li>
<?r end ?>

And finally here's the models/user.rb (not posted earlier)

# models/user.rb
# This is the model for the User and is backed by the :users table in the
# database. We add the id_and_names for the index method in the
# main_controller.
require 'rubygems'
require 'sequel'

# Create the Account model.
class User < Sequel::Model

# Create a class method to grab the id, and first and last names from
# the default User dataset.
def self.id_and_names
select(:id, :first_name, :last_name).all

If you have questions or comments on this or the previous post (or any post for that matter), please don't hesitate to ask.


  1. These last few articles look good (and correct). One thing I'd like to point out is that it is best practice for migrations to be acting directly on the tables, not through the model. That is, your migration code as from(:users).insert(blah) is much preferred over User.create(blah) (which is consistent with how you've written this). This is namely because...what if your first migration only contains first names, but later on you added a constraint to your model that first and last names are required. The model isn't "migration-aware" so to speak. Then you're screwed.

    Also, there's a slightly better way to generate that link href -- see the Helpers section here: for hints.

    Keep up the good work. The more guides Ramaze and Sequel get, the better!

  2. Thanks Maximus for your kind words. Here's what I end up with after looking at Pisto's site:

    <li> <a href="#{r(:personal, user[:id])}">#{user[:first_name].capitalize} #{user[:last_name].capitalize}</a> </li>

    A little bit simpler to be sure. Thanks for the tip.

  3. Slight typo in the post title - "Temaplates"

  4. kd, Thanks. Can't believe no one's noticed that before. I had to read it a couple of times before I actually saw what was wrong.