RankedModelをSTIで使う時にハマった
Rails 4で作るドラッグアンドドロップで表示順を変更できるサンプルアプリ(スクリーンキャスト付き)などで有名なRankedModel。 RankedModelを知ってから、順序を指定するようなモデルではRankedModelを利用しています。
本日はRankedModelをSTIを利用したとき、順番が意図した通りにならずハマったので共有します。
何が起きたのか?
RankedModelでは作成した順番に並ぶようにデータが作成されていきますが、STIを利用したときに上手く行きませんでした。 下の例では、car1、car2、truck1、truck2と並んで欲しいところです。 どうやらモデルごとに値を決めているようです。
class Vehicle < ActiveRecord::Base ranks :row_order end class Car < Vehicle end class Truck < Vehicle end Car.create!(name: :car1) Car.create!(name: :car2) Truck.create!(name: :truck1) Truck.create!(name: :truck2) Vehicle.rank(:row_order).pluck(:name) #=> ["car1", "truck1", "car2", "truck2"] ( ゚∋゚)
解決策
ranksメソッドの第二引数にオプションとしてclass_nameを渡せば解決します。
よく見たらGithubに書いてありました。
class Vehicle < ActiveRecord::Base ranks :row_order, class_name: 'Vehicle' end class Car < Vehicle end class Truck < Vehicle end Car.create!(name: :car1) Car.create!(name: :car2) Truck.create!(name: :truck1) Truck.create!(name: :truck2) Vehicle.rank(:row_order).pluck(:name) #=> ["car1", "car2", "truck1", "truck2"]
解決策に至るまでに考えたこと
- データを投入したあとにupdate_columnで値を更新する
Car.create!(name: :car1) Car.create!(name: :car2) Truck.create!(name: :truck1) Truck.create!(name: :truck2) Vehicle.rank(:row_order).each.with_index { |v, i| v.update_column(:row_order, i + 1) } # => rankした時点でcar1、truck1、car2、truck2の順番に並ぶため、無意味。この時点ではモデルごとに値を決めていることに気づいていなかった