在 Rails 上的 Ruby 中实施 STI,如何将对象从一个 class 复制到另一个?

Implementing STI in Ruby on Rails, how can I duplicate an object from one class to the other?

我实现了 STI 来分离两种类型的技能对象:DefinedSkill 和 DeployedSkill。他们在物理上非常接近,但管理方式不同。

DefinedSkill 的一个方法是 deploy 方法,它创建了几乎相同的 DeployedSkill。

最初,我是这样写的:

def deploy
  @template_skill = DefinedSkill.find(params[:id])
  if @template_skill.status.code == "ACCEPTED"
    @deployed_skill = @template_skill.deep_clone include: [:translations]
    @deployed_skill.type = 'DeployedSkill'
---
    @deployed_skill.save
  end
end

但这会生成 DefinedSkill class 的对象,即使我尝试分配 type 属性。

然后我尝试在属性级别工作,并写了这个:

def deploy
  @template_skill = DefinedSkill.find(params[:id])
  if @template_skill.status.code == "ACCEPTED"
    @deployed_skill = DeployedSkill.new(@template_skill.attributes.except(:id, :type))
    # @deployed_skill.type = 'DeployedSkill' (useless as type is managed by STI feature)
---
    @deployed_skill.save
  end
end

但这会产生以下错误:

ActiveRecord::SubclassNotFound (Invalid single-table inheritance type: DefinedSkill is not a subclass of DeployedSkill)

所以这是我的问题:如何在 STI 的上下文中创建同级对象 class?

而不是设置 @deployed_skill = type,尝试使用 becomes 方法:

@deployed_skill.becomes(DeployedSkill)

非常感谢 msencenb 和 felipeecst 让我上路。 看了文档试了一下,得出的结论是现有对象无法转换,但是class创建新实例时应该进行转换。

我应用的方案是:

@deployed_skill = @template_skill.becomes!(DeployedSkill).deep_clone include: [:translations]

解决了我的问题。