Upgrading Ruby to 1.8.6 on OSX and Windows

Posted by Brian in Rails, snacks (March 24th, 2007)

Mac users

Assuming you’ve followed the Hivelogic article that walks you through a basic Ruby on Rails installation, you can use this code snippet to install Ruby 1.8.6.

cd /usr/local/src
curl -O ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.6.tar.gz
tar -zxvf ruby-1.8.6.tar.gz
cd ruby-1.8.6
./configure --prefix=/usr/local --enable-pthread --with-readline-dir=/usr/local
sudo make install
sudo make install-doc
cd ..
sudo gem install rails --include-dependencies

Windows users

Windows users only need to snag the latest version of Curt Hibbs’ One Click Ruby Installer which can be downloaded here.

The major advantage of moving to Ruby 1.8.6 and Rails 1.2.3 is that breakpointer works again.

Update: When I did this on my Macbook Pro, I had to recompile a few libraries like Ruby-DBI and Ruby-ODBC before I could connect to Microsoft SQL Server again.

Serializing ActiveRecord objects

Posted by Brian in Rails, snacks (March 19th, 2007)

One neat feature of Rails’ ActiveRecord objects is the #serialize method which will allow you to store an object in the database as YAML. This means, for example, you could have a User and a Profile. The Profile could be a hash containing a bunch of values that you want to manage, but that don’t necessarily need their own database table.

class User < ActiveRecord::Base serialize :profile end u = User.find 1 u.profile = {"url" => "http://www.rubyonrails.com", :nickname =>"Ninja master"}

u = User.find 1
=> Hash

The magic of the #serialize method takes the given object, serializes it to YAML, stores the YAML in the database, and then unserializes it when you retrieve the data.

This is all well and good, and I thought I would take advantage of this to help me easily cache some data. I have a system in which I have tasks, and a task belongs to a Service which contains the rate we charge for the task. Now, I really want to be able to store the service name and rate on the task when it’s assigned so that the task won’t be affected when I change my rates in the future.

“Aha!” I thought,”I can just use serialize and store the Service object right on the task!” I created a migration that added a service_data field to my database

./script/generate migration AddServiceDataToTasks

class AddServiceDataToTasks< ActiveRecord::Migration def self.up add_column :tasks, :service_data, :text end def self.down remove_column :tasks, :service_data end end

I wrote a quick unit test which I knew would come in handy later.

def test_saves_service_when_task_is_created
@service = Service.find_by_name "Rails development"
task = Task.create :name=>"Create user registration site", :esthours => 5, :service => @service
t = Task.find task.id
assert_not_nil t.service_data
assert_kind_of Service, t.service_data


Then I modified my Task model

class Task < ActiveRecord::Base belongs_to :service serialize :service_data after_create :sync_service_data! def sync_service_data! self.service_data = self.service self.save! end end

That seemed simple enough. However, when I tried it, I got a nasty surprise...

t = Task.find 1
=> nil

No matter what i tried, the service data always came back empty.

Running my unit test proved that something was definitely wrong, as I kept seeing "nil expected to not be nil".

After searching and playing, I decided that #serialize was just not capable of serializing ActiveRecord objects. To get around this, I simply changed my code slightly. I knew that #serialize can handle Hashes so I stored just the attributes hash. Then I redefined #service_data "getter" method to create a new instance of Service from that hash.

class Task < ActiveRecord::Base belongs_to :service serialize :service_data def sync_service_data! self.service_data = self.service.attributes self.save! end def service_data Service.new(self.attributes["service_data"] end end

A quick run of the tests showed that I was now getting what I wanted.

Shortly after I discovered this solution, Jon Garvin offered a much cleaner solution.... don't use Serialize. He found that Serialize does some strange magical things that often get in the way of our intended results. He proposed that I try

class Task < ActiveRecord::Base belongs_to :service after_create :sync_service_data! def sync_service_data! self.service_data = self.service self.save! end def service_data self[:service_data] ? Marshal.load(self[:service_data]) : nil end def service_data=(service) self[:service_data] = Marshal.dump(service) end end

This method simply creates a setter that manually marshals the data to the database column, and a getter that retrieves it again. This method works great, and I thank Jon for his quick solution!

RadRails dead?

Posted by Brian in News, Products, Rails (March 15th, 2007)

It looks like RadRails, the Eclipse-based IDE that has become quite popular, has shut down completely. The codebase is to be incorprated by Aptana for inclusion in their open-source web development IDE, but it’s not apparent when that will be. As of today, radrails.org is now offline meaning that getting a copy of the software is much harder.

Those missing the plugin repository should be using the one by Ben Curtis at www.agilewebdevelopment.com/plugins.

Don’t hesitate to use Eclipse for Rails if you need a good replacement, or use the article that started it all to build your own environment. My upcoming book will recommend that in place of RadRails and will also mention several other free and commercial Rails IDEs.

I look forward to Aptana working on this project, as I believe they have the ability to make RadRails work the way it should work. I never used RadRails, nor have I ever recommended it to any clients, friends, or coworkers, but I do wish the RadRails team the best of luck in their new endeavors.

Test-driven development – Simple example

Posted by Brian in Rails, snacks (March 9th, 2007)

This is a really simple example of why unit tests are important. I was just working with a project where I am creating workshops. Students enroll in these workshops and I have a method on the Workshop model that handles the enrollment.


Connecting to Microsoft SQL Server from Mac OS X

Posted by Brian in Rails, snacks (March 8th, 2007)

Updated on July 2nd, 2008.

As you may know, I develop a lot of new web applications using Ruby on Rails, and to completely buy in to the whole “cult that is Rails”, I purchased a Macbook Pro for development. I am really happy with it, but one of the problems I ran across is the fact that there’s no built-in or prepackaged way to connect to Microsoft SQL Server which I use at work for a lot of my projects.

This guide is written from my notes and should give you the tools you need to get up and running. Some of this information comes from the Ruby on Rails wiki, but some things there are a bit misleading.

This now works on Leopard too!