在Rails中实现多表继承,最DRY的方法是什么?

4

我的应用程序中有几个表共享大部分列。我在一个模型中编写了所有验证,并尝试使所有其他模型从这个模型继承,但出现了ActiveRecord :: SubclassNotFound错误。

以下是我的模型代码:

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

这两个表拥有完全相同的列,我选择使用多表继承(MTI)来提高数据库的可扩展性,因为药房和医院也将使用单表继承(STI)来支持多个模型。

我遇到了以下错误:

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

我想重用我打算为两个模型实现的验证和一些方法。

4
如果你想在两个模型中重复使用相同的代码(验证),为什么不使用混合或关注点?关于多表继承,我会认为Ruby on Rails更喜欢单表继承,违反Rails的约定几乎从来不是一个好主意。当使用类继承另一个ActiveRecord类时,“ type”列具有非常特殊的含义。这可能是我们遇到问题的原因。 - spickermann
在你给我看的链接中,我应该把这个模块放在 concern 文件夹里,对吧? - aplneto
2个回答

3
你需要的是一个抽象类:
class Hospital < ActiveRecord::Base
  self.abstract_class = true

  # validations...
end

然后从你的子类中删除表格名称。


2
如果您正在使用单独的表格,您不应该使用不同的模型作为子类。在这种情况下,您只需要继承ActiveRecord::Base。如果您想共享验证,可以将它们放入一个模块中,并在两个模型中都要求它。
当然,您也可以转移到真正的STI,但在这种情况下,您需要向单个表格添加一个type列。在这种情况下,您可以从Hospital继承,但更好的做法是从Institute继承并让Hospital也从该基类继承。
class Institute < ActiveRecord::Base
  # put your validations here
end

class Hospital < Institute
end

class Pharmacy < Institute 
end

编辑:如果您想使用MTI,请参阅此回答,了解如何设置验证Mixins:https://dev59.com/HGgu5IYBdhLWcg3wYGC3#11372578

最初的回答。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接