Most of my ruby/rails development is against a legacy Oracle database. One of the things we needed to fix, was a user-table with not enough fields. Because the user table was shared with another application, we were not able to alter the table.
So we added another table, user_params, containing possibly extra parameters for each user.

Now it would be nice if each of those possible parameters would behave like a real attribute.

So, first implementation:

class User < ActiveRecord::Base

  set_primary_key "user_name"
  set_table_name "stca_user"
  set_sequence_name "autogenerated"  # do not use a sequence at insert!

  validates_presence_of :user_name
  validates_presence_of :password

  # define some virtual attributes for attributes defined in the UserParam table
  def group_name
    UserParam.get_param_value(self.user_name, 'UserGroup')
  end

  def group_name=(value)
    UserParam.set_param_value(self.user_name, 'UserGroup', value)
  end

  def title
    UserParam.get_param_value(self.user_name, 'UserTitle')
  end

  def title=(value)
    UserParam.set_param_value(self.user_name, 'UserTitle', value)
  end

  def language
    UserParam.get_param_value(self.user_name, 'UserLanguage')
  end

  def language=(value)
    UserParam.set_param_value(self.user_name, 'UserLanguage', value)
  end

  def full_name
    UserParam.get_param_value(self.user_name, 'UserFullName')
  end

  def full_name=(value)
    UserParam.set_param_value(self.user_name, 'UserFullName', value)
  end

  def email
    UserParam.get_param_value(self.user_name, 'UserEmail')
  end

  def email=(value)
    UserParam.set_param_value(self.user_name, 'UserEmail', value)
  end

  # ... snipped away more code

end

Obviously, this code is not DRY. At lot of repetition, like the stuff i hate about C# or java properties. This could be done better, let’s just generate the methods:

class User < ActiveRecord::Base

  set_primary_key "user_name"
  set_table_name "stca_user"
  set_sequence_name "autogenerated"  # do not use a sequence at insert!

  validates_presence_of :user_name
  validates_presence_of :password

  # define some virtual attributes for attributes defined in the UserParam table
  instance_eval do
    [['group_name', 'UserGroup'], ['title', 'UserTitle'], ['language','UserLanguage'], ['full_name', 'UserFullName'], ['email', 'UserEmail']].each do |arr|
      define_method arr[0].to_sym  do
        UserParam.send('get_param_value', self.user_name, arr[1])
      end
      define_method "#{arr[0]}="  do |value|
        UserParam.send("set_param_value", self.user_name, arr[1], value)
      end
    end
  end

end

This looks nice. One disadvantage might be that this is not very readable. At first glance it is no longer clear which attributes are available. But with models that is always the case.

A few things can still be improved. Every get and set is a query against the database. We might want to improve upon that, and cache results.
Also saving the virtual fields is now done when they are being set, but at that time the parent “User” might still not be saved. So this still calls for a better solution.

But this does show why i like ruby so much. It makes me feel powerful :)