pg_sql_triggers 1.0.0 → 1.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.
- checksums.yaml +4 -4
- data/.erb_lint.yml +47 -0
- data/.rubocop.yml +4 -1
- data/CHANGELOG.md +112 -1
- data/COVERAGE.md +58 -0
- data/Goal.md +450 -123
- data/README.md +53 -215
- data/app/controllers/pg_sql_triggers/application_controller.rb +46 -0
- data/app/controllers/pg_sql_triggers/dashboard_controller.rb +4 -1
- data/app/controllers/pg_sql_triggers/generator_controller.rb +76 -8
- data/app/controllers/pg_sql_triggers/migrations_controller.rb +18 -0
- data/app/models/pg_sql_triggers/trigger_registry.rb +93 -12
- data/app/views/layouts/pg_sql_triggers/application.html.erb +34 -1
- data/app/views/pg_sql_triggers/dashboard/index.html.erb +70 -30
- data/app/views/pg_sql_triggers/generator/new.html.erb +22 -4
- data/app/views/pg_sql_triggers/generator/preview.html.erb +244 -16
- data/app/views/pg_sql_triggers/shared/_confirmation_modal.html.erb +221 -0
- data/app/views/pg_sql_triggers/shared/_kill_switch_status.html.erb +40 -0
- data/app/views/pg_sql_triggers/tables/index.html.erb +0 -2
- data/app/views/pg_sql_triggers/tables/show.html.erb +3 -4
- data/config/initializers/pg_sql_triggers.rb +69 -0
- data/db/migrate/20251222000001_create_pg_sql_triggers_tables.rb +3 -1
- data/db/migrate/20251229071916_add_timing_to_pg_sql_triggers_registry.rb +8 -0
- data/docs/README.md +66 -0
- data/docs/api-reference.md +681 -0
- data/docs/configuration.md +541 -0
- data/docs/getting-started.md +135 -0
- data/docs/kill-switch.md +586 -0
- data/docs/screenshots/.gitkeep +1 -0
- data/docs/screenshots/Generate Trigger.png +0 -0
- data/docs/screenshots/Triggers Page.png +0 -0
- data/docs/screenshots/kill error.png +0 -0
- data/docs/screenshots/kill modal for migration down.png +0 -0
- data/docs/usage-guide.md +493 -0
- data/docs/web-ui.md +353 -0
- data/lib/generators/pg_sql_triggers/templates/create_pg_sql_triggers_tables.rb +3 -1
- data/lib/generators/pg_sql_triggers/templates/initializer.rb +44 -2
- data/lib/pg_sql_triggers/drift/db_queries.rb +116 -0
- data/lib/pg_sql_triggers/drift/detector.rb +187 -0
- data/lib/pg_sql_triggers/drift/reporter.rb +179 -0
- data/lib/pg_sql_triggers/drift.rb +14 -11
- data/lib/pg_sql_triggers/dsl/trigger_definition.rb +15 -1
- data/lib/pg_sql_triggers/generator/form.rb +3 -1
- data/lib/pg_sql_triggers/generator/service.rb +82 -26
- data/lib/pg_sql_triggers/migration.rb +1 -1
- data/lib/pg_sql_triggers/migrator/pre_apply_comparator.rb +344 -0
- data/lib/pg_sql_triggers/migrator/pre_apply_diff_reporter.rb +143 -0
- data/lib/pg_sql_triggers/migrator/safety_validator.rb +258 -0
- data/lib/pg_sql_triggers/migrator.rb +85 -3
- data/lib/pg_sql_triggers/registry/manager.rb +100 -13
- data/lib/pg_sql_triggers/sql/kill_switch.rb +300 -0
- data/lib/pg_sql_triggers/testing/dry_run.rb +5 -7
- data/lib/pg_sql_triggers/testing/function_tester.rb +66 -24
- data/lib/pg_sql_triggers/testing/safe_executor.rb +23 -11
- data/lib/pg_sql_triggers/testing/syntax_validator.rb +24 -1
- data/lib/pg_sql_triggers/version.rb +1 -1
- data/lib/pg_sql_triggers.rb +24 -0
- data/lib/tasks/trigger_migrations.rake +33 -0
- data/scripts/generate_coverage_report.rb +129 -0
- metadata +45 -5
data/docs/usage-guide.md
ADDED
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
# Usage Guide
|
|
2
|
+
|
|
3
|
+
This guide covers the core features of PgSqlTriggers: trigger definitions using the DSL, migration management, and drift detection.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Declaring Triggers](#declaring-triggers)
|
|
8
|
+
- [Trigger Migrations](#trigger-migrations)
|
|
9
|
+
- [Combined Schema and Trigger Migrations](#combined-schema-and-trigger-migrations)
|
|
10
|
+
- [Drift Detection](#drift-detection)
|
|
11
|
+
|
|
12
|
+
## Declaring Triggers
|
|
13
|
+
|
|
14
|
+
PgSqlTriggers provides a Ruby DSL for defining triggers. Trigger definitions are declarative and separate from their implementation.
|
|
15
|
+
|
|
16
|
+
### Basic Trigger Definition
|
|
17
|
+
|
|
18
|
+
Create trigger definition files in `app/triggers/`:
|
|
19
|
+
|
|
20
|
+
```ruby
|
|
21
|
+
# app/triggers/users_email_validation.rb
|
|
22
|
+
PgSqlTriggers::DSL.pg_sql_trigger "users_email_validation" do
|
|
23
|
+
table :users
|
|
24
|
+
on :insert, :update
|
|
25
|
+
function :validate_user_email
|
|
26
|
+
|
|
27
|
+
version 1
|
|
28
|
+
enabled false
|
|
29
|
+
timing :before
|
|
30
|
+
|
|
31
|
+
when_env :production
|
|
32
|
+
end
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### DSL Reference
|
|
36
|
+
|
|
37
|
+
#### `table`
|
|
38
|
+
Specifies which table the trigger is attached to:
|
|
39
|
+
|
|
40
|
+
```ruby
|
|
41
|
+
table :users
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
#### `on`
|
|
45
|
+
Defines when the trigger fires (one or more events):
|
|
46
|
+
|
|
47
|
+
```ruby
|
|
48
|
+
on :insert # Single event
|
|
49
|
+
on :insert, :update # Multiple events
|
|
50
|
+
on :delete # Delete operations
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
#### `function`
|
|
54
|
+
The PostgreSQL function that the trigger executes:
|
|
55
|
+
|
|
56
|
+
```ruby
|
|
57
|
+
function :validate_user_email
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
#### `version`
|
|
61
|
+
Version number for tracking changes:
|
|
62
|
+
|
|
63
|
+
```ruby
|
|
64
|
+
version 1 # Increment when trigger logic changes
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
#### `enabled`
|
|
68
|
+
Initial state of the trigger:
|
|
69
|
+
|
|
70
|
+
```ruby
|
|
71
|
+
enabled true # Trigger is active
|
|
72
|
+
enabled false # Trigger is inactive
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
#### `when_env`
|
|
76
|
+
Environment-specific activation:
|
|
77
|
+
|
|
78
|
+
```ruby
|
|
79
|
+
when_env :production # Only in production
|
|
80
|
+
when_env :staging, :production # Multiple environments
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
#### `timing`
|
|
84
|
+
Specifies when the trigger fires relative to the event (BEFORE or AFTER):
|
|
85
|
+
|
|
86
|
+
```ruby
|
|
87
|
+
timing :before # Trigger fires before constraint checks (default)
|
|
88
|
+
timing :after # Trigger fires after constraint checks
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Complete Example
|
|
92
|
+
|
|
93
|
+
```ruby
|
|
94
|
+
# app/triggers/orders_billing_trigger.rb
|
|
95
|
+
PgSqlTriggers::DSL.pg_sql_trigger "orders_billing_trigger" do
|
|
96
|
+
table :orders
|
|
97
|
+
on :insert, :update
|
|
98
|
+
function :calculate_order_total
|
|
99
|
+
|
|
100
|
+
version 2
|
|
101
|
+
enabled true
|
|
102
|
+
timing :after
|
|
103
|
+
|
|
104
|
+
when_env :production, :staging
|
|
105
|
+
end
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Trigger Generator
|
|
109
|
+
|
|
110
|
+
PgSqlTriggers provides a web-based generator and Rails generators for creating trigger definitions and migrations quickly.
|
|
111
|
+
|
|
112
|
+
### Web UI Generator
|
|
113
|
+
|
|
114
|
+
The web UI generator provides a user-friendly interface for creating triggers:
|
|
115
|
+
|
|
116
|
+
1. Navigate to `/pg_sql_triggers/generator/new` in your browser
|
|
117
|
+
2. Fill in the trigger details:
|
|
118
|
+
- **Trigger Name**: Lowercase letters, numbers, and underscores only
|
|
119
|
+
- **Table Name**: The PostgreSQL table to attach the trigger to
|
|
120
|
+
- **Function Name**: The PostgreSQL function name (must match the function body)
|
|
121
|
+
- **Timing**: When the trigger fires - BEFORE (before constraint checks) or AFTER (after constraint checks)
|
|
122
|
+
- **Events**: Select one or more events (INSERT, UPDATE, DELETE, TRUNCATE)
|
|
123
|
+
- **Function Body**: The complete PostgreSQL function definition
|
|
124
|
+
- **Version**: Starting version number (default: 1)
|
|
125
|
+
- **Enabled**: Whether the trigger should be enabled initially
|
|
126
|
+
- **Environments**: Optional environment restrictions
|
|
127
|
+
- **Condition**: Optional WHEN condition for the trigger
|
|
128
|
+
3. Preview the generated DSL and migration code (includes timing and condition display)
|
|
129
|
+
4. Create the trigger files
|
|
130
|
+
|
|
131
|
+
The generator creates:
|
|
132
|
+
- A DSL definition file in `app/triggers/`
|
|
133
|
+
- A migration file in `db/triggers/`
|
|
134
|
+
- A registry entry in the database
|
|
135
|
+
|
|
136
|
+
### Rails Generators
|
|
137
|
+
|
|
138
|
+
You can also use Rails generators to create trigger migrations:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
# Generate a trigger migration
|
|
142
|
+
rails generate trigger:migration add_user_validation
|
|
143
|
+
|
|
144
|
+
# Or using the full namespace
|
|
145
|
+
rails generate pg_sql_triggers:trigger_migration add_user_validation
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
This creates a migration file in `db/triggers/` that you can edit to add your trigger logic.
|
|
149
|
+
|
|
150
|
+
### Generator Features
|
|
151
|
+
|
|
152
|
+
The generator handles:
|
|
153
|
+
- **Function Name Formatting**: Automatically quotes function names with special characters
|
|
154
|
+
- **Multiple Environments**: Supports multiple environment restrictions
|
|
155
|
+
- **Condition Escaping**: Properly escapes quotes in WHEN conditions
|
|
156
|
+
- **Event Combinations**: Handles single or multiple events (INSERT, UPDATE, DELETE, TRUNCATE)
|
|
157
|
+
- **Migration Numbering**: Automatically generates sequential migration numbers
|
|
158
|
+
- **Error Handling**: Graceful error handling with detailed error messages
|
|
159
|
+
|
|
160
|
+
### Generator Edge Cases
|
|
161
|
+
|
|
162
|
+
The generator properly handles:
|
|
163
|
+
- Function names with special characters (quoted vs unquoted)
|
|
164
|
+
- Multiple environments in a single trigger
|
|
165
|
+
- Complex WHEN conditions with quotes
|
|
166
|
+
- All event type combinations
|
|
167
|
+
- Standalone gem usage (without Rails context)
|
|
168
|
+
- Migration number collisions
|
|
169
|
+
- Blank events and environments (filtered automatically)
|
|
170
|
+
|
|
171
|
+
## Trigger Migrations
|
|
172
|
+
|
|
173
|
+
Trigger migrations work similarly to Rails schema migrations but are specifically for PostgreSQL triggers and functions.
|
|
174
|
+
|
|
175
|
+
### Generating Migrations
|
|
176
|
+
|
|
177
|
+
Create a new trigger migration:
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
rails generate trigger:migration add_validation_trigger
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
This creates a timestamped file in `db/triggers/`:
|
|
184
|
+
|
|
185
|
+
```
|
|
186
|
+
db/triggers/20231215120000_add_validation_trigger.rb
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Migration Structure
|
|
190
|
+
|
|
191
|
+
Migrations have `up` and `down` methods:
|
|
192
|
+
|
|
193
|
+
```ruby
|
|
194
|
+
# db/triggers/20231215120000_add_validation_trigger.rb
|
|
195
|
+
class AddValidationTrigger < PgSqlTriggers::Migration
|
|
196
|
+
def up
|
|
197
|
+
execute <<-SQL
|
|
198
|
+
CREATE OR REPLACE FUNCTION validate_user_email()
|
|
199
|
+
RETURNS TRIGGER AS $$
|
|
200
|
+
BEGIN
|
|
201
|
+
IF NEW.email !~ '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$' THEN
|
|
202
|
+
RAISE EXCEPTION 'Invalid email format';
|
|
203
|
+
END IF;
|
|
204
|
+
RETURN NEW;
|
|
205
|
+
END;
|
|
206
|
+
$$ LANGUAGE plpgsql;
|
|
207
|
+
|
|
208
|
+
CREATE TRIGGER user_email_validation
|
|
209
|
+
BEFORE INSERT OR UPDATE ON users
|
|
210
|
+
FOR EACH ROW
|
|
211
|
+
EXECUTE FUNCTION validate_user_email();
|
|
212
|
+
SQL
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def down
|
|
216
|
+
execute <<-SQL
|
|
217
|
+
DROP TRIGGER IF EXISTS user_email_validation ON users;
|
|
218
|
+
DROP FUNCTION IF EXISTS validate_user_email();
|
|
219
|
+
SQL
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Running Migrations
|
|
225
|
+
|
|
226
|
+
#### Apply All Pending Migrations
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
rake trigger:migrate
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
#### Rollback Last Migration
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
rake trigger:rollback
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
#### Rollback Multiple Steps
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
rake trigger:rollback STEP=3
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
#### Check Migration Status
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
rake trigger:migrate:status
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
Output example:
|
|
251
|
+
```
|
|
252
|
+
Status Migration ID Migration Name
|
|
253
|
+
--------------------------------------------------
|
|
254
|
+
up 20231215120000 Add validation trigger
|
|
255
|
+
up 20231216130000 Add billing trigger
|
|
256
|
+
down 20231217140000 Add audit trigger
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
#### Run Specific Migration Up
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
rake trigger:migrate:up VERSION=20231215120000
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
#### Run Specific Migration Down
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
rake trigger:migrate:down VERSION=20231215120000
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
#### Redo Last Migration
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
rake trigger:migrate:redo
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
This rolls back and re-applies the last migration.
|
|
278
|
+
|
|
279
|
+
### Migration Best Practices
|
|
280
|
+
|
|
281
|
+
1. **Always Provide Down Method**: Ensure migrations are reversible
|
|
282
|
+
2. **Use Idempotent SQL**: Use `CREATE OR REPLACE FUNCTION` and `DROP ... IF EXISTS`
|
|
283
|
+
3. **Test in Development**: Verify migrations work before applying to production
|
|
284
|
+
4. **Version Control**: Commit migration files to git
|
|
285
|
+
5. **Incremental Changes**: Keep migrations small and focused
|
|
286
|
+
|
|
287
|
+
### Complex Migration Example
|
|
288
|
+
|
|
289
|
+
```ruby
|
|
290
|
+
# db/triggers/20231218150000_add_order_audit.rb
|
|
291
|
+
class AddOrderAudit < PgSqlTriggers::Migration
|
|
292
|
+
def up
|
|
293
|
+
execute <<-SQL
|
|
294
|
+
-- Create audit table
|
|
295
|
+
CREATE TABLE IF NOT EXISTS order_audits (
|
|
296
|
+
id SERIAL PRIMARY KEY,
|
|
297
|
+
order_id INTEGER NOT NULL,
|
|
298
|
+
operation VARCHAR(10) NOT NULL,
|
|
299
|
+
old_data JSONB,
|
|
300
|
+
new_data JSONB,
|
|
301
|
+
changed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
302
|
+
);
|
|
303
|
+
|
|
304
|
+
-- Create audit function
|
|
305
|
+
CREATE OR REPLACE FUNCTION audit_order_changes()
|
|
306
|
+
RETURNS TRIGGER AS $$
|
|
307
|
+
BEGIN
|
|
308
|
+
IF TG_OP = 'DELETE' THEN
|
|
309
|
+
INSERT INTO order_audits (order_id, operation, old_data)
|
|
310
|
+
VALUES (OLD.id, 'DELETE', row_to_json(OLD));
|
|
311
|
+
RETURN OLD;
|
|
312
|
+
ELSIF TG_OP = 'UPDATE' THEN
|
|
313
|
+
INSERT INTO order_audits (order_id, operation, old_data, new_data)
|
|
314
|
+
VALUES (NEW.id, 'UPDATE', row_to_json(OLD), row_to_json(NEW));
|
|
315
|
+
RETURN NEW;
|
|
316
|
+
ELSIF TG_OP = 'INSERT' THEN
|
|
317
|
+
INSERT INTO order_audits (order_id, operation, new_data)
|
|
318
|
+
VALUES (NEW.id, 'INSERT', row_to_json(NEW));
|
|
319
|
+
RETURN NEW;
|
|
320
|
+
END IF;
|
|
321
|
+
END;
|
|
322
|
+
$$ LANGUAGE plpgsql;
|
|
323
|
+
|
|
324
|
+
-- Create trigger
|
|
325
|
+
CREATE TRIGGER order_audit_trigger
|
|
326
|
+
AFTER INSERT OR UPDATE OR DELETE ON orders
|
|
327
|
+
FOR EACH ROW
|
|
328
|
+
EXECUTE FUNCTION audit_order_changes();
|
|
329
|
+
SQL
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
def down
|
|
333
|
+
execute <<-SQL
|
|
334
|
+
DROP TRIGGER IF EXISTS order_audit_trigger ON orders;
|
|
335
|
+
DROP FUNCTION IF EXISTS audit_order_changes();
|
|
336
|
+
DROP TABLE IF EXISTS order_audits;
|
|
337
|
+
SQL
|
|
338
|
+
end
|
|
339
|
+
end
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
## Combined Schema and Trigger Migrations
|
|
343
|
+
|
|
344
|
+
For convenience, PgSqlTriggers provides rake tasks that run both schema and trigger migrations together.
|
|
345
|
+
|
|
346
|
+
### Run Both Migrations
|
|
347
|
+
|
|
348
|
+
```bash
|
|
349
|
+
rake db:migrate:with_triggers
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
This runs:
|
|
353
|
+
1. `rake db:migrate` (Rails schema migrations)
|
|
354
|
+
2. `rake trigger:migrate` (Trigger migrations)
|
|
355
|
+
|
|
356
|
+
### Rollback Both
|
|
357
|
+
|
|
358
|
+
```bash
|
|
359
|
+
rake db:rollback:with_triggers
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
This rolls back:
|
|
363
|
+
1. The most recent trigger migration
|
|
364
|
+
2. The most recent schema migration
|
|
365
|
+
|
|
366
|
+
### Check Status of Both
|
|
367
|
+
|
|
368
|
+
```bash
|
|
369
|
+
rake db:migrate:status:with_triggers
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
Shows status of both schema and trigger migrations.
|
|
373
|
+
|
|
374
|
+
### Get Versions of Both
|
|
375
|
+
|
|
376
|
+
```bash
|
|
377
|
+
rake db:version:with_triggers
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
Displays current versions of both migration types.
|
|
381
|
+
|
|
382
|
+
## Drift Detection
|
|
383
|
+
|
|
384
|
+
PgSqlTriggers automatically detects when the actual database state differs from your DSL definitions.
|
|
385
|
+
|
|
386
|
+
### Drift States
|
|
387
|
+
|
|
388
|
+
#### Managed & In Sync
|
|
389
|
+
The trigger exists in the database and matches the DSL definition exactly.
|
|
390
|
+
|
|
391
|
+
```
|
|
392
|
+
Status: ✓ Managed & In Sync
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
#### Managed & Drifted
|
|
396
|
+
The trigger exists but its definition doesn't match the DSL (e.g., function modified outside PgSqlTriggers).
|
|
397
|
+
|
|
398
|
+
```
|
|
399
|
+
Status: ⚠ Managed & Drifted
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
**Actions:**
|
|
403
|
+
- Review the differences
|
|
404
|
+
- Update the DSL to match the database
|
|
405
|
+
- Re-apply the migration to restore the DSL definition
|
|
406
|
+
|
|
407
|
+
#### Manual Override
|
|
408
|
+
The trigger was modified outside of PgSqlTriggers (e.g., via direct SQL).
|
|
409
|
+
|
|
410
|
+
```
|
|
411
|
+
Status: ⚠ Manual Override
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
**Actions:**
|
|
415
|
+
- Document the manual changes
|
|
416
|
+
- Update the DSL to reflect the changes
|
|
417
|
+
- Create a new migration if needed
|
|
418
|
+
|
|
419
|
+
#### Disabled
|
|
420
|
+
The trigger is disabled via PgSqlTriggers.
|
|
421
|
+
|
|
422
|
+
```
|
|
423
|
+
Status: ○ Disabled
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
**Actions:**
|
|
427
|
+
- Enable via console or Web UI
|
|
428
|
+
- Verify the trigger is needed
|
|
429
|
+
|
|
430
|
+
#### Dropped
|
|
431
|
+
The trigger was dropped but still exists in the registry.
|
|
432
|
+
|
|
433
|
+
```
|
|
434
|
+
Status: ✗ Dropped
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
**Actions:**
|
|
438
|
+
- Re-apply the migration
|
|
439
|
+
- Remove from registry if no longer needed
|
|
440
|
+
|
|
441
|
+
#### Unknown
|
|
442
|
+
The trigger exists in the database but not in the PgSqlTriggers registry.
|
|
443
|
+
|
|
444
|
+
```
|
|
445
|
+
Status: ? Unknown
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
**Actions:**
|
|
449
|
+
- Add a DSL definition for the trigger
|
|
450
|
+
- Create a migration to bring it under management
|
|
451
|
+
- Drop it if it's no longer needed
|
|
452
|
+
|
|
453
|
+
### Checking for Drift
|
|
454
|
+
|
|
455
|
+
#### Via Console
|
|
456
|
+
|
|
457
|
+
```ruby
|
|
458
|
+
# Get drift information for all triggers
|
|
459
|
+
PgSqlTriggers::Registry.diff
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
#### Via Web UI
|
|
463
|
+
|
|
464
|
+
Navigate to the dashboard at `/pg_sql_triggers` to see drift status visually.
|
|
465
|
+
|
|
466
|
+
### Resolving Drift
|
|
467
|
+
|
|
468
|
+
1. **Review the Drift**: Understand what changed and why
|
|
469
|
+
2. **Choose Resolution**:
|
|
470
|
+
- Update DSL to match database
|
|
471
|
+
- Re-apply migration to match DSL
|
|
472
|
+
- Create new migration for intentional changes
|
|
473
|
+
3. **Verify**: Check that drift is resolved
|
|
474
|
+
|
|
475
|
+
Example:
|
|
476
|
+
|
|
477
|
+
```ruby
|
|
478
|
+
# Check current state
|
|
479
|
+
drift = PgSqlTriggers::Registry.diff
|
|
480
|
+
|
|
481
|
+
# Review specific trigger
|
|
482
|
+
trigger = PgSqlTriggers::Registry.find_by(trigger_name: "users_email_validation")
|
|
483
|
+
trigger.drift_status # => "drifted"
|
|
484
|
+
|
|
485
|
+
# Re-apply migration to fix drift
|
|
486
|
+
rake trigger:migrate:redo
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
## Next Steps
|
|
490
|
+
|
|
491
|
+
- [Web UI Documentation](web-ui.md) - Manage triggers through the web interface
|
|
492
|
+
- [Kill Switch](kill-switch.md) - Production safety features
|
|
493
|
+
- [API Reference](api-reference.md) - Console commands and programmatic access
|