Railsでseed_fuとclosure_treeを同時に使って困ったこと
Rails6で以下gemを使って初期データ投入しようとしたら困った事になったのでメモ
seed_fu
https://github.com/mbleigh/seed-fu Railsの初期seedより気の利いた初期データ投入ができるgem
closure_tree
https://github.com/ClosureTree/closure_tree
閉包テーブルを実現できるgem
問題1:superclass mismatch for class〜って怒られる
seed_fuでclosure_tree使ったmodelのデータ生成しようとしたら以下のメッセージで怒られた
TypeError: superclass mismatch for class FolderPath
例として、フォルダの階層構造を実現するという事で。
階層にしたいモデルは以下の通り。
class Folder < ApplicationRecord
validates :name,
:summary,
presence: true
has_closure_tree dependent: :nullify,
hierarchy_table_name: 'folder_paths',
hierarchy_class_name: 'FolderPath'
end
ここのhas_closure_treeの設定で怒られてる。
FolderPathモデルはこんな感じ
class FolderPath < ApplicationRecord
belongs_to :ancestor
belongs_to :descendant
end
しかしclosure_treeの中では(lib/closure_tree/support.rb)
hierarchy_class = parent_class.const_set(short_hierarchy_class_name, Class.new(ActiveRecord::Base))
男気あふれるモデル動的生成をしているのだった
つまりわざわざFolderPathというモデルのファイルは作らなくていいのだ
hierarchy_class_nameはどんなモデルのクラス名にするか聞いてるだけで、別に明示的にモデル作らなくてよかったんだ。
そしてもしFolderPathモデルを書いてみるとなると、こうなる。
ApplicationRecordじゃなくてActiveRecord::Baseを継承する。
class FolderPath <ApplicationRecord ActiveRecord::Base
belongs_to :ancestor
belongs_to :descendant
end
問題2:seed_fuでclosure_tree使ったmodelのデータ生成したら、modelのデータ自体は保存されてたけどclosure_treeのpathデータが保存されてない
Folderのデータを保存したらFolderPathに階層データが保存されてほしい。だってclosure_treeだもん。
しかし階層データが保存されてなくてとっても謎。consoleから保存した時はちゃんとpathデータ保存されていたので、設定ミスとかじゃなさそうな事はわかった。
seed_fuの中はこんな感じに書いている
Folder.seed(
[
{
id: 1,
name: 'folder1'
},{
id: 2,
name: 'folder2'
},
]
)
そうです、さきほどのFolderモデルの設定ファイルをみたらお分かりの通り、必須項目が足りないではないですか。
なぜ必須項目なのにエラーも出さずにそのまま保存できちゃうかっていうと
seed_fuの中身を見てみると、/seed-fu/lib/seed-fu/seeder.rbの中で以下のような処理をしているよ。
record.save(:validate => false) || raise(ActiveRecord::RecordNotSaved, 'Record not saved!')
というわけで、validationをオフにして保存しています。
細かいところ見てないので推測だけど、validation通過後に保存するはずだったclosure_treeのpathデータが保存されてなかった的な事なんじゃないだろうか。
こちら必須項目を追加したら問題なくpathデータも保存されました。やったね。