大量のコードをリファクタリングし、dbスキーマを大きく変更しました。そして今、古いテーブルのレコードを新しいテーブルに移行するためのレーキタスクを作成しようとしています。rakeタスクとカスタムSTI名で無効な単一テーブル継承タイプ
私はこのようなクラスを持っています:
#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'
のレコードを持っているので、それが有効な値であることが分かります。 これはどのような理由があり、この問題を解決するにはどうすればよいですか?
======
私は2つの方法で見ることができます:
1)だけperiscope
、Restream::Periscope
にtype
を設定されていません。しかし、それはRestream::Periscope.find_each
またはRestream::Custom.find_each
またはそのようなsmthで見つけることができないレコードを作成します。Restream::Periscope
ではなく、type
の列にperiscope
のレコードを検索するためです。
2)restream_custom
テーブルからなどcustom
、periscope
、それぞれのタイプのレコードだけを選択し、潜望鏡のためRestream::Periscope
、ないRestream::Custom
を作成し、ここに正しい型を提供しようとしています。しかし、私はそれが未知の、乾燥していない、そして不必要なものであることを発見し、私がそれでより美しいものをすることができるかどうか疑問に思います。
私はこれで終わると思います。しかし、私が本当に知りたかったことは、あなたが知っている... "賢い"ことです。 ActiveRecordがこれらが有効で、エラーを発生させないようにするために、クラスからロードする方法についての何か。私はそれを使うべき場所ではないかもしれませんが、私は本当にそれに興味があります。 – Ngoral
Railsは、 'Restream :: Periscope'が' Another'Namespace :: Periscopeとは別の名前空間を適切に扱うので、 'type'の値として文字列定数すなわち' Restream :: Periscope'を使用していると思います'。これはおそらく、Railsが関係する限り、これが実際に実際にどのようなサブクラスであるかをまだ知ることのできない「潜望鏡」を識別するための「魔法の」ソリューションを持っていない理由です。しかし、私は限られた知識しか持っていません。おそらく私は何かを欠けているだけかもしれません。 –
はい、私は何とかそれがそうしている理由を何とか理解しています。しかし、 'self.sti_name'を使うと、rails appを走らせている間に何かの理由で無視します。 – Ngoral