Skip to content

Instantly share code, notes, and snippets.

@nerdinand
Last active April 18, 2019 06:10
Show Gist options
  • Save nerdinand/3ee85a3da5c8095a6333f05105fef772 to your computer and use it in GitHub Desktop.
Save nerdinand/3ee85a3da5c8095a6333f05105fef772 to your computer and use it in GitHub Desktop.
Poor man's fixtures for hanami
#
# A quick and dirty fixture implementation for use with Hanami, RSpec and PostgreSQL.
# Fixtures will be loaded when the suite starts and will be reset using transactions
# to the same state after each test case.
#
# Supports associations like so (author has many books):
#
# # authors.yml
# rowling:
# name: J.K. Rowling
#
# # books.yml
# hp1:
# name: Harry Potter and the Philosopher's stone
# author: rowling
#
# put this in spec/support/fixtures.rb
# put your fixtures in spec/fixtures
ENV['HANAMI_ENV'] = 'test'
require 'yaml'
fixtures_path = 'spec/fixtures'
@connection = Hanami::Model.configuration.connection
@fixture_landscape = {}
@execution_plan = {}
def foreign_key_columns(table_name)
@connection[table_name.to_sym].columns.select do |column|
column != :id && column.to_s.end_with?('id')
end
end
def add_timestamps_if_necessary(attributes)
['created_at', 'updated_at'].each do |timestamp_attribute|
if attributes[timestamp_attribute].nil?
attributes[timestamp_attribute] = DateTime.now
end
end
attributes
end
def record_name_to_id(record_name)
record_name.hash
end
def lookup_foreign_keys(table_name, attributes)
foreign_key_columns = foreign_key_columns(table_name)
foreign_key_columns.each do |foreign_key_column|
foreign_record_name = attributes.delete(foreign_key_column.to_s[0..-4])
attributes[foreign_key_column.to_s] = record_name_to_id(foreign_record_name)
end
attributes
end
def add_id_column(record_name, attributes)
attributes['id'] = record_name_to_id(record_name)
attributes
end
def enrich_attributes(table_name, record_name, attributes)
add_id_column(record_name, add_timestamps_if_necessary(lookup_foreign_keys(table_name, attributes)))
end
def process_records(table_name, records)
records.each do |record_name, attributes|
@execution_plan[table_name] ||= []
@execution_plan[table_name] << enrich_attributes(table_name, record_name, attributes)
end
end
def process_fixture(fixture_path)
fixture_hash = YAML.load(File.read(fixture_path))
table_name = File.basename(fixture_path, '.*')
@fixture_landscape.merge!({table_name => fixture_hash})
process_records(table_name, fixture_hash)
end
def insert_records
@execution_plan.each do |table_name, records|
records.each do |attributes|
puts "INSERT #{table_name}: #{attributes}"
@connection[table_name.to_sym].insert(attributes)
end
end
end
@connection.transaction do
puts "SET CONSTRAINTS ALL DEFERRED;"
@connection.run("SET CONSTRAINTS ALL DEFERRED;")
Dir.glob(fixtures_path + '/**/*.yml').each do |fixture_path|
process_fixture(fixture_path)
end
insert_records
end
# Add this stuff to your spec_helper.rb
config.around(:each) do |example|
Hanami::Model.configuration.connection.transaction(savepoint: true) do
example.run
raise Sequel::Rollback
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment