1

I have two classes

class Animal < ActiveRecord::Base; end

class Kitty < Animal; end

But when I Kitty.find_by_name('Ser Pounce') I find that I am actually querying the Animals table, despite having created a Kitty table through a migration.

So how can I tell rails that I want Kitty.find_by_name to query the Kitty table and not the parent Animals table?

Csteele5
  • 1,262
  • 1
  • 18
  • 36

2 Answers2

4

Inheriting from models that inherit from ActiveRecord is a pattern for Single Table Inheritance. Instead of using STI (unless that's actually what you want), I would use a behavioral mixin pattern. Basically, make Animal a module and use include, so you'd have:

module Animal; end

and then

class Kitty < ActiveRecord::Base
  include Animal
end

That's probably the simplest way of keeping tables distinct per model and still keeping behavioral style OO.

photoionized
  • 5,092
  • 20
  • 23
3

The answer really depends on what you are tying to do: Sharing functionality, single table inheritance, or multiple table inheritance.

You can override the default STI behaviour via the abstract_class attribute:

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

Any subclasses of Animal will then use their own tables.

There is a slight drawback to this method though; scopes defined on the super class don't work. You need to define them via a class method instead.

br3nt
  • 9,017
  • 3
  • 42
  • 63
  • Be aware that you'll still have to set the `table_name` of the subclass manually to get this to work without STI. – photoionized May 12 '16 at 04:32
  • 3
    @photoionized, are you sure? I've got an application doing this at the moment and the subclasses don't need to define their tables. – br3nt May 12 '16 at 04:34
  • 3
    You are right, I was indeed mistaken, here's my quick test to prove you are correct: https://gist.github.com/photoionized/9f224c2a0f39574e1a44c21780a88fd9 – photoionized May 12 '16 at 04:42