首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >带有rake任务和自定义STI名称的无效单表继承类型

带有rake任务和自定义STI名称的无效单表继承类型
EN

Stack Overflow用户
提问于 2017-08-30 17:21:28
回答 1查看 490关注 0票数 0

我做了大量的代码重构工作,还对db模式做了很大的更改。现在,我正在尝试编写一个rake任务,以便将记录从旧表迁移到新表。

我正在上这样的课:

代码语言:javascript
复制
#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

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

代码语言:javascript
复制
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表中获取所有记录,只需复制类型即可。大致如下:

代码语言:javascript
复制
Restream::Custom.create(type: old_restream_custom.type)

但这并没有说:

代码语言:javascript
复制
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找不到的,也不是这样的,因为它将在type列中搜索periscope记录,而不是Restream::Periscope

2)只从restream_custom表中选择每种类型的customperiscope等的记录,并为望远镜创建Restream::Periscope,而不是Restream::Custom,并试图在这里提供正确的类型。但是我发现它有点不漂亮,不干燥,也没有必要,我想知道我能不能用它来做更漂亮的事。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-08-30 18:54:06

如果它不是太大的重构,我将与您的第一个选择1)设置typeRestream::Periscope,而不是periscope,主要是因为它是Rails公约

如果实现了选项1),您还提到了对此的另一个关注,即Restream::Periscope.find_each将不再返回其他“类型”的记录,并将根据子类的不同自动过滤.这样做是有意义的,因为您的.find_each正在查询Restream::Periscope,因此我很直观地认为所有返回的记录都是type "Restream::Periscope"的。

现在,如果您想查询“所有类型”,那么只需查询“父”类(即Restream::Service ),在该类中您现在可以执行以下操作:

代码语言:javascript
复制
Restream::Service.find_each(type: old_restream_custom.type)
# or
Restream::Service.create(type: old_restream_custom.type)

这是我的建议,除非这确实是一个很大的任务,重构您的所有代码。希望这能有所帮助。

票数 -2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45966336

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档