我做了一项重构的大量代码,还对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_each
或Restream::Custom.find_each
或SMTH无法找到记录,因为它将在其type
列中使用periscope
搜索记录,而不是Restream::Periscope
。
2)从restream_custom
表中选择每种类型的custom
,periscope
等记录,并为Periscopes而不是Restream::Custom
创建Restream::Periscope
,并在此处尝试提供正确的类型。但是我发现它有点毫无疑问,不干净和不必要,想知道我是否可以对此更加美丽。
如果它不太大的重构器,我会选择您的第一个选项1)将type
设置为Restream::Periscope
而不是periscope
,而不是仅仅是因为它是Rails justmind。
如果实现了选项1),您说过您对此的其他担忧,即Restream::Periscope.find_each
将不再返回其他"类型"的记录,并将根据子类自动进行相应的过滤...确实有意义,因为您.find_each
在Restream::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)
这是我的建议,除非当然这确实是重构所有代码的一项巨大任务。希望这有所帮助。