Birds on Rails, Part 3
Now I want to create a new page that lists all the species in the birds table. That is, it looks like this:
Brooklyn Bird Report Master Bird List
- Fulvous Whistling-Duck Dendrocygna bicolor
- Greater White-fronted Goose Anser albifrons
- Snow Goose Chen caerulescens
- Ross’s Goose Chen rossii
- Brant Branta bernicla
…
This will live in the file /masterbirdlist.rhtml
How to do it? I begin by creating a regular HTML file named masterbirdlist.rhtml and putting it in the app/views/bbr directory, but that doesn’t work. It just tells me “Unknown action No action responded to masterbirdlist.rhtml.” OK. Looking back at the notes from Day 1, I see how to handle that. I add this method to the bbr_controller.rb
file:
def masterbirdlist render_text "Hello" end
Now I get “Hello” for the masterbirdlist. Of course that’s not what I want. I want to load the masterbirdlist.rhtml file. How do I do that? About this point I begin wondering what the manual says. Googling for it, it appears that there isn’t one. That compares very unfavorably with PHP and Java, both of which at least have documentation, not to mention reams of third party books available. (Later I found this site, but it doesn’t appear to be a true comprehensive manual; just a random collection of HowTos.) However, there does seem to be some API documentation which mentions render_file()
methods. Maybe that’s what I need? No wait. I remember this now. I bet I have to generate a controller for the masterbirdlist:
~/Web sites/bbr$ script/generate controller masterbirdlist exists app/controllers/ exists app/helpers/ exists app/views/masterbirdlist exists test/functional/ identical app/controllers/masterbirdlist_controller.rb identical test/functional/masterbirdlist_controller_test.rb identical app/helpers/masterbirdlist_helper.rb
That seems to work. I thought this was just for mapping to database tables, but apparently it’s for all pages. This gives me the “Unknown action No action responded to index” at /masterbirdlist. But I’ll create a view for this in app/views/masterbirdlist/index.rhtml. Bingo! That works.
Now let’s add the code to generate the list of species:
<ul> <% @birds.each do |bird| %> <li><%= bird.common_name %></li> <% end %> </ul>
This produces
NoMethodError in
Masterbirdlist#index
Showing app/views/masterbirdlist/index.rhtml where line #14 raised:
You have a nil object when you didn't expect it! You might have expected an instance of Array. The error occured while evaluating nil.each
So now I have to create the birds
variable. Thus I add this code to the masterbirdlist_controller.rb
:
def index @birds = Bird.find_all end
Now I get this error:
NameError in
Masterbirdlist#index
uninitialized constant Bird
I suspect this is because I haven’t mapped that table in Rails yet. i.e. I haven’t generated a model for the birds. Let’s do that:
$ script/generate model Bird exists app/models/ exists test/unit/ exists test/fixtures/ create app/models/bird.rb create test/unit/bird_test.rb create test/fixtures/birds.yml
And now the page works. OK. I ‘m starting to get the hang of this. Adding the genus to the list is easy:
<% @birds.each do |bird| %> <li><%= bird.common_name %> <i><%= bird.genus %></i></li> <% end %>
Now let’s add the species:
<% @birds.each do |bird| %> <li><%= bird.common_name %> <i><%= bird.genus bird.species %></i></li> <% end %>
Oops. That didn’t work:
ArgumentError in
Masterbirdlist#index
Showing app/views/masterbirdlist/index.rhtml where line #15 raised:
wrong number of arguments (1 for 0)
Hmm. Do I just need to put that in two separate tags or do I need to learn how to concatenate strings or terminate statements in Ruby? Concatenating seems to work; and it uses the plus sign, same as in Java:
<% @birds.each do |bird| %> <li><%= bird.common_name %> <i><%= bird.genus + bird.species %></i></li> <% end %>
However, it turns out I forgot a space, so I might as well just go ahead and use two tags anyway:
<% @birds.each do |bird| %> <li><%= bird.common_name %> <i><%= bird.genus %> <= bird.species %></i></li> <% end %>
I think that’s as far as I’m going to go tonight, but just maybe I am speeding up a little past what I could do with PHP (though I still don’t fully grok how the site is getting organized, and the URLs mapped.)
December 3rd, 2005 at 11:24 PM
This is great. You’re like a Jerry Pournelle with skills. I think you should throw in there somewhere “remember, I go through this so you don’t have to.” ;-)
December 4th, 2005 at 3:34 PM
wow. so this is ruby on rails “power learning”. no simple tutorials or sample cookbook applications here; just straight on porting an existing project, tacking on accumulated info about the framework as you go on. not even a hint of rails’ “scaffolding” or that weird article “rails – what goes where” by amy hoy (http://slash7.com/articles/2005/03/06/rails-what-goes-where). not even a ruby syntax tutorial on statement termination and string concatenation! no questions, no documentation, no pauses; just a wild ride on intuition, convention, and how-many-years of programming experience.
i’m currently doing the same thing with the python web framework turbogears and the java web framework wicket. i can really relate; wicket has so little documentation that i can only hope i’m not reinventing anything like PageableOrderedListViews right now. i have a lot of headaches nowadays but i love the learning experience all the same.
btw, you wrote in your initial code
<% bird.genus bird.species %>
, which gave you an error. in ruby, parentheses are optional; instead of concatenating the two as you intended, you actually called the methodbird.genus
with the parameterbird.species
. it’s equivalent would bebird.genus( bird.species )
in java. For example, whereas in java the syntax for a method would look likeoverlay.layout( Point center, Double radius )
, the syntax in ruby would look likeoverlay.layout center, radius
.the default layout of the files, when the scaffolding tool is used, mirrors the actions for that model. for instance, if you have a set of birds, their controller would be called birds_controller, and it would have a model class called birds.
if i want a web page that lists a bunch of birds, i can find the code in the
list
method ofBirdsController
, the class of which can be found in app/controllers/birds_controller.rb i would then look for the list.rhtml page in app/views/birds directory. if i want a web page that edits the bird’s info, i can find the code in theedit
method ofBirdsController
, the class of which can be found in app/controllers/birds_controller.rb i would then look for the edit.rhtml page in app/views/birds directory. amy hoy’s cheatsheet can probably explain it better than i can (http://slash7.com/cheats/rails_files_cheatsheet.pdf).if i were in your shoes and i wanted the default (scaffolded) way of displaying bird info, i would run “script/generate scaffold birds”. i would then go to the created app/controllers/birds_controller.rb file and make sure that its
list
method has the line@birds = Birds.find_all
(or maybe write thatlist
method myself). then i would open the file app/views/birds/list.rhtml and write my display code there, probably something similar to what you wrote.i find rails restrictions on the placement and naming of files to be real draconian. i find it tolerable because it’s much like java’s
package com.foo.bar
; java expects the public com.foo.bar.SomeClass to be placed in a file called SomeClass.java under the directory com/foo/bar. at times, ruby on rails philosophy seems like some weird version of some social contract: “give up your naming conventions and method idiosyncracies and rails will make your life easier. do something that isn’t our way and we’ll hand you over to the mafia.”March 11th, 2006 at 5:38 PM
Hi,
thank you for writing down your approach to handle Ruby on Rails. I just reached a point with a similar problem and you gave me the right hint.
greetings
mtk
December 17th, 2006 at 6:55 PM
Dude,
Your insightful explanation of the list view error when designating a specific view based on the table columns – saved my life.
Its people like you that make the net a indespensible tool for everyone.
Please posting on your great work and thanks again.
August 28th, 2008 at 10:39 PM
home slot machine…
explore.Poole!inscribing?confine …