LoginSignup
2
0

More than 3 years have passed since last update.

【Rails/一意性制約】モデルのバリデーションをコンソールで確認する方法/複数カラムへの一意性制約

Last updated at Posted at 2020-11-01

状況

  • userとroomを紐付けるpermissionsテーブル(部屋に入れる許可証を管理)を作成したい

  • references型でuser, taskをカラムにもつ

  • 既にテーブルに存在する(user_id, task_id)のセットが入力された際、保存しない制約

  • このバリデーションが正常に動作するかをコンソールで確認したい


「一意性制約」を使えば実現できるこちらのバリデーション。

今回はこれがちゃんと実装できているか、rails cで立ち上げたコンソールでの操作についての記録です。


環境

  • macOS Catalina 10.15.6

  • ruby 2.6.5

  • Rails 6.0.3.4

  • MySQL : 5.6.47


今回のコード

app/models/permission.rb

class Permission < ApplicationRecord
  belongs_to :user
  belongs_to :task

  validates :user_id, uniqueness: { scope: :task_id }
end


ちなみに、こちらはアプリ上での制約であり、正確にはDB側でも制約をかける必要があります (Railsガイドより)。
しかしまだ理解できていないので今回は省略します。



コンソールで入力したコマンド

一意性制約を確認したかったので、以下の流れでコードを実行していきました。

  • Permission.find(数字)で既存のレコードを取得

  • 適当な変数に代入する

  • valid?メソッドで保存可能か確認

  • "false"になると予想


ターミナルでコンソールを立ち上げて確認しました。

teminal
$ rails c

[1] > permission = Permission.find(1)
=> #<Permission:*** id: 1, user_id: 1, task_id: 1, ***>

[2] > new.valid?
=> true


trueになってしまいました…。
原因を考え、コマンドを変えてみました。


原因とコマンドの変更

【原因】
▶"find"は既存のレコードを探すActiveRecordメソッド
▶これを保存すると上書き保存みたいになる?

【変更】
▶user_id, task_idを直打ちする


terminal
$ rails c

[1] > Permission.find(1)
=> #<Permission:*** id: 1, user_id: 1, task_id: 1, ***>

[2] > permission = Permission.new(user_id: 1, task_id: 1)
=> #<Permission:*** id: nil, user_id: 1, task_id: 1, ***>

[3] > permission.valid?
=> false

[4] > permission.errors.full_messages
=> "User has already been taken"


これでしっかりfalseになることを確認できました。


まとめ

  • 複数キーの一意性制約はscopeオプションで指定できる

  • 確認のためには、新たにレコードを生成すること


少しハマってしまいましたがなんとか乗り越えました。
本当に理解するためには、saveやvalidの裏側で何が動いているかを知る必要がありそうですね。


まだまだ勉強することがいっぱいありますが、1つずつおさえていきます。


参照記事


2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0