Tuesday, January 1, 2008

Upgrade to Rails 2.0

Well, to usher in the New Year, I bit the bullet today and tried upgrading one of the applications I built for my client to Rails 2.0 . The process to do the upgrade was relatively painless. The whole idea of Rubygems is awesome and is something I feel that the Java community is horribly lacking.
Installing Rails 2.0.2 was a simple as:

>sudo gem install rails

And then changing the line in the environment.rb to:

RAILS_GEM_VERSION = '2.0.2' unless defined? RAILS_GEM_VERSION

The issues though came in when I actually tried to run the application. Here's a brief rundown of the refactoring that I had to do and some gotchas that maybe other will run into.

1. Pagination - I had heard all of the warnings that the default pagination was going to be taken out of Rails 2.0, but like more programmers I am somewhat lazy ( or too busy ) to implement changes until I really NEED to. Well, if you upgrade to Rails 2.0 and you use the default pagination functions in Rails 1.2, you will NEED to do something else. It has been ripped out for Rails 2.0. I must say I agree with the the idea to pull it out as pagination is something that really should be done by a plug-in. After some searching I found a two options for people in my same situation.

a. classic_pagination - This is the plugin that will give you the same functionality of the old Rails 1.2 pagination. Many in the Rails community frown on the use of the old code for performance reasons, flexibility and good object oriented design.

b. will_paginate - This is the plugin that is seems like the Rails community is backing going forward for pagination. It offers some advantages of the old pagination methods and doesn't require too much refactoring to implement. Here is a good screencast on using it.
I decided to go with will_paginate since this is more the standard and new projects going forward this is what I will probably use, so it made sense for me to get aquainted with how it works. It turned out to be actually very easy to make the changes. He is an example of a change in the controller that I needed to make for "Jobs".

This:
@job_pages, @jobs = paginate(:jobs, :order => 'deadline')

Was changed to:
@jobs = Job.paginate(:page => params[:page], :order => 'deadline')

and in my view this code:
Page Number: <%= pagination_links(@job_pages, :params => {'job[filter]', @job_filter }) %>

was changed to simply:
<%= will_paginate @jobs %>

Much easier to read, understand and maintain. I'd suggest watching the screencast I mentioned above to learn more.

2. Nested RESTful routes - This was very annoying and was a little difficult for me to find much information on how to fix it. It seems like when you define a nested route in the routes.rb in Rails 2.0, the helper methods that are created don't behave the same or work the same as they did under Rails 1.2 This is what I had previously.

We have a relationship with jobs containing artifacts. So in our routes.rb:

map.resources :jobs do |job|
job.resources :artifacts
end

and in the a show.rhtml view had:

artifacts_path(@job)

When running under Rails 1.2 this works fine and generates the url

/jobs/1/artifacts URL.

Under Rails 2.0 we get an error:

You have a nil object when you didn't expect it!
The error occurred while evaluating nil.to_sym

Annoying. Well it turns out you have 2 options.
a. Modify your routes.rb to be

map.resources :jobs do |job|
job.resources :artifacts, :name_prefix => nil
end

b. Change the call to artifacts_path to instead be:

jobs_artifacts_path(@job)

There is information on this helper methods here. Thank god I found this reference. That is one thing that I do find frustrating about Rails is the lack of the documentation I was able to find when going through an upgrade. It seems like this issue I ren into should have beein BIG BOLD letters warning people that old RESTful methods don't work the same with out the changes that I mention. Anyway, I digress. I decided to go with the more simpler change of adding :name_prefix => nil to my routes.rb since I was worried about making sure I found all of the helpers. Hopefully this is the right choice and will work in all my cases. It seems to work for the time being.

3. Running unit tests in Textmate - It seems like there is some issues with a file called Builder.rb and it conflicting with Builder.rb in Rails 2.0. I couldn't run my tests in Textmate until I did what was described here. Not a big deal, but again... annoying and nothing that I have seen other documentation. With 75% of the Rails community using TextMate I'm surprised that at the very least DHH didn't mention it in the release notes for Rails 2.0

4. Capistrano - Capistrano 2 is what is now used by default with Rails 2.0. I tried running a simple 'cap deploy' after upgrading an have been getting some odd errors. I need to track down exactly what is going on. I had thought that deploy.rb was backward compatible, but I guess not. For now I have been doing `cap _1.4.1._ deploy` and forcing it to use the old version for now. I'll track this down shortly.

5. Flash.now - So, I re-ran by functional tests and started getting failures. I have the following line in my application.rb

flash.now[:error] = "You are not authorized."

When running under 1.2.3 and my functional test I have an assert to validate that the error returns in the flash.

assert_equal "You are not authorized", flash[:error]

However, when running under Rails 2.0.2, THE FLASH IS NOT RETURNED! Why is that?

If I change the line in the application.rb and remove the .now to be

flash[:error] = "You are not authorized."

THE TEST PASSES! Not sure why this is in the case. I haven't seen anything in the release notes that mention an upgrade would cause this. Maybe I'll send a post to the RUM group to see if others have seen something similar.

All in all though, the upgrade to 2.0.2 hasn't been too bad. I guess I was hoping that it would be trivial, but I guess what can I expect? I did come from 1.2.3 all the way to 2.0.2 and I can't expect everything to just automatically work right out of the box. I has however only been 8 months since I started work on this system and am surprised the versions that we are up to in Rails. I'm excited to see where things are in at in another 8 months!

5 comments:

Jason said...

"The whole idea of Rubygems is awesome and is something I feel that the Java community is horribly lacking."

The java world does have the same concept - maven. I'm not sure as I am relatively new to ruby/ror but I believe that maven was out long before gems showed up.

Localtone, LLC said...

Hey Jason,
Thanks for your comments! You are correct, I forgot to consider Maven. Maven is very similar to the Gems repository and can effectively do the same thing, on a PROJECT level. They are however in my mind, slightly different. Gems are installed at the SYSTEM level and multiple versions can be installed. In the ruby world, it's up to the client that runs your ruby program to 'gem install' of the gem that is required. In the case of Maven, you specify the library and version and it's downloaded from the repository and used just for that project - not at the system level. Anyway, because of the gem repository I was able to install Rails 2.0, but still keep the old 1.2 version at the system level and easily hop between the two to run my application with a change to the environment.rb.
Your point is well taken though, Maven does offer similar functionality in the Java world. I should have thought to mention that. Thanks again for commenting and pointing this out!

Jason said...

Good to know. I wasn't aware that gems behaved that way - as I said I am very new to this all and have been struggling to adjust my java-centric brain to this "most of it is already done for you" concept that ruby has embraced.

Anonymous said...

Hello,

I'm actually using Mephisto to developp a blog for my company in France.

Could you please explain me what I am supposed to do now?
"
Liquid error: You have a nil object when you didn't expect it! The error occurred while evaluating nil.source"

Arnaud

Localtone, LLC said...

Hi Anonymous,
I have done a little bit of work with Mephisto ( and another CMS tool built in Rails called Radiant ), but not a whole lot recently. I should be able to help you out though if you are having troubles. Can you post more information on the error in terms of your liquid template and the context in which you are trying to run it? Please feel free to contact me directly offline if you want. Thanks for reading the Localtone Blog!