ActiveRecord :: RecordInvalid因为必须是唯一的字段,尽管使用了该字段的序列

时间:2012-10-24 07:33:55

标签: ruby-on-rails activerecord factory-bot

美好的一天。我收到此错误

1) Subscription 
     Failure/Error: @subscription = FactoryGirl.create(:subscription)
     ActiveRecord::RecordInvalid:
       Encountered errors: Email already exists, Login already exists

虽然在FactoryGirl中我指定了这些字段的唯一性^

要求工厂女孩

@subscription = FactoryGirl.create(:subscription)

build无法实现,因为

  

应该validate_uniqueness_of(:category_id).scoped_to(:user_id)

工厂:

factory :subscription do
    association :category, factory: :advt_category 
    user
  end
factory :user do
    sequence(:login) { |n| "user__#{n}"  } 
    password "password"
    sequence(:email) { |n| "example__#{n}@example.com"}  
end

如何解决此错误?为什么会出现?

更新

我最终销毁了此规范中用户模型的所有记录

before do
User.destroy_all
end

2 个答案:

答案 0 :(得分:4)

最有可能的问题是,当您启动规范时,您的测试数据库不干净。当rspec过早退出或被杀死时,就会发生这种情况。

您使用before { User.destroy_all }的方法有效,但是很繁琐(因为您可能需要将其添加到其他规范中),并且速度很慢。

我建议你使用database_cleaner gem并像这样扩展你的rspec配置:

RSpec.configure do |config|
  config.use_transactional_fixtures = false

  config.before :suite do
    DatabaseCleaner.strategy = :transaction
    DatabaseCleaner.clean_with :truncation
  end

  config.before(:each) { DatabaseCleaner.start }
  config.after(:each)  { DatabaseCleaner.clean }
end

当您使用Capybara作为请求规范时,请将before :each块更改为:

config.before :each do
  if Capybara.current_driver == :rack_test
    DatabaseCleaner.strategy = :transaction
  else
    DatabaseCleaner.strategy = :truncation
  end

  DatabaseCleaner.start
end

答案 1 :(得分:0)

我认为这会起作用

为用户调用FactoryGirl并将其传递给订阅调用

@user = FactoryGirl.create(:user) 
@subscription = FactoryGirl.create(:subscription, :user_id => @user.id)

至于为什么会发生这种情况,我们需要看到更多的规范