Adventures in the land of Ruby on Rails, Part 1
patrick — Sat, 2006-10-14 17:29
So I've been hearing alot of good things about Ruby on Rails (RoR) in various places & from several people including sitepoint.com, several developers in eve-online, & several chat rooms I frequent. I even made an attempt at using the Seagull framework as it's supposed to be based on RoR, but written in PHP. I think part of my problem with Seagull is it starts with a CMS ready built & I was trying to jump in & modify it without having a clue as to what was going on.
Googling for Ruby on Rails sends me to their main page. From the main page I ended up at http://www.rubyonrails.org/down where it boldly states "Get Ruby on Rails in no time" (unfortunately if you're hearing the webpage or using a text browser you'll see "Web development that doesn't hurt" instead).
I like being lazy & initially thought that installing the debian package for rails would be enough, but the debian package doesn't include the gem package manager for rails... which means I'm stuck with waiting for debian testing to update & I can't install any of the extra packages very easily. After checking what debian packages where going to be uninstalled along with rails I noted which packages needed to be reinstalled - libapache2-mod-ruby, & ruby, & rdoc. I also added the libmysql-ruby & libdbd-mysql-ruby packages, but I don't know if they were necessarily needed.
After reinstalling these packages I continued on down the list. Downloading gem from http://rubyforge.org/frs/?group_id=126. The file I downloaded was rubygems-0.9.0.tgz (please check & see what the newest version is... things usually work better with the newest version). After running "tar -xvzf rubygems-0.9.0.tgz" I 'cd'ed into the created directory & ran "ruby setup.rb".
Everything seemed to go just fine & so I proceeded with "gem install rails --include-dependencies". This caused some stuff to be output to the screen & the last line was a complaint because rdoc wasn't installed (yes, I inserted it into the list above). I reinstalled rdoc, reran the "gem install rails --include-dependencies", & this time no complaints (I still haven't checked to see if it created the docs or not).
At this point I have Ruby 1.8.2, gem 0.9.0, rails 1.1.6, rake 0.7.1, & RDoc v1.0.1 - 20041108.
I exited out of 'su' & proceeded as my normal login. "Make your application", it says. "Create your application skeleton and start the server:", it says.
rails path/to/your/new/application
cd path/to/your/new/application
ruby script/server
As I was planning on following the tutorial at ONLamp.com (Rolling with Ruby on Rails) I typed
mkdir -p ~/public_html/rails/cookbook; rails ~/public_html/rails/cookbook. I don't know if the mkdir is necessary or not, but I was trying to avoid any pitfalls.I was flying along, following the tutorial, without any problems when on page 3 it happened. I had run
ruby script/generate controller Recipe, modified it as instructed, & when I went to the url (http://ceta:3000/recipe/new for me as it's on a remote machine) I got an error message. Digging around I found a small note somewhere about 1 of the new security features requires the server process to be restarted after modifying database.yml before the changes will take effect. I changed screens to where the server process was running & CTRL+C which closed the server & dumped me back to the console prompt (please note that if you started the server with the nifty trick of adding '&' to the end to push the process to the background allowing you continued use of the console - you will have to use ps to find the process & then kill the pid).One note here - when I modify configuration files *I'm lazy*. I tend to copy the settings that are there & comment out the originals. Then I can modify to my heart's content & if I ever have to go back I can simply delete (or more likely comment out) my modifications & uncomment the originals.
Unfortunately that's what caused my next problem. I couldn't get the server to restart. It barfed & spewed a bunch of information as to why I was stupid. Ok, it looked fairly normal - pretty much the same format that Java uses to curse at you.
I uncommented the original username & password fields, added root's password, & commented out the username & password that I had added. T'dah! Everything worked just perfectly. Ok, that's nice... at least it works, but you don't necessarily want to access anything as root unless you have to so I didn't want to stay with root.
I commented out the username/password combo for root & tried my alternate username/password. It didn't work. It was still barfing on the password field.
I changed the alternate username's password to be the same as root's & tried that. It barfed.
I flushed privileges for mysql (just on the off chance that it wasn't working because it was trying to connect to mysql before figuring out whether it could start). It still didn't work.
I fired up another X-Chat window, logged into irc.freenode.net, joined #rubyonrails, & asked my question. Hah, this channel requires a registered nick in order to talk. Ok, how does this work again? I flip to the server tab just so I don't get message spam over the top of channel chatter &
/msg nickserv help, /msg nickserv help register, /nickserv register mypassword. Yay, now I have a registered nick & I can change back to the channel & announce my problem...
argv[] wasn't sure what the problem was as he'd never seen such a problem. Everybody else seemed to be asking questions as well. Then there was this guy...
--> blahed (n=sda@hxxx.xxx.xxx.xx.ip.alltel.net) has joined #rubyonrails <blahed> i need some help
That's about as useful as asking, "can I ask a question?" Well obviously a question was asked & so therefore the person has already answered their own question. "May I ask a question?" isn't much more useful because if you were not allowed the question wouldn't show up or you'd be banned simply for asking =) Lucky for him he quickly recovered with a detailed description of his problem.
Meanwhile I kept digging around & trying to find something useful that might solve my problem...
=> Booting WEBrick...
/usr/lib/ruby/1.8/yaml.rb:133:in `load': syntax error on li
ne 19, col 2: ` password: xxxx' (ArgumentError)
from /usr/lib/ruby/1.8/yaml.rb:133:in `load'
from /usr/lib/ruby/gems/1.8/gems/rails-1.1.6/lib/in
itializer.rb:459:in `database_configuration'
from /usr/lib/ruby/gems/1.8/gems/rails-1.1.6/lib/in
itializer.rb:181:in `initialize_database'
from /usr/lib/ruby/gems/1.8/gems/rails-1.1.6/lib/in
itializer.rb:84:in `process'
from /usr/lib/ruby/gems/1.8/gems/rails-1.1.6/lib/in
itializer.rb:42:in `send'
from /usr/lib/ruby/gems/1.8/gems/rails-1.1.6/lib/in
itializer.rb:42:in `run'
from ./script/../config/../config/environment.rb:13
from /usr/local/lib/site_ruby/1.8/rubygems/custom_r
equire.rb:27:in `gem_original_require'
... 7 levels...
from /usr/local/lib/site_ruby/1.8/rubygems/custom_r
equire.rb:27:in `gem_original_require'
from /usr/local/lib/site_ruby/1.8/rubygems/custom_r
equire.rb:27:in `require'
from /usr/lib/ruby/gems/1.8/gems/activesupport-1.3.
1/lib/active_support/dependencies.rb:147:in `require'
from script/server:3
I'm not quite sure how I discovered it, but at some point I discovered that there was a tab character between "password:" & the actual password. Changing this tab character to a space immediately solved the problem. Just to be sure I tried it with several spaces between "password:" & the password - this worked just fine. Apparently the only whitespace that yaml.rb can handle is a space character. Not only that, but it requires at least 1 space character! If you try to pull off "password:xxxxx" it throws a hissy fit as well.
Now that I had the server started again & this time with a non-root username & password, it was time to test "recipe/new". Yay, the page now works as intended. I reported my findings to argv[], to which he responded that yaml is very picky.
I got a bit further down the page until I reached typing out all the stuff for "list.rhtml" and got that filled out. In my haste to see what would happen I refreshed the page & got an error about "You have a nil object when you didn't expect it!...". I promptly returned to the tutorial to see what I had done wrong & scrolling down I noticed I missed the next step... adding a single line of code to the list method in "recipe_controller.rb".
I get all the way to page 5 again before running into trouble. The code displayed for "edit.rhtml" displayed fine, but RoR wasn't saving any of my changes. Initially my changes consisted of only the items in the drop down menu at which point I assumed this was being caused by the fact that there was no id attribute listed for the <select> drop down menu. I modified my "edit.rhtml" to include an id attribute for the <select> drop down menu, refreshed the page, made my change, clicked the update button, and the menu selection hadn't been saved.
At this point I got suspicious that perhaps something in the tutorial didn't mesh with what I had done. Because the tutorial hadn't changed any of the default pages for the categories I decided that was the best place to start looking for clues. Pulling up the edit page for the first category item & viewing it's source I noticed that the 'category' portion of all of the id & name attributes where capitalized ('Category' instead of the expected 'category').
Off I went, doing a search & replace using s/(id|name)=\"recipe/\1=\"Recipe/g. I reloaded the form, changed some values, hit the update button, & values were actually modified.
Ok, but why did this work? I checked both "category_controller.rb" & "recipe_controller.rb" to see what I had done. The tutorial had lowercased the scaffold code & I had capitalized it (thereby getting it to capitalize the text on the default HTML pages).
class CategoryController < ApplicationController
scaffold :Category
end
instead of
class CategoryController < ApplicationController
scaffold :category
end
Ok, now here's where I go outside of the tutorial & ask questions (which I currently don't have answers to)
- is there a way for the edit page to figure out what case the update page is expecting the form variables to be?
- would a better way be to set a type of form_variable_name variable inside the controller that could be used in both the HTML templates as well as the updater method & how would I go about doing this?
The initial "oh wow" of having the scaffold code automatically generate the required html for listing, viewing, modifying, & deleting flew completely out the window after having to create *.rhtml templates for each of these. I'm hoping that this isn't completely the case & that you can still get some sort of form automation... Otherwise the rapidness & coolness goes out the window.
At this point I took a break to try to get RoR working under Apache2. Googling for ROR & apache2 I came across this page that was fairly helpful - Howto Setup Apache With FastCGI And Ruby Bindings in Ruby on Rails. No matter what I did ended up with errors & couldn't seem to find any of the files I'd worked on for the tutorials. At least until I came across a tidbit almost at the very bottom of the page -
Permissions
Make sure that (when using Apache) your www or apache user has write access to your rails/tmp and rails/log directory. If not you will get many 500 errors!
Ah, ok... as the group that the apache user is in is already assigned as the group on all files & directories (except a few I turned off) under ~/public_html this wasn't to painful. I ran chmod g+w log/ tmp/, changed several ownership permissions on individual files in log/ & checked tmp/ ... lots of directories & files in there, so chmod g+w log/* tmp/* tmp/*/*. I went back to my browser & loaded up the location I expected apache to serve & there was the page I expected. Yet another missing file found by correcting the file permissions.
Several links I came across in my search for tutorials & errors include the following -
Stephen's Web - Ruby On Rails Stephen's Web - Ruby On Rails (2) IBM Developer Works - Fast-track your Web apps with Ruby on Rails