Rails 有很多通过有一个多态

Posted

技术标签:

【中文标题】Rails 有很多通过有一个多态【英文标题】:Rails has many through has one polymorphic 【发布时间】:2022-01-17 12:39:39 【问题描述】:

我正在尝试设置多态实体 has_one 位置,但一个位置可以属于许多多态实体。我遇到的困惑是我需要指定多态关联,而guess + check 不起作用,哈哈。

澄清一下,任何“可定位”都应该有一个位置,但一个位置应该能够有许多与之关联的可定位对象。

当前设置:

class User
  has_one :locatable_location, as: :locatable
  has_one :location, through: :locatable_locations
end

class Entity
  has_one :locatable_location, as: :locatable
  has_one :location, through: :locatable_locations
end

class LocatableLocation
  belongs_to :locatable, polymorphic: true
  belongs_to :location
end

class Location
  has_many :locatable_locations
  has_many :locatables, polymorphic: true, through: :locatable_locations
end

任何帮助都非常感谢:)

【问题讨论】:

【参考方案1】:

因为我最终弄明白了,所以我会回答我自己的问题。

错误出现在位置模型中。改为

class Location
  has_many :locatable_locations
  has_many :users, through: :locatable_locations, source: :locatable, source_type: :User
  has_many :entities, through: :locatable_locations, source: :locatable, source_type: :Entity
end

如果您想与“定位”建立关系,即获取所有关联的记录,您必须在 location 中定义一个方法,例如

def locatables
  users + entities
end

如果你的用例有很多很多像我一样的定位,那么你也可以做类似的事情

class Location
  RELATIONS = %i[User Entity]
  has_many :locatable_locations
  RELATIONS.each do |associated_klass|
    has_many associated_klass.to_s.snake_case.to_sym, through: :locatable_locations, source: :locatable, source_type: associated_klass
  end

  def locatables
    RELATIONS.reduce([])  |all, curr| all.append(send(curr.to_s.snake_case)) 
  end

  

【讨论】:

【参考方案2】:

我会考虑您是否只是不必要地过度复杂化。使用多态连接表的唯一实际优势是您可以使其他模型“可定位”,而无需向表中添加列。您实际上不能将它用作同质集合而不冒 N+1 个查询的风险,因为多态关联不支持预加载。

这种实现方式也不能保证用户只能拥有一个“当前位置”——由于简单的竞争条件,可能会出现重复。 has_one 关联实际上只是将 LIMIT 1 放在查询上。另一方面,belongs_to 只能有一个值。

最简单的解决方案是简单地将外键列添加到用户表和单独的关联:

module Locatable
  extend ActiveSupport::Concern
  included do
    belongs_to :location
  end
end 

class User < ApplicationRecord
  include Locatable
end

class Entity < ApplicationRecord
  include Locatable
end

class Location < ApplicationRecord
  has_many :users
  has_many :entities
end

魔法总是有代价的——在这种情况下,它会彻底破坏您的数据库设计。

【讨论】:

以上是关于Rails 有很多通过有一个多态的主要内容,如果未能解决你的问题,请参考以下文章

Rails:如何创建多态关系/友谊模型

Rails 5 有很多通过实现

Rails 4 ActiveRecord 有很多通过关系不能从 sql 文件读取

ruby Rails has_many:通过多态协会(http://goo.gl/lxmehk)

如何在rails中有很多通过创建关系

Rails 上的两个作用域有很多通过返回比一个单一作用域更大的计数