LoginSignup
2
1

More than 5 years have passed since last update.

Railsのモデルバリデーションとカラム制約のユニークはどう挙動が変わるのか

Posted at

下記のモデルと対応するテーブル、3つずつ作成して実験しました。括弧内はカラムを表しています。

  • Post(title)
  • Tag(name)
  • PostTag(post_id, tag_id)

db/shema.rbにadd_index :tags, :name, unique: trueを追加して、モデルにバリデーションを追加すると、エラーのスタックトレースが表示されます。

Loading development environment (Rails 4.2.3)
irb(main):001:0> Tag.create(name: "tag1")
   (0.1ms)  begin transaction
  SQL (0.7ms)  INSERT INTO "tags" ("name", "created_at", "updated_at") VALUES (?, ?, ?)  [["name", "tag1"], ["created_at", "2015-10-05 04:56:25.110261"], ["updated_at", "2015-10-05 04:56:25.110261"]]
SQLite3::ConstraintException: UNIQUE constraint failed: tags.name: INSERT INTO "tags" ("name", "created_at", "updated_at") VALUES (?, ?, ?)
   (0.1ms)  rollback transaction
ActiveRecord::RecordNotUnique: SQLite3::ConstraintException: UNIQUE constraint failed: tags.name: INSERT INTO "tags" ("name", "created_at", "updated_at") VALUES (?, ?, ?)
    from /Users/mitsuru/.rbenv/versions/2.2.2/gemsets/vainglory/gems/sqlite3-1.3.10/lib/sqlite3/statement.rb:108:in `step'
\# ...省略
commands_tasks.rb:39:in `run_command!'
    from /Users/mitsuru/.rbenv/versions/2.2.2/gemsets/vainglory/gems/railties-4.2.3/lib/rails/commands.rb:17:in `<top (required)>'
    from bin/rails:4:in `require'
    from bin/rails:4:in `<main>'

次はsema.rbだけではなく、モデルにvalidates :name, uniqueness: trueを加えて試してみます。

irb(main):001:0> Tag.create(name: "tag1")
   (0.1ms)  begin transaction
  Tag Exists (0.2ms)  SELECT  1 AS one FROM "tags" WHERE "tags"."name" = 'tag1' LIMIT 1
   (0.1ms)  rollback transaction
=> #<Tag id: nil, name: "tag1", created_at: nil, updated_at: nil>

返り値がちゃんとありますね。これでRuby側のプログラムが止まらずに対処できるようになります。

2
1
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
1