带有耙子任务和自定义STI名称的无效单桌继承类型



我做了一项重构的大量代码,还对DB模式进行了重大更改。现在,我正在尝试编写一项耙子任务,以将记录从旧表迁移到新表。

我正在有这样的课程:

#app/models/restream/service.rb
class Restream::Service < ActiveRecord::Base
def self.types
    %w(custom multiple_destinations_service one_destination_service) +
    Restream::Custom.types + Restream::MultipleDestinationsService.types
  end
  def self.find_sti_class(type_name) #allows to find classes by short names
    type_name = "Restream::#{type_name.camelcase}".constantize
    super
  end
end
#app/models/restream/custom.rb
class Restream::Custom < Restream::Service
  def self.sti_name
    "custom"
  end
  def self.types
    %w(periscope odnoklassniki vkontakte)
  end
end
#app/models/restream/periscope.rb
class Restream::Periscope < Restream::Custom
  def self.sti_name
    "periscope"
  end
end

一切正常。直到我尝试手动添加记录。在我以前的版本中,我有这样的结构:

class Restream::Custom < ActiveRecord::Base
  def self.types; %w(custom periscope vkontakte); end
end
class Restream::Periscope < Restream::Custom
  def self.sti_name; 'periscope'; end
end

现在,我正在尝试只需从旧的restream_custom表中获取所有记录,然后复制类型。大致:

Restream::Custom.create(type: old_restream_custom.type)

,这失败了:

ActiveRecord::SubclassNotFound: Invalid single-table inheritance type: periscope is not a subclass of Restream::Custom

显然不是!但是无论如何,我已经有了type: 'periscope'的一堆记录,因此我知道这是一个有效的值。这样做的原因是什么,我该如何解决此行为?

=======

我可以看到两种方法:

1)将type设置为Restream::Periscope,而不仅仅是periscope。但这创建了记录,Restream::Periscope.find_eachRestream::Custom.find_each或SMTH无法找到记录,因为它将在其type列中使用periscope搜索记录,而不是Restream::Periscope

2)从restream_custom表中选择每种类型的customperiscope等记录,并为Periscopes而不是Restream::Custom创建Restream::Periscope,并在此处尝试提供正确的类型。但是我发现它有点毫无疑问,不干净和不必要,想知道我是否可以对此更加美丽。

如果它不太大的重构器,我会选择您的第一个选项1)将type设置为Restream::Periscope而不是periscope,而不是仅仅是因为它是Rails justmind。

如果实现了选项1),您说过您对此的其他担忧,即Restream::Periscope.find_each将不再返回其他"类型"的记录,并将根据子类自动进行相应的过滤...确实有意义,因为您.find_eachRestream::Periscope上查询,因此,我将期望所有返回的记录都将为type "Restream::Periscope"

是直观的。

现在,如果您想查询"所有类型",那么您可以在" parent"类上查询Restream::Service,现在可以进行以下操作:

Restream::Service.find_each(type: old_restream_custom.type)
# or
Restream::Service.create(type: old_restream_custom.type)

这是我的建议,除非当然这确实是重构所有代码的一项巨大任务。希望这有所帮助。

最新更新