rails factory girl getting "Email has already been taken"
Asked Answered
A

6

16

This is my factory girl code, and every time I try to generate a review, it's telling me that "Email has already been taken", i've reset my databases, set the transition in spec_helper to true, but still haven't solved the problem. I'm new to this, am I using the association wrong? Thanks!

Factory.define :user do |user|
  user.name                  "Testing User"
  user.email                 "[email protected]"
  user.password              "foobar"
  user.password_confirmation "foobar"
end

Factory.define :course do |course|
  course.title "course"
  course.link "www.umn.edu"
  course.sections 21
  course.description "test course description"
  course.association :user
end

Factory.define :review do |review|
  review.title "Test Review"
  review.content "Test review content"
  review.association :user
  review.association :course
end
Aluminous answered 5/4, 2011 at 5:46 Comment(0)
T
11

You need to use a sequence to prevent the creation of user objects with the same email, since you must have a validation for the uniqueness of emails in your User model.

Factory.sequence :email do |n|
  “test#{n}@example.com”
end

Factory.define :user do |user|
  user.name "Testing User"
  user.email { Factory.next(:email) }
  user.password "foobar"
  user.password_confirmation "foobar"
end

You can read more in the Factory Girl documentation.

Tonettetoney answered 5/4, 2011 at 5:50 Comment(0)
H
36

I know this is a pretty old question, but the accepted answer is out of date, so I figured I should post the new way of doing this.

FactoryGirl.define do
  sequence :email do |n|
    "email#{n}@factory.com"
  end

  factory :user do
    email
    password "foobar"
    password_confirmation "foobar"
  end
end

Source: Documentation

It's quite a bit simpler, which is nice.

Heavyfooted answered 7/10, 2013 at 22:53 Comment(0)
T
11

You need to use a sequence to prevent the creation of user objects with the same email, since you must have a validation for the uniqueness of emails in your User model.

Factory.sequence :email do |n|
  “test#{n}@example.com”
end

Factory.define :user do |user|
  user.name "Testing User"
  user.email { Factory.next(:email) }
  user.password "foobar"
  user.password_confirmation "foobar"
end

You can read more in the Factory Girl documentation.

Tonettetoney answered 5/4, 2011 at 5:50 Comment(0)
K
8

In addition to the above answers you could add gem 'faker' to your Gemfile and it will provide unique emails.

FactoryGirl.define do
  factory :admin do
    association :band
    email { Faker::Internet.email }
    password "asdfasdf"
    password_confirmation "asdfasdf"
  end
end
Kurtzig answered 1/7, 2016 at 15:2 Comment(1)
Here the important detail is to put the Faker generator into brackets{ } like in the example email { Faker::Internet.email } as it will not work without them and will raise the same error.Flowerlike
S
5

sequence gives really unique email and Faker gives random password.

FactoryGirl.define do
  sequence :email do |n|
    "user#{n}@test.com"
  end

  factory :user do
    email
    password { Faker::Internet.password(min_length: 8, max_length:20) }
    password_confirmation { "#{password}" }
  end
end
Stinkhorn answered 28/3, 2017 at 8:14 Comment(0)
T
1
  1. You need to add a sequence
  2. (optional) If you are often executing the factory in rails console you can add some randomness Random.hex(4) otherwise you will run into the same problem.
FactoryBot.define do
  factory :user do
    sequence(:email) do |index|
      "test_#{Random.hex(4)}#{index}@fake-domain.xyx"
    end
  end
end
Tavy answered 22/3, 2023 at 8:6 Comment(0)
S
0

For some reason the password_confirmation field wasn't working for me. What worked was this:

FactoryBot.define do

  sequence :email do |n|
    "user#{n}@test.com"
  end

  factory :user do
    email
    password { Faker::Internet.password(min_length: 8, max_length:20) }
    confirmed_at { Time.current } # <---- This worked for me
  end
end

Note that if you're not using Faker, you can have something as simple as `password { "password" } instead of that line.

Sourwood answered 23/7, 2022 at 16:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.