foundries 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "fileutils"
4
+
5
+ module Foundries
6
+ module Snapshot
7
+ class Store
8
+ def initialize(preset_name, adapter: Snapshot.adapter,
9
+ storage_path: Snapshot.storage_path,
10
+ source_paths: Snapshot.source_paths)
11
+ @preset_name = preset_name.to_s
12
+ @adapter = adapter
13
+ @storage_path = storage_path
14
+ @fingerprint = Fingerprint.new(
15
+ adapter.instance_variable_get(:@connection),
16
+ source_paths: source_paths
17
+ )
18
+ end
19
+
20
+ def cached?
21
+ cache_dir.exist? &&
22
+ cache_dir.join(".fingerprint").exist? &&
23
+ cache_dir.join(".fingerprint").read.strip == @fingerprint.current
24
+ end
25
+
26
+ # Record which tables are empty before the preset block runs.
27
+ # Only these tables will be captured after the block completes.
28
+ def record_empty_tables
29
+ @capturable_tables = @adapter.table_names.select { |t| @adapter.empty?(t) }
30
+ end
31
+
32
+ def capture
33
+ tables = @capturable_tables || @adapter.table_names
34
+
35
+ tmp_dir = Pathname.new("#{cache_dir}.#{$$}.tmp")
36
+ tmp_dir.mkpath
37
+
38
+ tables.each do |table|
39
+ tmp_dir.join("#{table}.dat").open("w") do |f|
40
+ @adapter.capture(table, f)
41
+ end
42
+ end
43
+
44
+ tmp_dir.join(".fingerprint").write(@fingerprint.current)
45
+
46
+ # Atomic swap
47
+ FileUtils.rm_rf(cache_dir) if cache_dir.exist?
48
+ FileUtils.mv(tmp_dir, cache_dir)
49
+ end
50
+
51
+ def restore
52
+ @adapter.disable_referential_integrity do
53
+ cache_dir.glob("*.dat").each do |file|
54
+ next unless file.size > 0
55
+
56
+ table = file.basename(".dat").to_s
57
+ file.open("r") do |f|
58
+ @adapter.restore(table, f)
59
+ end
60
+ @adapter.reset_sequence(table)
61
+ end
62
+ end
63
+ end
64
+
65
+ private
66
+
67
+ def cache_dir
68
+ @cache_dir ||= Pathname.new(@storage_path).join(@preset_name)
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "digest"
4
+ require_relative "snapshot/fingerprint"
5
+ require_relative "snapshot/adapter"
6
+ require_relative "snapshot/adapters/postgres_adapter"
7
+ require_relative "snapshot/adapters/sqlite_adapter"
8
+ require_relative "snapshot/store"
9
+
10
+ module Foundries
11
+ module Snapshot
12
+ class << self
13
+ attr_writer :storage_path, :connection, :enabled, :source_paths
14
+
15
+ def storage_path
16
+ @storage_path || "tmp/foundries"
17
+ end
18
+
19
+ def connection
20
+ @connection || ActiveRecord::Base.connection
21
+ end
22
+
23
+ def source_paths
24
+ @source_paths || []
25
+ end
26
+
27
+ def enabled?
28
+ return @enabled unless @enabled.nil?
29
+ ENV["FOUNDRIES_CACHE"] == "1"
30
+ end
31
+
32
+ def adapter
33
+ @adapter ||= Adapter.for(connection)
34
+ end
35
+
36
+ def reset!
37
+ @adapter = nil
38
+ @source_paths = nil
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Foundries
4
+ VERSION = "0.1.0"
5
+ RELEASE_DATE = "2026-02-25"
6
+ end
data/lib/foundries.rb ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "factory_bot"
4
+ require_relative "foundries/version"
5
+ require_relative "foundries/blueprint"
6
+ require_relative "foundries/similarity"
7
+ require_relative "foundries/base"
8
+
9
+ module Foundries
10
+ end
11
+
12
+ require_relative "foundries/snapshot" if defined?(ActiveRecord)
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: foundries
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - John Dowd
8
+ - Jim Gay
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 1980-01-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: factory_bot
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '6.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '6.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: ostruct
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Compose factory_bot factories into foundries that build complex trees
42
+ of related records with a declarative DSL.
43
+ email:
44
+ - john.dowd@sofwarellc.com
45
+ - jim.gay@sofwarellc.com
46
+ executables: []
47
+ extensions: []
48
+ extra_rdoc_files: []
49
+ files:
50
+ - CHANGELOG.md
51
+ - LICENSE
52
+ - README.md
53
+ - Rakefile
54
+ - lib/foundries.rb
55
+ - lib/foundries/base.rb
56
+ - lib/foundries/blueprint.rb
57
+ - lib/foundries/similarity.rb
58
+ - lib/foundries/similarity/comparator.rb
59
+ - lib/foundries/similarity/recorder.rb
60
+ - lib/foundries/similarity/structure_tree.rb
61
+ - lib/foundries/snapshot.rb
62
+ - lib/foundries/snapshot/adapter.rb
63
+ - lib/foundries/snapshot/adapters/postgres_adapter.rb
64
+ - lib/foundries/snapshot/adapters/sqlite_adapter.rb
65
+ - lib/foundries/snapshot/fingerprint.rb
66
+ - lib/foundries/snapshot/store.rb
67
+ - lib/foundries/version.rb
68
+ homepage: https://github.com/SOFware/foundries
69
+ licenses:
70
+ - MIT
71
+ metadata:
72
+ allowed_push_host: https://rubygems.org
73
+ homepage_uri: https://github.com/SOFware/foundries
74
+ source_code_uri: https://github.com/SOFware/foundries
75
+ changelog_uri: https://github.com/SOFware/foundries/blob/main/CHANGELOG.md
76
+ rdoc_options: []
77
+ require_paths:
78
+ - lib
79
+ required_ruby_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: 3.2.0
84
+ required_rubygems_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ requirements: []
90
+ rubygems_version: 3.7.2
91
+ specification_version: 4
92
+ summary: Declarative trees of related data using factory_bot
93
+ test_files: []