ActiveRecord: Legacy primary keys


#1

Hi,
I’m building a frontend for a legacy schema, with tables like this:
CREATE TABLE types (
a_type_cd varchar(6) NOT NULL default ‘’,
a_type varchar(30) NOT NULL default ‘’,
PRIMARY KEY (a_type_cd)
);

The primary key is specified by the user (not auto-generated), and needs
to be updateable. I create the following a base class to support this,
which I would like some feedback on. It works with scaffold generated
code. Specifically:

  • I feel like there should be a better way to do the “update” method.
    (It is overridden so that you can update the primary key)
  • Is overriding self.inherited a good idea?
  • This implementation works for me, are there any other features anyone
    can think of that they may require in this instance?

Usage:
class AType < UserPKActiveRecord
set_primary_key ‘a_type_cd’
end

Base Class:
class UserPKActiveRecord < ActiveRecord::Base
def self.inherited(sub)
set_table_name undecorated_table_name(sub)

self.class_eval <<-EOS
  def initialize params = nil
   super
   self.id = params[self.class.primary_key] if params && 

params.has_key?(self.class.primary_key)
end
EOS
end

def self.set_primary_key pk
super

alias_method pk, :id
alias_method pk + '=', :id=

self.class_eval <<-EOS
  def #{pk}_before_type_cast
    return read_attribute(self.class.primary_key) if 

read_attribute(self.class.primary_key)
return self.id
end
EOS
end

def self.content_columns
@content_columns = columns.reject { |c| c.name =~ /(_id|_count)$/ ||
c.name == inheritance_column }
end

def update
if !@new_id
sql = "UPDATE #{self.class.table_name} " +
"SET #{quoted_comma_pair_list(connection,
attributes_with_quotes(false))} " +
“WHERE #{self.class.primary_key} = #{quote(id)}”
else
sql = "UPDATE #{self.class.table_name} " +
"SET #{quoted_comma_pair_list(connection,
attributes_with_quotes(false))} " +
", #{self.class.primary_key} = #{quote(@new_id)} " +
“WHERE #{self.class.primary_key} = #{quote(id)}”
end
puts sql
connection.update(sql, “#{self.class.name} Update”)
end

def update_attributes(attributes)
if attributes.has_key?(self.class.primary_key)
@new_id = attributes[self.class.primary_key]
end
result = super
self.id = @new_id
@new_id = nil
return result
end
end