具有 rake 任务和自定义 STI 名称的无效单 table 继承类型
Invalid single-table inheritance type with rake task and custom STI names
我重构了大量代码,并对数据库架构进行了重大更改。现在我正在尝试编写一个 rake 任务以将记录从旧 table 迁移到新记录。
我有这样的 类:
#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
table 获取所有记录,然后只是复制类型。大致:
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
或类似的东西找到的记录,因为它会在其 type
列中搜索带有 periscope
的记录,不是 Restream::Periscope
.
2) Select from restream_custom
table 仅记录 custom
、periscope
等各类型,并创建 Restream::Periscope
对于潜望镜,不是 Restream::Custom
并尝试在此处提供正确的类型。但我发现它有点不漂亮,不干而且没有必要,想知道我是否可以用它做得更漂亮。
如果重构不是太大,我会选择你的第一个选项 1) 将 type
设置为 Restream::Periscope
而不是 periscope
主要是因为它是Rails convention.
如果选项 1) 被实施,你说了你对此的另一个担忧,即 Restream::Periscope.find_each
将不再 return 其他 "types" 的记录,并将相应地自动过滤取决于 subclass... 确实有意义,因为您的 .find_each
正在查询 Restream::Periscope
,因此很直观我会期望所有 return ed 记录将是 type
"Restream::Periscope"
.
现在,如果您想查询 "all types",那么您可以只查询 "parent" class,也就是 Restream::Service
,您可以在其中查询现在执行以下操作:
Restream::Service.find_each(type: old_restream_custom.type)
# or
Restream::Service.create(type: old_restream_custom.type)
这是我的建议,除非重构所有代码确实是一项艰巨的任务。希望这能有所帮助。
我重构了大量代码,并对数据库架构进行了重大更改。现在我正在尝试编写一个 rake 任务以将记录从旧 table 迁移到新记录。
我有这样的 类:
#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
table 获取所有记录,然后只是复制类型。大致:
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
或类似的东西找到的记录,因为它会在其 type
列中搜索带有 periscope
的记录,不是 Restream::Periscope
.
2) Select from restream_custom
table 仅记录 custom
、periscope
等各类型,并创建 Restream::Periscope
对于潜望镜,不是 Restream::Custom
并尝试在此处提供正确的类型。但我发现它有点不漂亮,不干而且没有必要,想知道我是否可以用它做得更漂亮。
如果重构不是太大,我会选择你的第一个选项 1) 将 type
设置为 Restream::Periscope
而不是 periscope
主要是因为它是Rails convention.
如果选项 1) 被实施,你说了你对此的另一个担忧,即 Restream::Periscope.find_each
将不再 return 其他 "types" 的记录,并将相应地自动过滤取决于 subclass... 确实有意义,因为您的 .find_each
正在查询 Restream::Periscope
,因此很直观我会期望所有 return ed 记录将是 type
"Restream::Periscope"
.
现在,如果您想查询 "all types",那么您可以只查询 "parent" class,也就是 Restream::Service
,您可以在其中查询现在执行以下操作:
Restream::Service.find_each(type: old_restream_custom.type)
# or
Restream::Service.create(type: old_restream_custom.type)
这是我的建议,除非重构所有代码确实是一项艰巨的任务。希望这能有所帮助。