aplneto
aplneto

Reputation: 137

What is the most DRY way to implement multiple table inheritance in Rails?

I have a few tables in my application that share most columns. I wrote all validations in one model and tried to make all other models inherit from this one but got an ActiveRecord::SublassNotFound error.

Here is the code for my models:

hospital.rb

class Hospital < ActiveRecord::Base
  validates :cnes, presence: true, numericality: true
  validates :name, presence: true, length: { maximum: 80 }
  validates :address, presence: true, length: { maximum: 50 }
  validates :neighborhood, presence: true, length: { maximum: 30 }
  validates :phone, presence: true, length: { in: 10..25 }
  validates :latitude, :longitude, presence: true, length: { maximum: 20 }
  validates :type, presence: true

pharmacy.rb

class Pharmacy < Hospital
  self.table_name = 'pharmacies' 
end

Both tables have the exact same columns and I choose to use MTI to give my database more scalability, since both pharmacy and hospital will also have STI to multiple models.

This is the error I'm getting:

ActiveRecord::SubclassNotFound:
  Invalid single-table inheritance type: Hospital is not a subclass of Pharmacy

I would like to reuse the validations and some methods I intend to implement for both models.

Upvotes: 4

Views: 3138

Answers (2)

idmean
idmean

Reputation: 14875

What you need is an abstract class:

class Hospital < ActiveRecord::Base
  self.abstract_class = true

  # validations...
end

Then remove the table names from your subclasses.

Upvotes: 3

bo-oz
bo-oz

Reputation: 2872

If you are using a separate table, you should not be using a different model as subclass. In this case you just want to inherit from ActiveRecord::Base. If you want to share the validations, you could put them in a module and require it in both models.

Of course you could also move to real STI, but in that case you would need to add a type column to the single table. In that case you are able to inherit from Hospital, but it would be even better to inherit from Institute and let Hospital also inherit from that Base class.

class Institute < ActiveRecord::Base
  # put your validations here
end

class Hospital < Institute
end

class Pharmacy < Institute 
end

Edit: if you like to use MTI... see this answer for how to set-up validation Mixins: https://stackoverflow.com/a/11372578/891359

Upvotes: 2

Related Questions