Tag Archives: Ruby

Cool stuff you can do with rails has_one

Over the past three months has_one has shown itself to be the answer to questions that I was struggling to get an elegent answer for.

The two cases I found were:

1. Specifying a belongs_to :through
2. Accessing one item of a list of related records

The second case ends up expanding to be anytime you want to have a named scope that returns a single record.

Specifying a belongs_to :through with has_one

Say you have a model of the form:

You can see that we’ve used the standard has_many and belongs_to methods to model the relationships between the entities. We’ve also thrown in a has_many through to help model the fact that an organization has_many employees. Conceptually we also want to be able to specify the inverse of this relationship on the Employee. Something like:

The way to implement the belongs_to :through concept is to use has_one :through

Accessing one item of a list of related records

There can often be a desire to specify a scope that returns a single record. This isn’t possible in rails, as scopes by definition are chainable and will return subclasses of ActiveRecord::Relation, which is a list like object.

The way to do this is to setup a has_one with a block specifying a scope. For example:

has_one :head_of_department, -> { where role: ‘department_head’ }, class_name: ‘Employee’

For bonus points the proc and conditions can also be parameterised, so we can end up with a has_one relationship with a parameter. To see the coolness of this we can extend the model a little bit to include
a many-to-many entity and a has_many through relationship.

With the above model it would be handy to have an easy way of accessing the ProjectDepartment easily when you are working with projects. has_one to the rescue.

So with our collection of has ones all together, we end up with code something like:

 

has_one is a powerful tool to have in your rails modelling. Take advantage of it to give some really nice clean looking code.

Updating RubyGems in OSX 10.5.7

.7When recently trying to install Sinatra via RubyGems, I got a message that RubyGems was out of date. I figured that gem would be smart enough to have an easy upgrade command, so there had to be a command to easily upgrade. Naturally there is:

gem update --system

I only found this when looking through google, and I got a series of pages warning to be careful when using gem update --system as it can kill existing gems (http://puctuatedproductivity.com/2007/11/01/unistalling-ruby-installed-by-source-on-os-x, http://thenoobonrails.blogspot.com/2008/06/doing-gem-update-system-might-lose-all.html) so I was a bit nervous.  Since I have a periodic use of ruby and I'm lazy enough to make Larry Wall proud, I figured I'd take a punt on just using gem update --system.  Turns out it just works, and I've kept all my old gems.  Hooray.  Given that the posts talking about issues are old, I'm either assuming that they've done things differently to me, or things have been fixed since then… so… if you need to update gems due to a message:

ERROR: Error installing sinatra:
fastthread requires RubyGems version >= 1.2

or similar, just use gem update --system