Ruby on Rails - Fedora 17

July 21, 2012

Whenever I do an operating system upgrade, I can always count on my rails applications breaking. Not only is rails "opinionated software", it is also "fragile software". Just be warned. If you are not willing to be a full time rails developer and closely follow all of the rails API changes, you can expect to be caught with your pants down.

I just did a full fresh install of Fedora 17, which is a big event for Ruby as it is the first fedora release to deliver Ruby 1.9. I have already had some trivial scripts break, so I fully expect troubles with rails.

Installing Passenger

After the upgrade, I had to comment out some passenger related lines in my httpd.conf file to get my web server (apache) to start. Now lets install passenger, and reenable those lines (which will try to reenable my rails virtual hosts).
gem install passenger
yum install ruby-devel
yum install httpd-devel
yum install apr-devel
yum install apr-util-devel
passenger-install-apache2-module
The install of httpd-devel pulls in the two apr packages as dependencies. "APR" is Apache portable runtime, just so you know. The "passenger-install" command compiles the passenger module and then instructs me to add the following lines to my httpd.conf file:
LoadModule passenger_module /usr/local/share/gems/gems/passenger-3.0.13/ext/apache2/mod_passenger.so
PassengerRoot /usr/local/share/gems/gems/passenger-3.0.13
PassengerRuby /usr/bin/ruby
In my case, these go into /etc/httpd/conf.d/passenger.conf.

After updating this file and uncommenting the RailsEnv settings in my httpd.conf file, I can do a service httpd restart without errors.

Installing Rails itself

I have for some time debated whether to get rails via yum or using the gem system. I think using gem is wiser, since I won't have any automatic updates catching me by surprise. Also I can pick and choose the latest rails (and rails plugins) as I see fit. In other words, I am in control, for better or worse.

Yum would give me rails 3.0.11. The rails website tells me that I can get rails 3.2 (released in January, 2012) and they recommend ruby 1.9.3 for use with rails (this is good). They also say that rails 3.2 is the last version to support ruby 1.8 (but not 1.8.6).

su
gem install rails
This is getting me 27 packages, including rails 3.2.6 -- this should be interesting. Rails 3.2.6 was released June 12, 2012 (only a month ago). Plugins are now deprecated (you should use gems for any such functionality). Rails 4.0 is on the way.

Sort out errors specific to my application

It is important to realize that I am starting with a previously running rails application, so any problems I encounter are either due to API changes or some obsolete scaffolding code.

I go to my rails application, delete the Gemfile.lock and do "bundle update". After this, the game is to try to start my application, see what error pops up, figure out how to fix that problem and then repeat this process until we are happily running again.

mysql adapter

The application blows up looking for activerecord-mysql-adapter. The fix is to edit config/database.yml and change mysql to mysql2.

debug_rjs

The application is blowing up because of a call to the debug_rjs() method which no longer exists. This is obsolete scaffolding code. To fix this, I edit config/environments/development.rb and comment out the line:
#config.action_view.debug_rjs             = true

session method missing

Now, I get a routing error with the message: "undefined method `session' for ApplicationController:Class" I am confused and clueless at this point, so I get out the big hammer.

The big hammer - Start over!

cd /u1
mv myapp myapp_ORIG
rails new myapp
We are going to let the new rails build new (and compatible) scaffolding, and bit by bit transplant my old application into the new scaffold. We have done this before, and we can play with a simple demo application along the way.

Following the getting started guide at rubyonrails.org I next do:

cd myapp
rake db:create
And I get the error:
rake aborted!
Could not find a JavaScript runtime. See https://github.com/sstephenson/execjs for a list of available runtimes.
Oh good! Another can of worms!! Some people say to install nodejs. Others say to put these two lines in my gemfile:
gem 'execjs'
gem 'therubyracer', :platforms => :ruby
I do this, then type "bundle install". This works!!
And now I get the "welcome aboard" message in my browser - this is progress.

I could play along with the tutorial at this point, but I decide to get brave and just start transplanting my files:

copy: config/database.yml
copy: config/routes.rb
rename: public/index.html
copy: app/models/*.rb (3 files)
copy: app/controllers/display_controller.rb
merge: app/controllers/application_controller.rb
copy: app/helpers/display_helper.rb
copy: app/views/layouts/display.rhtml
mkdir: app/views/display
copy: app/views/display/_form.rhtml
copy: app/views/display/debug.rhtml
copy: app/views/display/list.rhtml
copy: app/views/display/main.rhtml
copy: app/views/display/show.rhtml
The file application_controller.rb has the line:
session :session_key => '_myapp_session_id'
This may have been what was causing my problems. The idea back in the day when I set it up was to use cookies to handle the session hash, now advised against (the new scheme is to use an SQLite session table). I am still getting the error about the session method, so I comment out this line in application_controller.rb and do this:
cd myapp
rake db:sessions:create
This gives me:
Please install the mysql2 adapter: `gem install activerecord-mysql2-adapter` (mysql2 is not part of the bundle. Add it to Gemfile.)
So I add gem 'mysql2' to my Gemfile (and get rid of the gem Sqlite3), then do bundle install and the rake db:sessions:create now works.

Now I go to config/initializers/session_store.rb and edit this file. I comment out the line that says to use cookies and uncomment the line:

Myapp::Application.config.session_store :active_record_store
As recommended, I restart httpd.

I am advised that if I change the data type stored in the sessions I may want to do:

rake db:sessions:clear

Now I get:

Unknown action
The action 'main' could not be found for DisplayController
And this seems to be exactly right, I have this message commented out in my display controller, even though I have a route for it in my routes.rb ..... I uncomment an empty "main" method in display_controller.rb and now I get:
Template is missing

Missing template display/main, application/main with {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder, :coffee]}. Searched in: * "/u1/rails/myapp/app/views" 
I think I can see what is up here. I have a main.rhtml template, but I see a list of handlers that includes .erb, but not .rhtml (maybe that is old school). I rename all my .rhtml files in views/display to be .html.erb files and voila! I am on to the next issue:
Mysql2::Error: Table 'myapp_development.sessions' doesn't exist: SHOW FULL FIELDS FROM `sessions`
It looks like this session business has more issues for me to solve. Whatever the rake db:sessions:create command did, it did not create a "sessions" table in the myapp_development database as it ought to have.

What I do is to go back to the file config/initializers/session_store.rb and put it back to the old cookie based scheme. But I leave commented out the offending line in Application_controller.rb that tries to specify (override maybe?) the name of the session key -- hey, I don't care what it gets called and it looks to me that you set that in the session_store.rb file now (which makes more sense anyway). This works!! Now my application is running, with some other issues mind you, but my application is the issue now, not obscure rails issues!! It is rendering only part of main.erb -- it turns out my form_tag statements used to be wrapped in <% but now must be wrapped in <%= Who woulda thought?

Now I can launch a query, but I get missing method "paginate", even after adding will_paginate to my gemfile ... restarting the web servers seems to solve this and we are on to the next issue.

Active Record is telling me:

ActiveRecord::DangerousAttributeError
My database has a field named "association" that active record has now decided that it owns and that I should not be using.
add the "safe_attributes" gem to my Gemfile
bundle install
restart the web server
After this, I had to change this:
text = h( mount.send(column.name) )
To this:
text = mount[column.name].to_s
And we were back on the air!
Feedback? Questions? Drop me a line!

Ruby on Rails notes / tom@mmto.org