Ruby on Rails - Transition to rails 3.0

Well, I just updated to Fedora 15, and along with it comes Rails 3.0.5, so I find myself in the midst of transitioning my two rails apps to Rails 3.0.5

I had hoped to be able to use yum (fedora RPM's) to keep my rails stuff updates, but that just does not seem possible. I have to use gem to install some things. This actually seems to work out, but it makes me nervous.

There is the issue that yum updates will update rails and as API changes happen, my apps will break. It might be wiser to freeze my applications to depend on specific rails versions. In the old days, you did this by setting the variable RAILS_GEM_VERSION in config/environment.rb. I don't have a clue how to do this with rails 3.0.

Here are some handy links:

Converting the project

What I did (and perhaps there is a gentler and kinder way to do this) was to rename my original project and then create a new project using rails 3, and begin copying files:
cd /u1/rails
mv myapp myapp.2.x
rails new myapp
I hear the shrieks and howls in the distance.

Then I tackled things like so:

Without tackling the routing issues, I can't resist just trying:

rails server
It does launch! This is something. I still get the welcome page, which is not surprising given that I have not tackled routes.rb yet. It also warns me that I am missing the mysql2 gem, and I discover there is no RPM package like rubygem-mysql2 as I might have hoped and expected. I guess the rails world has gone to sqlite3 (and maybe I will/should someday, once this disaster is calmed down).

The details on installing the mysql2 gem are in my notes on Fedora 15 and rails. After doing this, my application tries to start. There are two things to do to get rails to route to my application instead of the generic welcome:

In the old days, the root route to get my application started was specified by:
map.connect '', :controller => "login", :action => 'login'
A default route was also given as:
map.connect ':controller/:action/:id'

In the new route.rb, the root route (what a phrase!) is specified by:

root :to => "login#login"
This root route seems to do the job. It does get to the view I would like and tries to do some database access that looks like what it should be doing.

More is required to get the application running. I uncomment the following "non-restful" route that I am warned about and my application takes off.

match ':controller(/:action(/:id(.:format)))'

Mongrel bites the ... dust

Now that I have my application sputtering along with webrick, I give it a whirl by trying service mongrel_cluster restart. (Hey, it was working fine under Fedora 14 a week ago).
I get:
in `require': no such file to load -- dispatcher (LoadError)
Some google searches on this actually do yield answers. There is bad news and good news. The bad news: the basic word is that Rails 3 and mongrel don't get along. The good news: passenger is way better than mongrel.

This is the rails deployment issue that I have confronted so many times in the past when the deployment scheme de jour changes. The present fashion allows a choice between "passenger" and "unicorn". Well, I have always said that deployment is the achilles heel of rails applications. Here we go again. Neither of these is available as RPM packages for fedora.

In a nutshell, passenger is custom made to work with apache and looks like the ideal route for me given that I have an extremely low traffic site. Unicorn along with Nginx is admired by the rails developers and would be recommended for a high traffic (a thousand hits per second) site.

Onward with passenger

Well, passenger actually is pretty slick and I was up an running with it and apache with almost no effort, and frankly it is simpler and nicer than mongrel anyway. It is designed as "mod_rails" for apache (and was called that at one point). So far, I can't say enough good things about it.

API changes and my applications

My first application runs OK after getting the above issues sorted out. Only one API change showed up in Rails 3, and that is that error_messages_for() has gone away. I just commented out the lines that invoke this and see no particular issue with my application (I guess this error reporting wasn't doing much important for me, eh?).

Apparently this was deprecated (and is still available via a plugin, but after reading the reasons, I am OK with doing away with it). The following code is an outline of one persons replacement:

# add this to app/helpers/application_helper.rb
  def errors_for(object, message=nil)
    html = ""
    unless object.errors.blank?
      html << "<div class='formErrors #{object.class.name.humanize.downcase}Errors'>\n"
      if message.blank?
        if object.new_record?
          html << "\t\t<h5>There was a problem creating the #{object.class.name.humanize.downcase}</h5>\n"
        else
          html << "\t\t<h5>There was a problem updating the #{object.class.name.humanize.downcase}</h5>\n"
        end    
      else
        html << "<h5>#{message}</h5>"
      end  
      html << "\t\t<ul>\n"
      object.errors.full_messages.each do |error|
        html << "\t\t\t<li>#{error}</li>\n"
      end
      html << "\t\t</ul>\n"
      html << "\t</div>\n"
    end
    html
  end  
My second application goes smoother once I iron out some apache virtual host issues and remember just what database I was using. The first hitch is that it cannot find a paginate method.

will_paginate

Apparently my second application used will_paginate, which is now a plugin. I do:
gem install will_paginate
Fetching: will_paginate-2.3.15.gem
Now I have to figure out how to tell my rails application to use this as a plugin.

Here is what I did. I added the following line to /u1/rails/myapp/Gemfile

gem "will_paginate", "~> 3.0.pre2"
Then I did:
cd /u1/rails/myapp
bundle install
This reports the gems I already am using, and finally:
Installing will_paginate (3.0.pre2)
Notice that this is a more recent version that the one I apparently uselessly installed earlier (2.3.15).

Eureka! My application is back on the air now!

.rthml or .erb

The new rails 3 scaffolds all have .erb files. My old applications all use .rhtml files. But my old applications work with .rhtml files, so why worry.

Well, I was curious, "what is the difference?", and a google search turns up the fact that .rhtml is deprecated (it seems to be a matter of taste and semantics). The expectations was that .rhtml files would not work with rails 3, but that is clearly not the case. Somebody posted the following script to convert the filenames:

namespace 'views' do
  desc 'Renames all your rhtml views to erb'
    task 'rename' do
      Dir.glob('app/views/**/*.rhtml').each do |file|
	puts `svn mv #{file} #{file.gsub(/\.rhtml$/, '.erb')}`
      end
  end
end
My applications are not under svn, so I don't want to use this Rakefile verbatim, but it shows the way to automate this.
Feedback? Questions? Drop me a line!

Ruby on Rails notes / tom@mmto.org