使用多态通过模型来引导 STI - 从父类填充 source_type

问题描述 投票:0回答:1

使用 Rails 7

我正在使用单表继承(STI)来存储一些非常简单的关联。源对象使用 has_many 与 STI 模型关联。遵循一些有问题的建议https://stackoverflow.com/a/45681641/1014251我在连接模型中使用多态关系。这确实非常有效,但有一个烦恼:

创建连接模型时,源类型是从根 STI 类获取的,而不是实际的源。

型号:

class Guidance < ApplicationRecord
  has_many :guidance_details
  has_many :themes, through: :guidance_details, source: :detailable, source_type: "Theme"
end

class Detail < ApplicationRecord
  has_many :guidance_details, as: :detailable
  has_many :guidances, through: :guidance_details
end

class GuidanceDetail < ApplicationRecord
  belongs_to :detailable, polymorphic: true
  belongs_to :guidance
end

class Theme < Detail
end

问题

如果我创建一个新的 GuidanceDetail 并且不指定

detailable_source
系统会插入父类“Detail”:

guidance_detail = GuidanceDetail.create(guidance: Guidance.first, detailable: Theme.first)
guidance_detail.detailable_type => "Detail"

详细类型应为“主题”。

当前要解决此问题,我必须在每次创建新的 GuidanceDetail 时指定Detailable_type。

修复无效

我尝试直接指定子对象的 has_many 关联,但得到相同的结果:

class Theme < Detail
  has_many :guidance_details, as: :detailable
end

替代创建方法不起作用

theme = Theme.first
guidance = Guidance.first

guidance.themes << theme

输出:

GuidanceDetail Create (1.3ms)  INSERT INTO "guidance_details" ("detailable_id", "guidance_id", "position", "created_at", "updated_at", "detailable_type") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id"  [["detailable_id", 11], ["guidance_id", 1], ["position", nil], ["created_at", "2024-11-14 10:24:19.785623"], ["updated_at", "2024-11-14 10:24:19.785623"], ["detailable_type", "Detail"]]

如您所见:“detailable_type”是“Detail”。

ruby-on-rails ruby polymorphic-associations ruby-on-rails-7 sti
1个回答
0
投票

我有点困惑,因为

GuidanceDetail
的父类不是
Detail
,所以我假设你的意思是
Theme

根据我的理解(我将删除它,这可以被反驳),为了存储类名

"Theme"
,看来
Detail
需要是
abstract_class

ActiveRecord::Associations::BelongsToPolymorphicAssociation

foreign_type
设置为
polymorphic_name

polymorphic_name
定义为:

def polymorphic_name
  store_full_class_name ? base_class.name : base_class.name.demodulize
end

base_class

def set_base_class # :nodoc:
  @base_class = if self == Base
    self
  else
    unless self < Base
      raise ActiveRecordError, "#{name} doesn't belong in a hierarchy descending from ActiveRecord"
    end

    if superclass == Base || superclass.abstract_class?
      self
    else
      superclass.base_class
    end
  end
end
© www.soinside.com 2019 - 2024. All rights reserved.