Secondly, does anyone have any pointers on how I can make this work in
Active Record in a nice clean way.
In a domain i'm workin in, this type of thing also came up, and I chose
to split it in a somewhat similar way using abstract classes. Create an
abstract class, Wheels, put all common code in there. I chose to
include the equivalent of that mapping table as a constant, so in your
example a "CarToWheelsClassHash" Constant, and then create sub-classes
for each of the wheels table. Override the ActiveRecord Methods for the
Wheel class, and then re-override them in the subclasses to bring them
back.
def self.abstract_find(car_brand, *normalfindargs)
CarToWheelsClassHash[car_brand].constantize.find(*normalfindargs)
end
[other code common to all wheels models]
end
FordWheel < Wheel
code specific to the ford wheels model
end
hope that makes sense to you, i actually really like this solution so
far on my end.
Thanks Gabriel, but unfortunately this exact solution wouldn't work in
our case. The names of the various Wheel tables are not known at design
time. In other words, there's nothing to stop someone creating a new
table and adding it to the mapping table during runtime.
Given the wonderful dynamic nature of ruby I suppose I could get past
that fairly easily by creating the Wheel subclasses dynamically, but I'm
not sure that that is the best approach.
The names of the various Wheel tables are not known at design
time.
well..if this is the case, i don't see how you're really going to keep
from some form of dynamic creation/metaprogramming/code generation and
also keep the design clean...
I guess the best I can come up with right now is to add a
fetch_wheel_model method somewhere that looks something like:
def get_wheel_class(table_name)
@cached_wheel_classes ||= {}
unless @cached_wheel_classes.has_key? table_name
@cached_wheel_classes[table_name] = Class.new(AbstractWheel) do
set_table_name table_name
end
end
@cached_wheel_classes[table_name]
end
but for some reason that doesn't quite feel like a good solution.