ActiveRecord Custom Type Naming Scheme
I am dealing with a table that already has a column with natural type names. Eg there already exists a column called 'provider' that has values of either 'foo' or 'bar'. I want to use STI on this table using the existing type names, as it seems silly to have to add an additional column called 'type' for Active Record to use. Problem is, these type names don't match up exactly the the ruby classes. I was hoping to be able to set up a custom mapping, eg Class1 => foo, Class2 => bar.
I tried the following:
# In the base class
set_inheritance_column :provider
# In Class1
def self.sti_name
'foo'
end
# In Class2
def self.sti_name
'bar'
end
But this doesn't seem to cut it, I get:
The single-table inheritance mechanism failed to locate the subclass: 'foo'
...
activerecord (3.0.8) lib/active_record/base.rb:923:in `find_sti_class'
It looks like ActiveRecord is only equipped to handle full class names and demodularized class names. I am not sure what the purpose of having a protected sti_name method is at all.
I am about to dig deeper into the framework and override ActiveRecord::Base.compute_type. Before I do that, has anyone done this before? Is this a wild goose chase?
Can rails handle custom type names or am I stuck with having the Ruby class names?
Update
I got this to work with:
# In the base class
def self.find_sti_class(type_name)
# Do mapping from foo/bar to Class1/Class2
...
end
I am still wary of hitting some more issues down the road. Is this the right way to do this?
我有类似的情况,并找到了这个链接的解决方案:https://gist.github.com/1381880
Looking at the AR code and just focusing on sti_name
and instantiate
..it seems it might be enough for you to monkey patch those two methods.
I don't have experience with this, but it doesn't look impossibly complicated. Here's how instantiate
looks like:
def instantiate(record)
model = find_sti_class(record[inheritance_column]).allocate
model.init_with('attributes' => record)
model
end
Ideally you'd want to scan the code for anything that references something like record[inheritance_column]
or just plain inheritance_column
and inject your own mapping code in there. Just a quick look and it seems it's not used in that many places.
I'd say what you're attempting IS possible :), but you will need test cases for basic instantiation + stuff where associations are involved to make sure AR can find and build the correct SQL for the different cases.
It's clear though AR was not built with what you're attempting in mind, since the use of inheritance_column
in the code is not clearly abstracted away anywhere. So that's why you need to poke around in the code a bit more.
上一篇: 从多个远程位置拉/推