Refactoring ActiveRecord models with a base class versus a base module

前端 未结 5 1323
执念已碎
执念已碎 2021-02-04 08:22

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
<         


        
5条回答
  •  遇见更好的自我
    2021-02-04 09:10

    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).

提交回复
热议问题