Factory-girl create that bypasses my model validation

38,022

Solution 1

This isn't very specific to FactoryGirl, but you can always bypass validations when saving models via save(validate: false):

describe ".current" do
  let!(:current_group) { FactoryGirl.create(:group) }

  let!(:old_group) do
    g = FactoryGirl.build(:group, expiry: Time.now - 3.days)
    g.save(validate: false)
    g
 end
      
 specify { Group.current.should == [current_group] }
end

Solution 2

I prefer this solution from https://github.com/thoughtbot/factory_girl/issues/578.

Inside the factory:

trait :without_validations do
  to_create { |instance| instance.save(validate: false) }
end

Solution 3

It's a bad idea to skip validations by default in factory. Some hair will be pulled out finding that.

The nicest way, I think:

trait :skip_validate do
  to_create {|instance| instance.save(validate: false)}
end

Then in your test:

create(:group, :skip_validate, expiry: Time.now + 1.week)

Solution 4

foo = build(:foo).tap { |u| u.save(validate: false) }

Solution 5

For this specific date-baesd validation case, you could also use the timecop gem to temporarily alter time to simulate the old record being created in the past.

Share:
38,022
Norto23
Author by

Norto23

Web developer

Updated on July 08, 2022

Comments

  • Norto23
    Norto23 almost 2 years

    I am using Factory Girl to create two instances in my model/unit test for a Group. I am testing the model to check that a call to .current returns only the 'current' groups according to the expiry attribute as per below...

      describe ".current" do
        let!(:current_group) { FactoryGirl.create(:group, :expiry => Time.now + 1.week) }
        let!(:expired_group) { FactoryGirl.create(:group, :expiry => Time.now - 3.days) }
    
        specify { Group.current.should == [current_group] }
      end
    

    My problem is that I've got validation in the model that checks a new group's expiry is after today's date. This raises the validation failure below.

      1) Group.current 
         Failure/Error: let!(:expired_group) { FactoryGirl.create(:group, :expiry => Time.now - 3.days) }
         ActiveRecord::RecordInvalid:
           Validation failed: Expiry is before todays date
    

    Is there a way to forcefully create the Group or get around the validation when creating using Factory Girl?

  • Kyle Heironimus
    Kyle Heironimus about 8 years
    This is a much more elegant solution than the accepted one.
  • tgf
    tgf almost 7 years
    Keep in mind that if you did this for your general purpose factory you'd be skipping validations EVERY time you did create on that factory. It's probably best to use this technique only on a sub-factory (or in a trait).
  • David Hempy
    David Hempy over 6 years
    See Jason Denney's answer below for a better solution.
  • David Hempy
    David Hempy over 6 years
    You'll almost certainly want to put this in a trait. See the answer by Tim Scott, below.
  • adaam
    adaam about 6 years
    Is there a way to apply this to all factories?
  • yefrem
    yefrem about 5 years
    since 1.9.1 you can do g.tap { |g| g.save(validate: false) }