THpubs
THpubs

Reputation: 8172

In Rails Factory Girl is creating duplicate records

When I run rspec, sometimes all tests pass. But occasionally it give failures. It say Validation failed: Nyaaid has already been taken. It looks like Factory girl is creating duplicate entries occasionally.

Here's my Factory Girl code :

factory :awardunit do
    sequence(:name)  { |n| "Person #{n}" }
    nyaaid { "NYAA/N/WP#{ [1,1,1,1].map!{|x| (3..9).to_a.sample}.join }" }
    address "Example Address"
    district "Colombo"
    contact ["23232223"]
    sequence(:email) { |n| "person_#{n}@example.com"}
    insthead "Example Person"
    instheadcontact ["232324223"]
    datestarted "2013-08-04"
    allowedmem 8
    remarks "No"
    disabled false
end

Here's my tests :

    ### Award Unit List

    describe "pagination" do

      before(:all) do 
        30.times { FactoryGirl.create(:awardunit) }
        visit awardunits_path
      end
      after(:all)  { Awardunit.delete_all }

      it { should have_selector('div.pagination') }

      it "should list each awardunit" do
        Awardunit.paginate(page: 1).each do |awardunit|
          expect(page).to have_selector( 'a', awardunit.name)
        end
      end

    end


    ### Award Unit Edit page

    describe "awardunit edit page" do
        let(:awardunit) { FactoryGirl.create(:awardunit) }

        before do 
            visit edit_awardunit_path(awardunit)
        end

        it { should have_title("Edit #{awardunit.name} | SLNYAA Core") }

    end

    ### Award Unit Show page


    describe "awardunit show page" do
        let(:awardunit) { FactoryGirl.create(:awardunit) }

        before do 
            visit awardunit_path(awardunit)
        end

        it { should have_title("#{awardunit.name} Award Unit | SLNYAA Core") }

    end

Upvotes: 0

Views: 830

Answers (2)

Michael Lynch
Michael Lynch

Reputation: 1743

If the restriction that each number must fall between 3 - 9 isn't a true restriction, then you can achieve a truly unique value each time by doing sequence:

factory :awardunit do
  ...
  sequence(:nyaaid) { |n| "NYAA/N/WP#{ "%04d"%n } }
  ...
end

Update:

The following code will do what you want and only generate numbers between 3-9 for each character while providing a unique value every time.

factory :awardunit do
  ...
  sequence(:nyaaid) { |n| "NYAA/N/WP#{ n.to_s(7).split('').map{|c| "#{c.to_i + 3}" }.join } }
  ...
end

Side Note: If you're looking for some variance in your "fake" data, there is a great gem called Faker that will allow you have 'real looking' fake data. https://github.com/stympy/faker

Upvotes: 4

spickermann
spickermann

Reputation: 106882

Sure it does. You generate nyaaid with this [1,1,1,1].map!{|x| (3..9).to_a.sample}.join what has only about 2400 possible values. I think the chance to generate a duplicate is quite high.

I do not know how strict validations on that attribute are, perhaps you can just generate nyaaid with something like SecureRandom.hex or sequence(:nyaaid) { |n| "NYAAID#{n}" }. That would allow more variations. Or you need to generate a valid nyaaid with something like this:

def generate_nyaaid
  loop
    nyaaid = [1,1,1,1].map!{|x| (3..9).to_a.sample}.join
    return nyaaid if Awardunit.where(nyaaid: nyaaid).count < 1
  end
end

Upvotes: 0

Related Questions