Rails 有很多通过有一个多态

Rails has many through has one polymorphic

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

澄清一下,任何“locatable”都应该有一个位置,但一个位置应该能够有多个与之相关联的locatable。

当前设置:

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

非常感谢任何帮助:)

因为我最终弄清楚了,所以要回答我自己的问题。

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

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

如果您想与“locatables”建立关系,即获取所有关联的记录,您必须在 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

  

我会考虑你是否只是不必要地使它过于复杂。使用多态连接 table 的唯一实际优势是您可以在不向 table 添加列的情况下创建额外的模型“locatable”。如果不冒 N+1 查询的风险,您实际上不能将它用作同质集合,因为多态关联不支持预先加载。

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

最简单的解决方案是简单地向用户添加一个外键列 table 和一个单独的关联:

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

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