Hands on with Ruby on Rails

Follow along as our editor learns this hot Web dev framework

1 2 3 4 5 6 7 8 Page 6
Page 6 of 8

Querying for data
Next up, I want to tap into the database, find some data and display it. To do that, I need to 1) add logic to the controller, and then 2) add code so the view generates HTML to display data in a browser.

So I go back to the story controller, the file story_controller.rb (in the app/controllers directory), and type

def index
@story_list = Story.find(:all)

This creates a variable called story_list that will hold an array of all the story objects from the database.

Now, in the index.rhtml view, I enter

<p>The stories in my database are:</p>

<% @story_list.each do |title| %>
<%= title.headline%><br />
<% end %>

What's all that code about?

@story_list.each do |title| sets up my code loop. Each is a method that cycles through the @story_list array. Do does just what you'd expect -- tells the program to start doing something. The title between the | pipes is a variable set up for the loop that follows, and it could be named anything.

<% %> brackets signify Ruby code embedded within an HTML page that should be executed but not displayed. Slightly different, the <%= %> brackets show embedded Ruby that's meant to be both executed and displayed. So <%= title.headline%><br /> will display the headline and insert a line break in the browser.

When I go back to my browser and reload, I see

The stories in my database are:

Ruby on Rails hands on: What's so hot about Rails?
QuickStudy: Ruby on Rails
Rails for Java Developers

With a large database, of course, you might not want to show everything in a table. Lenz shows how to get the most recent entry. I change the controller logic tied to my index view to say

def index
@laststory = Story.find(:first,
  :order = > 'id DESC')

This creates a variable laststory, which will store the most recent entry to the table. The Ruby code to the right of @laststory is using the built-in "find" method for the Story class.

This is something else that's slick about Ruby on Rails, the many built-in methods whenever you create an object. Anytime I add another attribute to my class (and thus another field to my database table), I can use the find method to search my database for entries that have a certain value for that attribute. For example, if I want to get the story "Rails for Java Developers" out of my database, I can simply use Story.find_by_name('Rails for Java Developers').

Story.find(:first, :order= > 'id DESC' will find just one item and assign it to the @laststory variable. That item will be the one at the top of the list, which is ordered in descending order. It will be the last one that was created in the table.

Adding logic
Back in the controller, I can add more sophisticated logic for creating a Computerworld.com URL. At the top of the story_controller.rb file, I define my own new method, geturl, that takes one argument:

def geturl(x)  # a method to create a URL using our content ID
x = x.to_s  # to_s turns a number into a string so it can be joined to the URL
@theurl = 'http://www.computerworld.com/action/article.do?
  command=viewArticleBasic&articleId=' + x

Now, I can use this on any page of my project. If the URL structure changes on our site, I only need to update it once, in that one place. And voila, it's changed everywhere.

Yes, I could create a similar function in another programming language. The question is: Would I? Or would I first build the logic into one page, realize later that I want to repeat it and then have to pull it out of some pages to store the string somewhere else? More importantly, a year later, would I remember where it was? Even more importantly, if this were a team project and the initial coder left, how long would it take someone else to find the function and change it? With Rails, it's more likely you'll know where the logic lives.

To take advantage of this on my index page, as a last step, I need to use my new method. I'll add it to my controller:

def index
@last_story = Story.find(:first, :order = > 'id DESC')
  # finds the most recent story
@theurl = geturl(@last_story.contentid)  # uses the geturl method

With all the logic in place, the final piece is to code the view to make this actually display in the browser. I replace the contents of index.rhtml with this:

<p>The last story added to my database of favorite Ruby on Rails stories is <%= @last_story.headline %> at the URL <%= @theurl%></p>

I go to http://localhost:3000/story and see

The last story added to the database is Rails for Java Developers at theURLhttp://www.computerworld.com/action/article.do?command=viewArticleBasic&articleId=9018460

1 2 3 4 5 6 7 8 Page 6
Page 6 of 8
Shop Tech Products at Amazon