views:

33

answers:

3

What i'm looking to do is have a base class for some of my models that has some default activerecord behavior:

class Option < ActiveRecord::Base
  has_many :products

  def some_method
    #stuff
  end

  #etc..etc..
end

class ColorOption < Option
  #stuff...
end


class FabricOption < Option
  #stuff...
end

However, I want ColorOption and FabricOption to each be in their own tables. I do NOT want to use STI or have a table for the base class "Option". The only way I've gotten this to work is with some non-inheritance metaprogramming magic. But I wondered if there was a way to tell AR that the base class does not need a table. Its just there for extra behavior, and to put the other subclasses in their own table as usual.

Thanks, Craig

A: 

Hi you may check this post but you'll need to redefi ne self.columns in your child classes

Bohdan Pohorilets
yeah i saw that, but seems like more work than its worth.
fregas
+3  A: 

Looks like a case for a module that you include.

module Option
  def self.included(base)
    base.has_many :products
  end

  # other instance methods
end

class ColorOption < ActiveRecord::Base
  include Option
  set_table_name '???' # unless ColorOption / FabricOption have same table -> move to Option module

  #stuff...

end


class FabricOption < Option
  include Option
  set_table_name '???' # unless ColorOption / FabricOption have same table -> move to Option module

  #stuff...
end

http://mediumexposure.com/multiple-table-inheritance-active-record/

Stephan

Stephan Wehner
yeah i tried the module, but the module cannot see the active record methods such as has_many :products. It says the method is undefined.
fregas
How did you try?Stephan
Stephan Wehner
fregas: make sure to include any class method calls, like `has_many` or validations inside the `self.included` method Stephan has in his example
Kyle Slattery
ah the self.included refers back to the class that is including the module. excellent, i'll try that!
fregas
sweet, that worked beautifully! yay ruby! Much more elegant than the meta programming was doing...
fregas
+1  A: 

What you want is an abstract class:

class Option < ActiveRecord::Base
  self.abstract_class = true
end

class ColorOption < Option
  set_table_name "color_options"
end

class FabricOption < Option
  set_table_name "fabric_options"
end

I have some extra information about STI and #abstract_class on my blog.

François Beausoleil
havent tried this but this seems reasonable too
fregas
do i have to set the table name, or can AR just infer that?
fregas
Try it without. Can't tell off-hand if it will work without.
François Beausoleil