【问题标题】:I can't create object with FactoryGirl.create, validation failed User has already been taken我无法使用 FactoryGirl.create 创建对象,验证失败 用户已被占用
【发布时间】:2015-12-09 02:27:30
【问题描述】:

我正在尝试使用 gem FactoryGirl 创建一个平衡对象,但是当我打开 Rails 控制台并编写命令 FactoryGirl.create(:balance) 时出现错误。

我在我的模型之间创建关联 has_one 和 belongs_to,此外还为外部字段中的唯一键添加验证,这些是我的模型。

余额

class Balance < ActiveRecord::Base
  #association macros
  belongs_to :user
  belongs_to :wallet

  #validation macros
  validates :user_id, presence: true, uniqueness: true
  validates :wallet_id, presence: true, uniqueness: true
end

钱包

class Wallet < ActiveRecord::Base
  #association macros
  belongs_to :user
  belongs_to :wallet_type
  has_one :bank_account, dependent: :destroy
  has_one :debit_card, dependent: :destroy
  has_one :credit_card, dependent: :destroy
  has_one :balance, dependent: :destroy

  #validation macros
  validates :user_id, presence: true
  validates :wallet_type_id, presence: true

end

用户

class User < ActiveRecord::Base
  #association macros  
  ...
  has_one :salt
  has_one :balance

end

工厂平衡

FactoryGirl.define do
  factory :balance do
    user
    wallet
    amount 2000
  end
end

我的平衡测试

RSpec.describe @Balance, type: :model do

  describe "Balance" do

    before(:each) do
      @user = FactoryGirl.create(:user)
      @wallet = FactoryGirl.create(:wallet)
      @balance = FactoryGirl.create(:balance, user_id: @user[:id], wallet_id: @wallet[:id])
    end

    it "when is valid" do
      expect(@balance).to be_valid
    end

    it "when is presence user_id" do
      expect(@balance).to validate_presence_of :user_id
    end

    it "when is presence wallet_id" do
      expect(@balance).to validate_presence_of :wallet_id
    end

    pending "when is uniqueness user_id" do
      expect(@balance).to validate_uniqueness_of :user_id
    end

    pending "when is uniqueness wallet_id" do
      expect(@balance).to validate_uniqueness_of :wallet_id
    end

    it "when is belongs_to :user" do
      should belong_to(:user)
    end

    it "when is belongs_to :wallet" do
      should belong_to(:wallet)
    end

  end

end

当我创建余额对象FactoryGirl.create(:balance) 时,出现以下错误。

ActiveRecord::RecordInvalid: Validation failed: User has already been taken
    from .../lib/active_record/validations.rb:79:in `raise_record_invalid'
    from .../lib/active_record/validations.rb:43:in `save!'
    from .../lib/active_record/attribute_methods/dirty.rb:29:in `save!'
    from .../lib/active_record/transactions.rb:291:in `block in save!'
    from .../lib/active_record/transactions.rb:351:in `block in with_transaction_returning_status'
    from .../lib/active_record/connection_adapters/abstract/database_statements.rb:213:in `block in transaction'
    from .../lib/active_record/connection_adapters/abstract/transaction.rb:184:in `within_new_transaction'
    from .../lib/active_record/connection_adapters/abstract/database_statements.rb:213:in `transaction'
    from .../lib/active_record/transactions.rb:220:in `transaction'
    from .../lib/active_record/transactions.rb:348:in `with_transaction_returning_status'
    from .../lib/active_record/transactions.rb:291:in `save!'
    from .../lib/factory_girl/configuration.rb:14:in `block in initialize'
    from .../lib/factory_girl/evaluation.rb:15:in `[]'
    from .../lib/factory_girl/evaluation.rb:15:in `create'
    from .../lib/factory_girl/strategy/create.rb:12:in `block in result'
    from .../lib/factory_girl/strategy/create.rb:9:in `tap'
    from .../lib/factory_girl/strategy/create.rb:9:in `result'
    from .../lib/factory_girl/factory.rb:42:in `run'
    from .../lib/factory_girl/factory_runner.rb:23:in `block in run'
    from .../lib/active_support/notifications.rb:166:in `instrument'
    from .../lib/factory_girl/factory_runner.rb:22:in `run'
    from .../lib/factory_girl/strategy_syntax_method_registrar.rb:20:in `block in define_singular_strategy_method'
    from (irb):1
    from .../lib/rails/commands/console.rb:110:in `start'
    from .../lib/rails/commands/console.rb:9:in `start'
    from .../lib/rails/commands/commands_tasks.rb:68:in `console'
    from .../lib/rails/commands/commands_tasks.rb:39:in `run_command!'
    from ..lib/rails/commands.rb:17:in `<top (required)>'
    from bin/rails:4:in `require'
    from bin/rails:4:in `<main>'irb(main):002:0> a= FactoryGirl.create(:balance)

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-4 rspec rspec-rails


    【解决方案1】:

    问题

    您在运行测试时看到此错误:

    ActiveRecord::RecordInvalid: Validation failed: User has already been taken
    

    因为您在之前的任何测试运行中都创建了该用户。所以,它得到了验证错误。

    解决方案

    您可以使用database_cleaner gem,这将确保您运行测试的测试数据库处于干净状态。

    您可以通过将其添加到您的 Gemfile 来安装 gem:

    group :test do
      gem 'database_cleaner'
    end
    

    然后,运行:

    bundle install
    

    之后,在您的spec_helper.rb 中配置database_cleaner

    RSpec.configure do |config|
      config.before(:suite) do
        DatabaseCleaner.strategy = :transaction
        DatabaseCleaner.clean_with(:truncation)
      end
    
      config.before(:each) do
        DatabaseCleaner.start
      end
    
      config.after(:each) do
        DatabaseCleaner.clean
      end
    end
    

    此配置将确保上次测试运行的数据在每个规范之后都会被截断。而且,每次运行新规范时,都是针对干净的数据库进行的。

    您可以从 gem 的 documentation 页面查看如何使用 RSpec 配置 database_cleaner

    【讨论】:

    • 我知道了,但是我无法删除的表会发生什么,因为这些表有数据种子。 Databasecleaner 删除了所有表中的所有数据。
    • database_cleaner 适用于您的测试数据库。但是,我认为您需要开发数据库的种子数据。所以,这两者不应该冲突。
    • 好吧,在我的情况下,我在测试数据库中使用了种子数据,因为我有一个带有类型的表并且其他表与之有关系,那么没有种子我无法运行所有测试,我想所以我接近解决方案,但我需要在无法删除的 database_cleaner 表中进行配置,然后将表添加为 wallet_type、event_status、notification_type。如果你知道怎么做?
    • 好吧,我尝试在before.config(:each) 中使用Rails.application.load_seed 不起作用,我发现database_cleaner DatabaseCleaner.clean_with(:truncation, except:%w[wallet_types event_statuses notification_types friendship_statuses participant_roles activity_types transaction_types] ) 的这个配置并且这些表没有清理,但是麻烦继续User has already been taken
    • 我收到错误,在模型 User 我有一个回调 after_create :create_account_balance 然后当我使用 user_id 创建余额时,错误触发器因为所有用户在我的那一刻都有余额创建一个。我修复了我的所有测试,感谢您的时间。
    猜你喜欢
    • 1970-01-01
    • 2015-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-13
    • 1970-01-01
    • 1970-01-01
    • 2020-12-19
    相关资源
    最近更新 更多