8
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

railsの複合ユニーク制約をshoulda_matchersでテストする

Last updated at Posted at 2015-12-15

Railsのユニーク制約をshoulda-matchersを使ってテストしてみました。結果として、このマッチャーは複数カラムをまたいだ制約の時は使わない方がいい気がしました。1つのカラムでのユニーク制約も、複数カラムのユニーク制約も同じ扱いになっているようです。

ちなみに、undefined methodと表示される場合はshoulda-matchersのバージョンを2.8に落とすと直ります。3.0の不具合みたいです。

# 【環境】
# ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-darwin14]
# Rails 4.2.3
# rspec 3.3.2
# shoulda-matchers 2.8.0


# db/schema.rb
ActiveRecord::Schema.define(version: 20151012132542) do

  create_table "people", force: :cascade do |t|
    t.string   "first_name"
    t.string   "last_name"
    t.string   "sex"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  add_index "people", ["first_name", "last_name", "sex"], name: "index_people_on_first_name_and_last_name_and_sex", unique: true

end


# app/model/person.rb
class Person < ActiveRecord::Base
  # 下記3つ、どの書き方でもバリデートは成功。
  # 今回は、一番上を使用してテストを書き進めていきます。
  validates :first_name, uniqueness: { scope: [:last_name, :sex] }
  #validates :last_name, uniqueness: { scope: [:first_name, :sex] }
  #validates :sex, uniqueness: { scope: [:first_name, :last_name] }

  # scopeに渡すカラムが1つの場合は配列にはしません
  #validates :first_name, uniqueness: { scope: :last_name }
end


# spec/models/person_spec.rb
require 'rails_helper'
RSpec.describe Person, type: :model do
  it { is_expected.to validate_uniqueness_of(:first_name) } # true
  it { is_expected.to validate_uniqueness_of(:first_name).scoped_to(:last_name) } # true
  it { is_expected.to validate_uniqueness_of(:first_name).scoped_to(:sex) } # true
  it { is_expected.to validate_uniqueness_of(:first_name).scoped_to(:last_name, :sex) } # true

  # 下記のようなエラーがでる
  # Expected errors to include "has already been taken" when sex is set to "a", got no errors
  it { is_expected.to validate_uniqueness_of(:last_name) } # false
  it { is_expected.to validate_uniqueness_of(:last_name).scoped_to(:first_name, :sex) } # false
  it { is_expected.to validate_uniqueness_of(:sex) } # false
end
8
4
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
8
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?