Skip to content

Commit 7895b91

Browse files
committed
Make SchemaLoader database-agnostic
SchemaLoader now introspects an ActiveRecord connection instead of hardcoding SQLite in-memory. The SQLite setup moves to specs.
1 parent 733c6dc commit 7895b91

3 files changed

Lines changed: 42 additions & 59 deletions

File tree

lib/fixture_bot/rails/cli.rb

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,12 @@ def self.exit_on_failure?
1010
end
1111

1212
desc "generate FIXTURES_FILE [OUTPUT_DIR]", "Generate YAML fixtures from a DSL file"
13-
option :schema, type: :string, default: "db/schema.rb", aliases: "-s", desc: "Path to schema.rb"
1413
def generate(fixtures_path, output_dir = "test/fixtures")
15-
schema_path = options[:schema]
16-
17-
unless File.exist?(schema_path)
18-
raise Thor::Error, "Schema file not found: #{schema_path}"
19-
end
20-
2114
unless File.exist?(fixtures_path)
2215
raise Thor::Error, "Fixtures file not found: #{fixtures_path}"
2316
end
2417

25-
schema = SchemaLoader.load_file(schema_path)
18+
schema = SchemaLoader.load
2619
fixture_set = FixtureBot.define_from_file(schema, fixtures_path)
2720
YamlDumper.new(fixture_set).dump(output_dir)
2821

lib/fixture_bot/rails/schema_loader.rb

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,36 +6,34 @@ module FixtureBot
66
module Rails
77
class SchemaLoader
88

9-
def self.load_file(path)
10-
new.load_file(path)
9+
def self.load(connection = ActiveRecord::Base.connection)
10+
new(connection).load
1111
end
1212

13-
def load_file(path)
14-
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
15-
load(path)
13+
def initialize(connection)
14+
@connection = connection
15+
end
1616

17-
conn = ActiveRecord::Base.connection
18-
build_schema(conn)
19-
ensure
20-
ActiveRecord::Base.connection_pool.disconnect!
17+
def load
18+
build_schema
2119
end
2220

2321
private
2422

2523
INTERNAL_TABLES = %w[ar_internal_metadata schema_migrations].freeze
2624

27-
def build_schema(conn)
25+
def build_schema
2826
schema = Schema.new
29-
table_names = conn.tables - INTERNAL_TABLES
27+
table_names = @connection.tables - INTERNAL_TABLES
3028

31-
join_table_names = detect_join_tables(conn, table_names)
29+
join_table_names = detect_join_tables(table_names)
3230

3331
(table_names - join_table_names).each do |name|
34-
columns = conn.columns(name)
32+
columns = @connection.columns(name)
3533
.reject { |c| skip_column?(c.name) }
3634
.map { |c| c.name.to_sym }
3735

38-
foreign_keys = conn.foreign_keys(name)
36+
foreign_keys = @connection.foreign_keys(name)
3937
associations = foreign_keys.map do |fk|
4038
assoc_name = fk.column.sub(/_id$/, "")
4139
Schema::BelongsTo.new(
@@ -54,7 +52,7 @@ def build_schema(conn)
5452
end
5553

5654
join_table_names.each do |name|
57-
fk_columns = conn.columns(name)
55+
fk_columns = @connection.columns(name)
5856
.select { |c| c.name.end_with?("_id") }
5957
.map { |c| c.name }
6058

@@ -74,12 +72,12 @@ def skip_column?(name)
7472
%w[id created_at updated_at].include?(name)
7573
end
7674

77-
def detect_join_tables(conn, table_names)
75+
def detect_join_tables(table_names)
7876
table_names.select do |name|
79-
pk = conn.primary_key(name)
77+
pk = @connection.primary_key(name)
8078
next false if pk
8179

82-
id_cols = conn.columns(name).select { |c| c.name.end_with?("_id") }
80+
id_cols = @connection.columns(name).select { |c| c.name.end_with?("_id") }
8381
id_cols.size == 2
8482
end
8583
end

spec/fixture_bot/schema_loader_spec.rb

Lines changed: 25 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,44 @@
11
# frozen_string_literal: true
22

33
require "fixture_bot/rails"
4-
require "tmpdir"
54

65
RSpec.describe FixtureBot::Rails::SchemaLoader do
7-
let(:schema_content) do
8-
<<~RUBY
9-
ActiveRecord::Schema.define(version: 2024_01_01_000000) do
10-
create_table "users", force: :cascade do |t|
11-
t.string "name"
12-
t.string "email"
13-
t.timestamps
14-
end
6+
before do
7+
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
158

16-
create_table "posts", force: :cascade do |t|
17-
t.string "title"
18-
t.text "body"
19-
t.integer "author_id"
20-
t.timestamps
21-
end
9+
ActiveRecord::Schema.define(version: 2024_01_01_000000) do
10+
create_table "users", force: :cascade do |t|
11+
t.string "name"
12+
t.string "email"
13+
t.timestamps
14+
end
2215

23-
add_foreign_key "posts", "users", column: "author_id"
16+
create_table "posts", force: :cascade do |t|
17+
t.string "title"
18+
t.text "body"
19+
t.integer "author_id"
20+
t.timestamps
21+
end
2422

25-
create_table "tags", force: :cascade do |t|
26-
t.string "name"
27-
t.timestamps
28-
end
23+
add_foreign_key "posts", "users", column: "author_id"
2924

30-
create_table "posts_tags", id: false, force: :cascade do |t|
31-
t.integer "post_id", null: false
32-
t.integer "tag_id", null: false
33-
end
25+
create_table "tags", force: :cascade do |t|
26+
t.string "name"
27+
t.timestamps
3428
end
35-
RUBY
36-
end
3729

38-
let(:schema_path) do
39-
dir = Dir.mktmpdir
40-
path = File.join(dir, "schema.rb")
41-
File.write(path, schema_content)
42-
path
30+
create_table "posts_tags", id: false, force: :cascade do |t|
31+
t.integer "post_id", null: false
32+
t.integer "tag_id", null: false
33+
end
34+
end
4335
end
4436

4537
after do
46-
FileUtils.rm_rf(File.dirname(schema_path))
38+
ActiveRecord::Base.connection_pool.disconnect!
4739
end
4840

49-
subject(:schema) { described_class.load_file(schema_path) }
41+
subject(:schema) { described_class.load }
5042

5143
it "loads regular tables with columns" do
5244
expect(schema.tables.keys).to contain_exactly(:users, :posts, :tags)

0 commit comments

Comments
 (0)