Skip to content

Instantly share code, notes, and snippets.

@reggieb
Last active December 6, 2022 10:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save reggieb/3f9b597a896a24fdf171cb785c3e7f9d to your computer and use it in GitHub Desktop.
Save reggieb/3f9b597a896a24fdf171cb785c3e7f9d to your computer and use it in GitHub Desktop.
Use fixtures along side FactoryBot
FixtureError = Class.new(StandardError)
#
# Wrapper for fixtures so they can be loaded with a FactoryBot type syntax
# Usage:
# fixture :user, :admin
#
# This will try to find a model with an id that matches the fixture label
def fixture(model_name, label)
model = model_name.to_s.classify.constantize
id = ActiveRecord::FixtureSet.identify(label)
model.find(id)
rescue ActiveRecord::RecordNotFound
raise FixtureError, "#{label} fixture not found for #{model_name}"
rescue NameError
raise FixtureError, "No class found for #{model_name}"
end
@reggieb
Copy link
Author

reggieb commented Dec 6, 2022

Background

Recently I've been working on a project when fixtures were used instead of factories, to greatly reduce the running time for specs.

I think both fixtures and factories have their advantages and disadvantage. So I wondered if it is possible to use both in a project.

Usage

Adding this gist code to rspec/support/fixture.rb allows fixtures to be used with a similar syntax to factories.

Example

So in a rails project with FactoryBot installed the following is possible:

RSpec.describe UsersController, type: :request do
  # Use a fixture object for login as all that is needed is an object with the correct authorisation permissions
  # and therefore the same object can be used across many specs
  let(:admin) { fixture :user, :admin }
  before { log_in admin } 

  # Use a factory where the specifics of the object parameters are fundamental to the spec
  describe 'UPDATE user' do
    subject do
      patch user, params: { user: { name: new_name } } 
    end
    let(:original_name) { 'John' }
    let(:new_name) {'Harry' }
    let(:user) { create :user, name: original_name }

   expect { subject }.to change { user.name }.from(original_name).to(new_name)
  end
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment