Rails5+複合主キーでやっていくにはcomposite_primarykeyが必要ですが
テストコードを書く際にハマったのでその時のメモを残しておきます
FactoryBotでテストデータを作成する際の話です
composite_prrimarykeyを使ってreports
テーブルを複合主キーで扱うことにしています
- migrate
def change create_table :reports, primary_key: ['id', 'date'] do |t| t.bigint :id, null: false, auto_increment: true t.date :date, null: false t.integer :hoge, null: true t.timestamps end end
- app/models/report.rb
modelで明示的に主キーをid
,date
と指定しています
class Report < ApplicationRecord self.primary_keys = :id, :date end
- spec/factories/report.rb
テスト用のデータ部分を記述します
FactoryBot.define do factory :report do sequence(:id) {|n| n} sequence(:date) {|n| Date.today.subtract } .... .... .... .... end end
- spec/models/report_spec.rb
簡単なテストコードを書いてみます
RSpec.describe Report, type: :model do describe 'sample' do before(:each) do FactoryBot.create_list(:report, 2) end context 'hoge' do it do expect(Report.all.size).to eq(2) end end end end
実行するとエラーが出ます
Failures: 1) Report sample hoge Failure/Error: let(:row) { FactoryBot.create(:report) } ArgumentError: Unsupported type: 1
簡単に抜粋だけしましたがこれだと上記エラーが出てきます
ただArgumentError: Unsupported type:
しかでてきません
ソース追ってみると該当箇所の主キーの渡し方が違うようです
def self.parse(value) case value when Array value.to_composite_keys when String self.new(value.split(ID_SEP)) else raise(ArgumentError, "Unsupported type: #{value}") end end
このparseはArrayかStringしか受け付けないようになっています
なので配列で渡すか、1,2
というふうに区切り文字で区切って渡す方法が用意されているようです
それに対応させて渡してあげれば良いわけですね
今回はid
をid,dateで指定しているので同じようにテストデータ作成時もidに対して渡して上げる必要があるようです
後でREADME見てみたら普通にのっていたのでちゃんと読めって話ではあるのですがいつもパーティションはった複合主キーのテーブルに対してはactiverecord-import
でしかデータ入れてなかったためちょっとはまりました
なのでこんな感じでデータを作ってあげるようにすれば良い感じです
- spec/factories/report.rb
sequence(:id) {|n| [n, Date.today]}
おわり