activerecord-postgresql-branched 0.2.0 → 0.4.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aaa20a8d3be0ae8ce7427b9b8e826fdcb561274ac39ff7c1b6c4234f06db6a1b
4
- data.tar.gz: f1b437b5cb279a11234e18943d40b33e94897fa2b69cf166453f0a346ceb979e
3
+ metadata.gz: 1742fc285cfd6d57e93baa73da6dd675fa3b75df1f02a3320fae25bcfe08f28d
4
+ data.tar.gz: 2ee36f561b9a1e9b4b555f48e39499189bd0da2bbf4344bb2b52616869d52008
5
5
  SHA512:
6
- metadata.gz: d1b59c69941701aa595d8def4334bdbe056ebf5b68e91898b3947ea0b2d95cda4fa20e1b1ab5d541c8eb102bcc9fcf182e62a2cdea9e02ffe392eb226d771809
7
- data.tar.gz: 46d5fe4cab69a81ffa6d53a375267848a7c87fa03f6805ec58104f56320310b736ae3cd8e212bf56861105b078e04f4aaa9a6e8035959d89898f0462168eb139
6
+ metadata.gz: 623f743e34d6db55c2b9b3b447dcf1b2b7066d9aad8d05f656580dcf5546a6e20f142ee35d2a7f7f9a7260eea9b2dcb76e78d35006eb1ecf54d8b604d6af0f98
7
+ data.tar.gz: c48eefaa0809be95fdda529956160f85ba240afb0ac97b94c983d80648d4ba7bce5eab35050d100c21ffee5538f93b219bcee8db2059d7df8c442846f78ef091
data/CHANGELOG.md CHANGED
@@ -1,14 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.0
4
+
5
+ - Restore primary branch — the primary branch (default: `main`) writes to `public` so feature branches see shared state via `search_path` fallthrough
6
+ - Comprehensive test suite: workflow tests, full DDL coverage (69 tests, 163 assertions)
7
+ - Rewrite README from first principles
8
+
9
+ ## 0.3.0
10
+
11
+ - Add `db:branch:console` rake task — opens psql with the branch `search_path`
12
+
3
13
  ## 0.2.0
4
14
 
5
- - Remove primary branch concept — every branch gets its own schema equally
6
15
  - Add shadow interception for `add_foreign_key`, `remove_foreign_key`, `add_check_constraint`, `remove_check_constraint`, `validate_foreign_key`, `validate_check_constraint`
7
16
  - Simplify branch resolution to `PGBRANCH` env var with git fallback
8
17
  - Remove `branch_override` config option and `BRANCH` env var
9
18
  - `db:branch:prune` accepts `KEEP=branch1,branch2` for explicit control
10
19
  - Fix railtie to reuse the adapter's existing BranchManager
11
- - Fix redundant Shadow instantiation in migration table shadowing
20
+ - Pass shadow to `activate` instead of creating a redundant instance
12
21
  - Quote schema identifiers consistently in shadow SQL
13
22
 
14
23
  ## 0.1.0
data/README.md CHANGED
@@ -117,22 +117,36 @@ rails db:branch:discard BRANCH=agent-0
117
117
  ## Rake tasks
118
118
 
119
119
  ```bash
120
- rails db:branch:reset # drop and recreate current branch schema
120
+ rails db:branch:reset # drop and recreate current branch schema
121
121
  rails db:branch:discard # drop current branch schema (or BRANCH=name)
122
122
  rails db:branch:list # list all branch schemas and their sizes
123
123
  rails db:branch:diff # show tables in the current branch schema
124
124
  rails db:branch:prune # drop stale schemas (KEEP=main,feature/x or auto-detect from git)
125
+ rails db:branch:console # open psql with the branch search_path
125
126
  ```
126
127
 
128
+ ### psql
129
+
130
+ `psql` connects directly to PostgreSQL and knows nothing about branch schemas. Use `db:branch:console` instead — it launches psql with `search_path` set to your branch schema, so you see exactly what your Rails app sees.
131
+
127
132
  ## Configuration
128
133
 
129
- The adapter needs one thing: a branch name. Resolution order:
134
+ ```yaml
135
+ development:
136
+ adapter: postgresql_branched
137
+ database: myapp_development
138
+ primary_branch: main # default, can be 'master', 'trunk', etc.
139
+ ```
140
+
141
+ The adapter needs a branch name. Resolution order:
130
142
 
131
143
  1. `PGBRANCH` environment variable
132
144
  2. `git branch --show-current` (automatic fallback)
133
145
 
134
146
  If neither is available, the adapter raises an error.
135
147
 
148
+ On the **primary branch** (`main` by default), the adapter stands aside entirely. No branch schema is created. Migrations land directly in `public`. This is how the shared baseline advances — when you pull main and run `db:migrate`, the tables go to `public` where every feature branch can see them via `search_path` fallthrough.
149
+
136
150
  All standard PostgreSQL connection parameters work as normal (`host`, `port`, `username`, `password`, etc.).
137
151
 
138
152
  **Do not set `schema_search_path` in database.yml** — it conflicts with the adapter's `search_path` management.
@@ -31,7 +31,7 @@ module ActiveRecord
31
31
  def initialize(...)
32
32
  super
33
33
  @branch_manager = BranchManager.new(self, @config)
34
- @shadow = Shadow.new(self, @branch_manager.branch_schema)
34
+ @shadow = Shadow.new(self, @branch_manager.branch_schema) unless @branch_manager.primary_branch?
35
35
  end
36
36
 
37
37
  def configure_connection
@@ -41,7 +41,7 @@ module ActiveRecord
41
41
 
42
42
  SHADOW_BEFORE.each do |method|
43
43
  define_method(method) do |table_name, *args, **kwargs, &block|
44
- @shadow.call(table_name)
44
+ @shadow&.call(table_name)
45
45
  super(table_name, *args, **kwargs, &block)
46
46
  end
47
47
  end
@@ -51,9 +51,10 @@ module ActiveRecord
51
51
  # the branch schema. The table and index renames succeed before the
52
52
  # sequence rename fails, so we rescue the sequence error.
53
53
  def rename_table(table_name, new_name, **options)
54
- @shadow.call(table_name)
54
+ @shadow&.call(table_name)
55
55
  super
56
56
  rescue ActiveRecord::StatementInvalid => e
57
+ raise if @branch_manager.primary_branch?
57
58
  raise unless e.cause.is_a?(PG::UndefinedTable)
58
59
  end
59
60
 
@@ -13,11 +13,17 @@ module ActiveRecord
13
13
  end
14
14
 
15
15
  def activate(shadow)
16
+ return if primary_branch?
17
+
16
18
  ensure_schema
17
19
  set_search_path
18
20
  shadow_migration_tables(shadow)
19
21
  end
20
22
 
23
+ def primary_branch?
24
+ @branch == primary_branch_name
25
+ end
26
+
21
27
  def reset
22
28
  drop_schema
23
29
  ensure_schema
@@ -26,6 +32,11 @@ module ActiveRecord
26
32
 
27
33
  def discard(branch_name = @branch)
28
34
  schema = self.class.sanitise(branch_name)
35
+
36
+ if schema == self.class.sanitise(primary_branch_name)
37
+ raise "Cannot discard the primary branch schema"
38
+ end
39
+
29
40
  @connection.execute("DROP SCHEMA IF EXISTS #{quote(schema)} CASCADE")
30
41
  end
31
42
 
@@ -45,6 +56,8 @@ module ActiveRecord
45
56
  end
46
57
 
47
58
  def diff
59
+ return [] if primary_branch?
60
+
48
61
  @connection.select_values(<<~SQL)
49
62
  SELECT table_name FROM information_schema.tables
50
63
  WHERE table_schema = #{@connection.quote(@branch_schema)}
@@ -107,6 +120,10 @@ module ActiveRecord
107
120
  name
108
121
  end
109
122
 
123
+ def primary_branch_name
124
+ (@config[:primary_branch] || "main").to_s
125
+ end
126
+
110
127
  def ensure_schema
111
128
  @connection.execute("CREATE SCHEMA IF NOT EXISTS #{quote(@branch_schema)}")
112
129
  end
@@ -9,6 +9,12 @@ module ActiveRecord
9
9
  desc "Drop and recreate the current branch schema"
10
10
  task reset: :load_config do
11
11
  manager = branch_manager
12
+
13
+ if manager.primary_branch?
14
+ puts "On primary branch (#{manager.branch}), nothing to reset."
15
+ next
16
+ end
17
+
12
18
  manager.reset
13
19
  puts "Reset branch schema #{manager.branch_schema}. Run db:migrate to reapply branch migrations."
14
20
  end
@@ -53,6 +59,12 @@ module ActiveRecord
53
59
  desc "Show objects in the current branch schema"
54
60
  task diff: :load_config do
55
61
  manager = branch_manager
62
+
63
+ if manager.primary_branch?
64
+ puts "On primary branch, no diff."
65
+ next
66
+ end
67
+
56
68
  tables = manager.diff
57
69
 
58
70
  if tables.empty?
@@ -62,6 +74,26 @@ module ActiveRecord
62
74
  tables.each { |t| puts " #{t}" }
63
75
  end
64
76
  end
77
+
78
+ desc "Open psql with the branch search_path"
79
+ task console: :load_config do
80
+ manager = branch_manager
81
+ config = ActiveRecord::Base.connection_db_config.configuration_hash
82
+
83
+ env = {}
84
+ unless manager.primary_branch?
85
+ env["PGOPTIONS"] = "-c search_path=#{manager.branch_schema},public"
86
+ end
87
+
88
+ args = ["psql"]
89
+ args.push("-h", config[:host].to_s) if config[:host]
90
+ args.push("-p", config[:port].to_s) if config[:port]
91
+ args.push("-U", config[:username].to_s) if config[:username]
92
+ args.push(config[:database].to_s)
93
+
94
+ puts "Connecting to #{config[:database]}#{" as #{manager.branch_schema}" unless manager.primary_branch?}..."
95
+ exec(env, *args)
96
+ end
65
97
  end
66
98
  end
67
99
 
@@ -8,7 +8,8 @@ module ActiveRecord
8
8
  private
9
9
 
10
10
  def on_branch?
11
- @connection.respond_to?(:branch_manager)
11
+ @connection.respond_to?(:branch_manager) &&
12
+ !@connection.branch_manager.primary_branch?
12
13
  end
13
14
 
14
15
  def initialize(connection, options = {})
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-postgresql-branched
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Carl Dawson