Skip to content

Instantly share code, notes, and snippets.

@lucassus
Created October 9, 2012 07:47
Show Gist options
  • Save lucassus/3857230 to your computer and use it in GitHub Desktop.
Save lucassus/3857230 to your computer and use it in GitHub Desktop.
Smart fxitures for mongoid and factory_girl
Before
$ rspec spec/ --tag api
Run options: include {:api=>true}
..........................................
Finished in 3 minutes 59.73 seconds
After
$ rspec spec/ --tag api
Run options: include {:api=>true}
..........................................
Finished in 1 minute 12.46 seconds
shared_context 'stuff for the API integration specs' do
before do
fixtures = SmartFixtures.instance
fixtures.capture('API integration specs') do
user = create(:user, email: 'user@email.com', password: 'secret password')
other_user = create(:user, email: 'other.user@email.com', password: 'secret password')
create(:company, name: 'First company', subdomain: 'first-company', users: [user])
create(:company, name: 'Second company', subdomain: 'second-company', users: [user])
create(:company, name: 'Third company', subdomain: 'third-company', users: [other_user])
end
end
let(:user) { User.where(email: 'user@email.com').first }
let(:other_user) { User.where(email: 'other.user@email.com').first }
let(:first_company) { Company.where(subdomain: 'first-company').first }
let(:second_company) { Company.where(subdomain: 'second-company').first }
let(:third_company) { Company.where(subdomain: 'third-company').first }
let(:company) { first_company }
end
# fixtures = SmartFixtures.instance
# fixtures.by_name('sample API data').capture do
# ...
# end
class SmartFixtures
include Singleton
attr_reader :fixtures
def initialize
@fixtures = {}
end
def find_by_name(name)
fixtures[name.to_sym] ||= SmartFixture.new
fixtures[name.to_sym]
end
def capture(name, &block)
find_by_name(name).capture(&block)
end
end
class SmartFixture
attr_accessor :captured_data
def initialize
@captured_data = []
end
def capture(&block)
unless captured?
ActiveSupport::Notifications.subscribe('mongodb.insert') do |name, start, finish, id, payload|
captured_data << [payload[:collection], payload[:documents]]
end
block.call
ActiveSupport::Notifications.unsubscribe('mongodb.insert')
else
insert_all
end
end
def captured?
not captured_data.empty?
end
# insert data from the query cache
def insert_all
captured_data.each do |data|
collection, documents = *data
session = User.collection.database.session
session[collection].insert(documents)
end
end
end
# hook into moped logger
Moped::Protocol::Insert.class_eval do
def log_inspect_with_instrument
ActiveSupport::Notifications.instrument('mongodb.insert', collection: collection, documents: documents)
log_inspect_without_instrument
end
alias_method_chain :log_inspect, :instrument
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment