Question

Here's a FactoryGirl factory:

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

And here's idea model:

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

Now, when I type into my Rails console t1 = FactoryGirl.create(:idea), no problem, I get an idea. But when I then type t2 = FactoryGirl.create(:idea) it crashes, saying that the validation fails: ActiveRecord::RecordInvalid: Validation failed: Title has already been taken

And indeed, I see in the SQL dump that FactoryGirl tried using the same exact string twice:

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

But when I repeatedly run Faker::Lorem.sentence in the console, I keep getting random, different sentences.

So, why does Faker and/or FactoryGirl decide to use the same exact string even though it's supposed to be random?

Was it helpful?

Solution

You need to wrap the call to Faker into a block.

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

If you don't, the call to the sentence method happens only once and the returned value is set as title/note. So without the {} it's actually the same as saying:

title "some string"
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top