I recently tried to retrofit STI on a database table that had already 
existed for a while. Here's a basic outline of the scenario.

   1. I had a class 'Code' and a database table 'codes'.
   2. 'Code' had an attribute 'units', which could be either '$' or '%'
   3. I wanted the STI classes to be Code::Dollar or Code::Percent

I successfully implemented this with the following:

class Code
  self.inheritance_column = 'units'

  class << self
    def find_sti_class(units)
      unit_class_for[units]
    end

    def sti_name
      unit_class_for.invert[self]
    end

    def unit_class_for
      {
        '$' => Code::Dollar,
        '%' => Code::Percent
      }
    end
  end
end

This works perfectly if I use it in the following way:

Code::Dollar.new(initialization_hash)
Code::Percent.new(initialization_hash)

However, if I do just Code.new(units: '$') or something.build(units: '$'), 
I get an error like the following:

ActiveRecord::SubclassNotFound: Invalid single-table inheritance type: $ is not 
a subclass of Code

What I really want is for Code.new(units: '$') to return me a Code::Dollar
 object.

I was able to trace the lookup of the class name into
ActiveRecord::Inheritance::ClassMethods#subclass_from_attrs. From there I 
could see that it was trying to build the class name from the units value 
in the database, which obviously doesn't work as there isn't a class named 
$ or %.

What I'm really trying to do is setup STI to work correctly when the value 
of the database column doesn't correspond to a class name. As there is 
already another method called find_sti_class, it seems curious that we 
couldn't use it inside of subclass_from_attrs in order to make it work in 
this way. I did try it and was successful, but as find_sti_class is a 
private method, I did not submit a patch using this.

So, after all of that, I guess what I'm after is finding out if doing such 
a thing is possible in Rails as is. If not, would a patch to make it 
possible be desired by people other than myself? And if that patch made 
find_sti_class part of the public interface, would that be likely to be 
accepted?

-- 
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to rubyonrails-talk+unsubscr...@googlegroups.com.
To post to this group, send email to rubyonrails-talk@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/rubyonrails-talk/8af5104b-6e67-4dae-8e63-63216dcddccf%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to