views:

24

answers:

1

I've got a legacy table that my rails application shares with another application. It has a column called "class". The first time I reference any attribute in that model, I get an error. Subsequent references to attributes work. Is there a good workaround for this, or should I just go modify the other application that uses this table (ugh).

>> Member::Ssg.find(:first)
 => #<Member::Ssg ssg_key: #<BigDecimal:10b169688,'0.253E3',4(8)>, org_id: 2, academic_year: 2006, class: true, next_due_date: "2011-06-01", submitted_date: "2006-02-13", notes: nil, owner_id: "1">
 >> Member::Ssg.find(:first).notes
 NoMethodError: undefined method `generated_methods' for true:TrueClass
        from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/attribute_methods.rb:247:in `method_missing'
        from (irb):2
>> Member::Ssg.find(:first).notes
=> nil

SOLUTION: I went with a combination of the Bellmyer solution and additng the code below to my model

 class << self
   def instance_method_already_implemented?(method_name)
     return true if method_name == 'class'
     super
   end
 end
+2  A: 

This has come up often enough (legacy column names interfering with ruby/rails) that I might just make a plugin out of this. Here's how you can fix it right away, though. Create this file in your app:

# lib/bellmyer/create_alias.rb
module Bellmyer
  module CreateAlias
    def self.included(base)
      base.extend CreateAliasMethods
    end

    module CreateAliasMethods
      def create_alias old_name, new_name
        define_method new_name.to_s do
          self.read_attribute old_name.to_s
        end

        define_method new_name.to_s + "=" do |value|
          self.write_attribute old_name.to_s, value
        end
      end
    end
  end
end

And now, in your model:

class Member < ActiveRecord::Base
  include Bellmyer::CreateAlias
  create_alias 'class', 'class_name'
end

The first parameter to create_alias is the old method name, and the second parameter is the new name you want to call it, that won't interfere with rails. It basically uses the read_attribute and write_attribute methods to interact with the column instead of the ruby methods that get defined by ActiveRecord. Just be sure to use the new name for the field everywhere, like so:

member.class_name = 'helper'

This works with ruby 1.8, but I haven't tested with ruby 1.9 yet. I hope this helps!

Jaime Bellmyer
This doesn't quite do the trick. It allows me to reference the value of the class column, but I still go the error NoMethodError: undefined method `generated_methods' for true:TrueClass from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/attribute_methods.rb:247:in `method_missing' from (irb):2
Anna