【问题标题】:What is the most dry way to implement multiple table inheritance in rails?在rails中实现多表继承最干的方法是什么?
【发布时间】:2019-05-20 05:56:26
【问题描述】:

我的应用程序中有一些共享大多数列的表,我在一个模型中编写了所有验证,并试图让所有其他模型都继承自这个模型,但出现ActiveRecord::SublassNotFound 错误。

这是我的模型的代码:

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

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

【问题讨论】:

  • 如果您想在两个模型中重复使用相同的代码(验证),为什么不直接使用 mixin 或关注点?关于多表继承,我认为 Ruby on Rails 更喜欢单表继承,反对 Rails 约定几乎不是一个好主意。当使用从另一个 ActiveRecord 类继承的类时,type 列具有非常特殊的含义。这可能是我们问题的原因。
  • 如果您在链接中显示,我会将模块放在concern 文件夹中,对吗?

标签: ruby-on-rails ruby


【解决方案1】:

你需要的是一个抽象类:

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://stackoverflow.com/a/11372578/891359

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-02-10
      • 1970-01-01
      • 2013-10-14
      • 1970-01-01
      • 2021-06-15
      • 2011-03-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多