Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Refactoring ActiveRecord models with a base class versus a base module

Class A and B are identical:

class A < ActiveRecord::Base
 def foo
  puts "foo"
 end
end

class B < ActiveRecord::Base
 def foo
  puts "foo"
 end
end

What's the difference between refactoring like this with a base class:

class Base < ActiveRecord::Base
 def foo
  puts "foo"
 end
end

class A < Base
end

class B < Base
end

versus like this using a base module:

module Base
 def foo
  puts "foo"
 end
end

class A < ActiveRecord::Base
 include Base
end

class B < ActiveRecord::Base
 include Base
end

Is one way preferable over another?

like image 466
Bryan Locke Avatar asked Nov 10 '09 16:11

Bryan Locke


1 Answers

There's a fundamental difference between those two methods that all the other answers are missing, and that's rails' implementation of STIs (Single Table Inheritance):

http://api.rubyonrails.org/classes/ActiveRecord/Base.html (Find the "Single Table Inheritance" section)

Basically, if you refactor your Base class like this:

class Base < ActiveRecord::Base
  def foo
    puts "foo"
  end
end

class A < Base
end

class B < Base
end

Then, you are supposed to have a database table called "bases", with a column called "type", which should have a value of "A" or "B". The columns on this table will be the same across all your models, and if you have a column that belongs to only one of the models, your "bases" table will be denormalized.

Whereas, if you refactor your Base class like this:

Module Base
  def foo
  puts "foo"
 end
end

class A < ActiveRecord::Base
 include Base
end

class B < ActiveRecord::Base
 include Base
end

Then there will be no table "bases". Instead, there will be a table "as" and a table "bs". If they have the same attributes, the columns will have to be duplicated across both tables, but if there are differences, they won't be denomarlized.

So, if one is preferable over the other, yes, but that's specific to your application. As a rule of thumb, if they have the exact same properties or a big overlap, use STI (1st example), else, use Modules (2nd example).

like image 127
Marcos Toledo Avatar answered Oct 20 '22 00:10

Marcos Toledo