我的创意工厂坏了(独特的标题验证)

时间:2012-12-27 18:30:08

标签: ruby-on-rails rspec factory-bot faker

这是FactoryGirl工厂:

FactoryGirl.define do
  factory :idea do
    title Faker::Lorem.sentence
    note Faker::Lorem.sentences(2)
    status "available"
  end
end

这是idea模型:

class Idea < ActiveRecord::Base
  attr_accessible :note, :status, :title
  validates :title,  presence: true, uniqueness: true, length: {minimum: 20}
  validates :status, presence: true, inclusion: {in: %w(pending available claimed overdue submitted aborted rejected)}
  belongs_to :user
end

现在,当我输入我的Rails控制台t1 = FactoryGirl.create(:idea)时,没问题,我明白了。但是当我输入t2 = FactoryGirl.create(:idea)时,它会崩溃,说验证失败了:ActiveRecord::RecordInvalid: Validation failed: Title has already been taken

事实上,我在SQL转储中看到FactoryGirl尝试使用相同的字符串两次:

1.9.3p327 :002 > t1 = FactoryGirl.create(:idea)
   (0.0ms)  begin transaction
  Idea Exists (1.8ms)  SELECT 1 AS one FROM "ideas" WHERE "ideas"."title" = 'Eligendi sint quod quia alias sed sit vitae repellendus.' LIMIT 1
  SQL (7.4ms)  INSERT INTO "ideas" ("created_at", "note", "status", "title", "updated_at", "user_id") VALUES (?, ?, ?, ?, ?, ?)  [["created_at", Thu, 27 Dec 2012 18:20:47 UTC +00:00], ["note", ["Aut placeat mollitia.", "Adipisci in est eos."]], ["status", "available"], ["title", "Eligendi sint quod quia alias sed sit vitae repellendus."], ["updated_at", Thu, 27 Dec 2012 18:20:47 UTC +00:00], ["user_id", nil]]
   (6.3ms)  commit transaction
 => #<Idea id: 1, title: "Eligendi sint quod quia alias sed sit vitae repelle...", note: ["Aut placeat mollitia.", "Adipisci in est eos."], status: "available", created_at: "2012-12-27 18:20:47", updated_at: "2012-12-27 18:20:47", user_id: nil> 
1.9.3p327 :003 > t2 = FactoryGirl.create(:idea)
   (0.1ms)  begin transaction
  Idea Exists (2.7ms)  SELECT 1 AS one FROM "ideas" WHERE "ideas"."title" = 'Eligendi sint quod quia alias sed sit vitae repellendus.' LIMIT 1
   (0.0ms)  rollback transaction
ActiveRecord::RecordInvalid: Validation failed: Title has already been taken

但是当我在控制台中反复运行Faker::Lorem.sentence时,我会随机获得不同的句子。

那么,为什么Faker和/或FactoryGirl决定使用相同的字符串,即使它应该是随机的呢?

1 个答案:

答案 0 :(得分:2)

您需要将对Faker的调用包装成一个块。

FactoryGirl.define do
  factory :idea do
    title { Faker::Lorem.sentence }
    note { Faker::Lorem.sentences(2) }
    status "available"
  end
end

如果不这样做,对句子方法的调用只发生一次,返回值设置为title / note。所以没有{}它实际上就像说:

title "some string"