Use FactoryGirl's Traits

Define a solid base factory with all appropriate traits

FactoryGirl.define do
  factory :todo_item, aliases: [:incomplete_todo_item] do
    # default attribute values
    name 'Pick up a gallon of milk'
    complete false

    # trait definitions
    trait :completed do
      complete true
    end

    trait :not_completed do
      complete false
    end

    trait :with_comments do
      after(:create) do |todo|
        create_list(:comment, 2, todo_item: todo)
      end
    end

  end
end

Use the base factory as a convenient parent

FactoryGirl.define do
  factory :construction_todo_item, parent: :todo_item do
    # default attribute values
    name 'Pick up drill'    

    # domain-specific trait definitions
    trait :cement do
      name 'Pick up cement'
      amount '50kg'
    end

  end
end

Mix and match traits as you please:

create(:todo_item, :completed, :with_comments)
create(:todo_item)
create(:todo_item, :not_completed, name: 'Pick up a bag of sugar')
create(:construction_todo_item, :not_completed, :cement, amount: "100kg")
# But not
# create(:todo_item, :cement) # since :cement trait is only defined for construction todos

Use traits in child factory definitions

FactoryGirl.define do
  factory :large_cement_todo_item, parent: :construction_todo_item do
    cement # will set :name and :amount accordingly
    amount "200kg" # override amount set in trait
  end
end

Originally at Thoughtbot Blog.

traits

Written on January 21, 2016