Fork me on GitHub

Gem released: has_attributes_from

Posted by Frank Oxener
on Friday, August 21, 2009

My first little gem has_attributes_from for merging attributes from one ActiveRecord Class to another individual STI subclass.

So why, do we want to do that, you might ask? Well, I was working on a rails project where clients take care of the administration (planning and billing) for child daycare centres. In this project I have all kinds of people objects, like a child, a contactperson, a father, mother, caretaker etc. etc. So, the ideal casus for a Single Table Inheritance implementation. So I implemented a ‘classic’ Person Class as follows:


  create_table :people, :force => true do |t|
    t.string   :firstname
    t.string   :lastname
    t.string   :initials
    t.string   :type
    t.string   :social_security_number
    t.string   :gender
    t.datetime :date_of_birth
  end

However, I like to add certain extra attributes to a Child, like for example its nickname and information about its allergies. So I introduce another class which I call ChildDetail. Of course I can add these attributes to the people table as well, but in this project I had several more fields to add and some other attributes for a father., which would lead to a lot of columns for only two subclasses (of the five in total).


create_table :child_details, :force => true do |t|
    t.string   :nickname
    t.string   :vaccination
    t.string   :allergy
    t.integer  :child_id #belongs_to relationship with Child
end

Ok, now I can access the extra attributes


class Person < ActiveRecord::Base
end
class Child < Person
  has_one :child_detail
end
class ChildDetail < ActiveRecord::Base
  belongs_to :child
end

child = Child.first
=>#<Child id: 2, firstname: "William", lastname: "Oxener", type: "Child", social_security_number: "123456789", gender: "m", date_of_birth: "2005-12-02 00:00:00">
puts child.child_detail.nickname
=>"Bill" 

This is not really the way I want it, I like to ask directly for the nickname of a child without going through a child_detail. So to solve this ‘problem’ I wrote the has_attributes_from gem. Add the following line to your environment.rb file


config.gem 'dovadi-has_attributes_from', :lib => 'has_attributes_from', :version => '>=0.1.1', :source => 'http://gems.github.com'
Install and unpack this gem to your vendor directory or install as a plugin
./script/plugin install git://github.com/dovadi/has_attributes_from.git

Now we can do the following:


class Person < ActiveRecord::Base
end
class Child < Person
  has_attributes_from :child_detail
  validates_presence_of :nickname
end
class ChildDetail < ActiveRecord::Base
end

With has_attributes_from the attributes from ChidDetail are merged with Child. A child object acts as one single object and I can even do validation on nickname directly (or the other attributes from ChildDetail).


child = Child.first
=>#<Child id: 2, firstname: "William", lastname: "Oxener", type: "Child", social_security_number: "123456789", gender: "m", date_of_birth: "2005-12-02 00:00:00">
puts child.nickname
=>"Bill" 
child.update_attributes(:nickname=>nil)
=>false
child.errors.full_messages
=> ["Nickname must be present"]
child.nickname="Daam" 
=>"Daam" 
child.save
=>true

I think this is much nicer, besides it was fun to make and a good exercise to put some Ruby meta programming into practice.

The ampersand in Twitter4R

Posted by Frank Oxener
on Monday, March 03, 2008

For Bemba.com we use the Twitter4R gem, which works like a charm.

sharing web pages with friends in one click on several social networks at once!

Except we had some problems when we used the & character in our messages. It turned out that URI.encode was used for encoding and the text message was chopped off at the & character.

The solution was to use CGI::escape for encoding in ../twitter/lib/twitter/ext/ stdlib.rb:


class Hash
  # Returns string formatted for HTTP URL encoded name-value pairs.
   def to_http_str
    result = ''
    return result if self.empty?
    self.each do |key, val|
      result << "#{key}=#{CGI::escape(val.to_s)}&" 
    end
    result.chop 
end

Now it is just a matter of submitting a patch for the gem, but although the specifications are all nicely written with RSpec, we’re not able to run the specs.


no such file to load -- ./../spec_helper (LoadError)

What are we doing wrong here….where is the spec helper?

Update of our website.

Posted by Frank Oxener
on Thursday, February 28, 2008

It was about time to do an update of our website.

First, we migrated from Typo to the more ligther-weight and stable Mephisto. The migration was also the moment to use a more timeless theme (Scribbish) and, from now on, to post in English.

It also reflects a slight change in our business focus. We’re still very much dedicated to our Ruby and Rails work, but our active involvement in the Fablab community has lead to a repositioning of our services.

With the expertise of Ruby, Rails and agile software development and our knowledge of digital and personal fabrication, we think that we’re better suited for multidisciplinary projects on the edge of open source connected soft- and hardware.

We closely follow the trends and developments in that sector and we of course share this on our blog.

So stay tuned …... !!