中村的雑記

技術に関する記事を書いていきます。iOSエンジニア->Railsエンジニア。

Rails1週目: modelの設計、複合ユニークのテストetc

はじめに

8/3 ~ 8/7に経験した内容をまとめる。Railsを触り始めて初週だったのもあって、インプットメインという感じだったが、助けを借りながらモデルを二つ実装した。
そのなかでも、validation、複合ユニークのテスト(RSpec)の書き方など、今後のために覚えておきたいことを殴りがいておく。
モデル名とかカラム名は適当にぼやかしてかいている。
もし間違いなどがあれば指摘していただけると嬉しい。

model作成のコマンド

今回作成したmodelでは外部キー(ForeignKey)の設定が必要だったのでreferencesを使った。

rails g model Stock company:references price:integer month:integer day:integer

最初accountのところをcompany_id:referenceとやってうまくいかなかった。
_idをつけなくても上記コマンドを打てばカラムにcompany_idが入る仕様になっているようだ。

複合ユニーク

migrationファイルに下記を実装する。

add_index :stocks, [:company_id, :month, :day], unique: true

modelのユニークの設計1

最初price含めてユニークにしまっていたのだが、
「それだと間違って二回集計されたときに金額が違うと、二重でレコードができてしまう」 というのをレビューで言われ、なるほどなーとなった。

ちなみに一回rails db:migrateした後、migrationファイルを編集したら、

rails db:migrate:reset

このコマンドを打てばよい。 ただ、masterにマージされているモデルの編集の場合は、migrationコマンドでファイルを使って、それを使って編集していく。

migrationが終わったら、モデルファイルに下記のようにvalidationを実装する。

validates :company_id, uniqueness: { scope: %i[month day] }

modelのユニークの設計2

今回はpay_idとpay_history_idをFKとして中間テーブルを作ったのですが、
最初はこの二つに複合ユニークを貼ってたのですが

「「一つの集計に同じpay_idが複数回ふくまれない事」が保証できてるとおもうので、
「同じpay_idがが複数回他の集計に含まれない事」を保証するために pay_id 自体もUniqueインデックスをはってください」 とレビューで指摘された。

これもなるほどな、となった。 modelにvalidates :pay_id, uniqueness: trueを実装した。 今後こういう設計をするときユニークをうまく実装できるようにしたい。

複合ユニークのテスト(RSpec)

上記の中間テーブルの中の複合ユニークをテストの実装をした。
こういう時はユニークにならないようにcreatebuildをしてfalseになるようにする。

let!(:pay)  { create(:pay) }
let!(:pay_history) { create(:pay_history) }

it 'should be false with non unique index pay_id and pay_history_id' do
      create(:pay_year, pay: pay, pay_history: pay_history)
      invalid_pay_year = build(:pay_year,
                                             pay: pay,
                                             pay_history: pay_history)
      expect(invalid_payslip_delivery_entry.valid?).to be false
end

来週に向けて

これを進めておく。