多对多的多态?

时间:2018-06-11 07:19:31

标签: ruby-on-rails

在我的应用中,我有很多"网站",我有多种用户类型,例如"患者","提供商","护士&# 34;,"管理员"等

class Patient
  has_many :sites
end

class Provider
  has_many :sites
end

#etc user models...

class Site < ApplicationRecord
  # I don't want to have to name every user model here...
  has_many :patients
  has_many :providers
  has_many :nurses
  # etc. user models...
end

我想做的是拥有它,以便每个用户类型可以拥有多个网站,每个网站可以拥有多个用户类型,但我不想做以下因为用户类型模型可能会呈指数级增长......

我想也许我可以做多态关系,但这并不能满足many_to_many关系。

2 个答案:

答案 0 :(得分:0)

你可能想要使用单表继承:

http://edgeguides.rubyonrails.org/association_basics.html#single-table-inheritance

然后您的患者,提供者,护士等都会从一个名为SiteOwner或类似名称的基类继承,这将是Site类中唯一的关联。

答案 1 :(得分:0)

class Patient < ApplicationRecord
  has_many :sites_siteables, as: :siteable
  has_many :sites, through: :sites_siteables
end

class Provider < ApplicationRecord
  has_many :sites_siteables, as: :siteable
  has_many :sites, through: :sites_siteables
end

# this is the join model between Site and Siteable(which is any model)
# you can generate this model by running the command:
# rails g model sites_siteable site:belongs_to siteable:references{polymorphic}
class SitesSiteable < ApplicationRecord
  belongs_to :site
  belongs_to :siteable, polymorphic: true
end

class Site < ApplicationRecord
  has_many :sites_siteables
  has_many :patients, through: :sites_siteables, source: :siteable, source_type: 'Patient'
  has_many :providers, through: :sites_siteables, source: :siteable, source_type: 'Provider'
end

用法

Patient.first.sites
# => returns Sites
Provider.first.sites
# => returns Sites

Site.first.patients
# => returns Patients
Site.first.providers
# => returns Providers

评论

  • 以上代码:Site has_many :patientshas_many :providershas_many :users等等是必需的,您不能简单地将它们全部整合为一个has_many;即你不能做以下事情(它会产生错误):

    # app/models/site.rb
    has_many :siteables, through: :sites_siteables, source: :siteable
    

...因为如果发生这种情况让我们说你有Site.first.siteables,那么返回的值将是不同种类的模型的集合:即:

Site.first.siteables[0] # => returns Provider
Site.first.siteables[1] # => returns Provider
Site.first.siteables[2] # => returns Patient

...这是有问题的,因为没有单一的模型来表示查询,我想与Rails代码不兼容:即为什么下面的内容令人困惑(至少在SQL字符串生成方面) :

Site.first.siteables.where(phone_number: '123456')

...并且可能是Rails特别不允许的原因,并引发错误(在多态关联上),并且您需要指定source_type

has_many :siteables, through: :sites_siteables, source: :siteable

然而...

如果你真的打算在has_many模型中没有这么多行Site,如下所示:

has_many :patients, through: :sites_siteables, source: :siteable, source_type: 'Patient'
has_many :providers, through: :sites_siteables, source: :siteable, source_type: 'Provider'
has_many :users, through: :sites_siteables, source: :siteable, source_type: 'User'
# ...
# ...

...你可以创造另一个&#34;摘要&#34;用于表示多态记录的表/模型(如果您愿意,我会更新答案;请告诉我)。即你可以做以下的事情:

Site.first.abstract_siteables[0].siteable
# => returns a Patient, or a Provider, or a User, etc...
Site.first.abstract_siteables[1].siteable
# => returns a Patient, or a Provider, or a User, etc...
Site.first.abstract_siteables[2].siteable
# => returns a Patient, or a Provider, or a User, etc...