0
0

More than 1 year has passed since last update.

FactoryBotでcreate(:client)時にActiveRecord::RecordNotUniqueが発生する

Posted at

コード

  • spec/models/client_spec.rb
require 'rails_helper'

RSpec.describe Client, type: :model do
  it "is valid with default" do
    client = FactoryBot.create(:client)
    expect(client).to be_valid
  end
end
  • spec/models/client_spec.rb
FactoryBot.define do
  factory :client do
    sequence(:id) { |n| n } # シーケンスを使う
    sequence(:name) { |n| "クライアント#{n}" }
    created_at { Time.current }
    updated_at { Time.current }
  end
end

概要

タイトルの通りだが、上記のコードでrspecを実行すると以下のエラーが発生する

Running via Spring preloader in process 160
F

Failures:

  1) Client is valid with default
     Failure/Error: client = FactoryBot.create(:client)

     ActiveRecord::RecordNotUnique:
       Mysql2::Error: Duplicate entry '1' for key 'clients.PRIMARY'
     # /usr/local/bundle/gems/mysql2-0.5.3/lib/mysql2/client.rb:131:in `_query'
     # /usr/local/bundle/gems/mysql2-0.5.3/lib/mysql2/client.rb:131:in `block in query'
     # /usr/local/bundle/gems/mysql2-0.5.3/lib/mysql2/client.rb:130:in `handle_interrupt'
     # /usr/local/bundle/gems/mysql2-0.5.3/lib/mysql2/client.rb:130:in `query'
     # /usr/local/bundle/gems/rack-mini-profiler-2.3.4/lib/patches/db/mysql2/alias_method.rb:22:in `query'
     # /usr/local/bundle/gems/factory_bot-6.2.1/lib/factory_bot/evaluation.rb:18:in `create'
     # /usr/local/bundle/gems/factory_bot-6.2.1/lib/factory_bot/strategy/create.rb:12:in `block in result'
     # /usr/local/bundle/gems/factory_bot-6.2.1/lib/factory_bot/strategy/create.rb:9:in `tap'
     # /usr/local/bundle/gems/factory_bot-6.2.1/lib/factory_bot/strategy/create.rb:9:in `result'
     # /usr/local/bundle/gems/factory_bot-6.2.1/lib/factory_bot/factory.rb:43:in `run'
     # /usr/local/bundle/gems/factory_bot-6.2.1/lib/factory_bot/factory_runner.rb:29:in `block in run'
     # /usr/local/bundle/gems/factory_bot-6.2.1/lib/factory_bot/factory_runner.rb:28:in `run'
     # /usr/local/bundle/gems/factory_bot-6.2.1/lib/factory_bot/strategy_syntax_method_registrar.rb:28:in `block in define_singular_strategy_method'
     # ./spec/models/client_spec.rb:5:in `block (2 levels) in <top (required)>'
     # ------------------
     # --- Caused by: ---
     # Mysql2::Error:
     #   Duplicate entry '1' for key 'clients.PRIMARY'
     #   /usr/local/bundle/gems/mysql2-0.5.3/lib/mysql2/client.rb:131:in `_query'

Finished in 0.06375 seconds (files took 4 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/models/client_spec.rb:4 # Client is valid with default

原因

  • Mysql2::Error: Duplicate entry '1' for key 'clients.PRIMARY' つまり、clientsのidが他のケースと重複しているため
  • FactoryBotのGitHubのページに以下のような記述があり、自分としてはFactoryBotはfixtureの代替であるため、fixtureの書き方を踏襲するものだと思った

factory_bot is a fixtures replacement
(訳: factory_bot はフィクスチャの代替品です。)

  • そのため spec/models/client_spec.rb にはidやcreated_at、updated_atといったDBで採番されるものをコードに書いていた。
  • しかしFactoryBotのWrong Wayとしても紹介されているが、独自SEQUENCE IDとして推奨されていない

対処

  • spec/models/client_spec.rbで独自SEQUENCE IDなコードを削除する
FactoryBot.define do
  factory :client do
    sequence(:name) { |n| "クライアント#{n}" }
  end
end
  • テストを実行し、passすることを確認
root@99008ab20f76:/app# rspec spec/models/client_spec.rb
Running via Spring preloader in process 181
.

Finished in 0.09304 seconds (files took 4.34 seconds to load)
1 example, 0 failures
0
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
0
0