Search code examples
ruby-on-railsdeviseassociationsfactory-botmodels

after association between two models error on a third : ActiveRecord::RecordInvalid: Validation failed: Email has already been taken


I just concluded this model associations between users (using devise to manage users), wall and posts. Before I tried the user and wall association the following error didn't exist. The output failure is:

Post
  Scopes
    .most_recent
      returns all posts ordered from the youngest to the oldest (FAILED - 1)

Failures:

  1) Post Scopes .most_recent returns all posts ordered from the youngest to the oldest
     Failure/Error: let!(:post) { create(:post, created_at: Date.today) }
     ActiveRecord::RecordInvalid:
       Validation failed: Email has already been taken
     # ./spec/models/post_spec.rb:16:in `block (3 levels) in <top (required)>'
     # -e:1:in `<main>'

Failed examples:

rspec ./spec/models/post_spec.rb:20 # Post Scopes .most_recent returns all posts ordered from the youngest to the oldest

My models:

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  # Associations
  has_one :wall, dependent: :destroy
end


class Wall < ActiveRecord::Base
  # Associations
  has_many :posts, dependent: :destroy
  belongs_to :user

  # Validations
  validates :user, presence: true
end


class Post < ActiveRecord::Base
  # Associations
  belongs_to :wall

  # Scopes
  scope :most_recent, -> { order(created_at: :desc) }

  # Validations
  validates :content, :wall, presence: true
end

My post_spec:

require 'rails_helper'

RSpec.describe Post, type: :model do
  let(:post) { build(:post) }

  describe 'Validations' do
    it 'has a valid factory' do
      expect(post).to be_valid
    end

    it { should validate_presence_of(:content) }
  end

  describe "Scopes" do
    let!(:older_post) { create(:post, created_at: Date.today - 2.month) }
    let!(:post) { create(:post, created_at: Date.today) }


    describe ".most_recent" do
      it "returns all posts ordered from the youngest to the oldest" do
        expect(Post.most_recent.first).to eq(post)
        expect(Post.most_recent.last).to eq(older_post)
      end
    end
  end
end

My post factory:

FactoryGirl.define do
  factory :post do
    content 'post text'
    wall
  end
end

any hint?


Solution

  • This is just a guess, but your User factory probably isn't generating unique email addresses. FactoryGirl lets you define a sequence, which will ensure uniqueness validation for your test users:

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

    You can read more in the documentation here: http://www.rubydoc.info/gems/factory_girl/file/GETTING_STARTED.md#Sequences