nandi 1.0.0 → 2.0.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/README.md +152 -3
- data/lib/generators/nandi/check_constraint/USAGE +9 -0
- data/lib/generators/nandi/check_constraint/check_constraint_generator.rb +2 -4
- data/lib/generators/nandi/compile/USAGE +14 -2
- data/lib/generators/nandi/compile/compile_generator.rb +27 -24
- data/lib/generators/nandi/foreign_key/USAGE +9 -0
- data/lib/generators/nandi/foreign_key/foreign_key_generator.rb +2 -4
- data/lib/generators/nandi/index/USAGE +9 -0
- data/lib/generators/nandi/index/index_generator.rb +2 -4
- data/lib/generators/nandi/migration/USAGE +12 -2
- data/lib/generators/nandi/migration/migration_generator.rb +3 -6
- data/lib/generators/nandi/not_null_check/USAGE +9 -0
- data/lib/generators/nandi/not_null_check/not_null_check_generator.rb +2 -4
- data/lib/nandi/compiled_migration.rb +17 -9
- data/lib/nandi/config.rb +69 -64
- data/lib/nandi/lockfile.rb +74 -54
- data/lib/nandi/migration_violations.rb +110 -0
- data/lib/nandi/multi_database.rb +178 -0
- data/lib/nandi/multi_db_generator.rb +23 -0
- data/lib/nandi/safe_migration_enforcer.rb +78 -82
- data/lib/nandi/validation.rb +1 -0
- data/lib/nandi/version.rb +1 -1
- data/lib/nandi.rb +3 -6
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ec4e2b089c4336135b3899d3d01ac55fd0876fa5f76b22f1672fb494c2267fce
|
4
|
+
data.tar.gz: f66eac48b75fcf959bacc454197c6fb09c6332026ea08a2587e02f6fcc6049fe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: adc1220776ae8fb445ba59c7755e6b80e3449897211485804461a02ebace759d22d098955e67d3ded835f9ff8871c72116b62e4c6aa7f7f9bd5a2f5ecaff3766
|
7
|
+
data.tar.gz: 9d6d92342078cc00360874bc73b8a87407497ef0c694aaefbb5b465215b3965063fab62b9ad753c937110231de7b368c48cabb829b004a510e98c423e333e63a
|
data/README.md
CHANGED
@@ -336,6 +336,8 @@ Some schema changes need to be split across two migration files. Whenever you wa
|
|
336
336
|
|
337
337
|
For some of the most common cases, we provide a Rails generator that generates both files for you.
|
338
338
|
|
339
|
+
All generators support multi-database mode with the `--database` option (see Multi-Database Support section below).
|
340
|
+
|
339
341
|
### Not-null checks
|
340
342
|
|
341
343
|
To generate migration files for a not-null check, run this command:
|
@@ -394,12 +396,23 @@ rails generate nandi:foreign_key foos bar --name my_fk
|
|
394
396
|
Nandi can be configured in various ways, typically in an initializer:
|
395
397
|
|
396
398
|
```rb
|
399
|
+
# Single database configuration
|
397
400
|
Nandi.configure do |config|
|
401
|
+
config.migration_directory = "db/safe_migrations"
|
398
402
|
config.lock_timeout = 1_000
|
399
403
|
end
|
404
|
+
|
405
|
+
# Multi-database configuration (see Multi-Database Support section below)
|
406
|
+
Nandi.configure do |config|
|
407
|
+
config.register_database(:primary)
|
408
|
+
config.register_database(:analytics,
|
409
|
+
migration_directory: "db/analytics_safe_migrations",
|
410
|
+
output_directory: "db/analytics_migrate"
|
411
|
+
)
|
412
|
+
end
|
400
413
|
```
|
401
414
|
|
402
|
-
The configuration parameters are as follows.
|
415
|
+
The configuration parameters are as follows for setting Nandi up for a single database.
|
403
416
|
|
404
417
|
### `access_exclusive_lock_timeout_limit` (Integer)
|
405
418
|
|
@@ -419,11 +432,11 @@ The default lock timeout for migrations. Can be overridden by way of the `set_lo
|
|
419
432
|
|
420
433
|
### `migration_directory` (String)
|
421
434
|
|
422
|
-
The directory for Nandi migrations. Default: `db/safe_migrations
|
435
|
+
The directory for Nandi migrations. Default: `db/safe_migrations`.
|
423
436
|
|
424
437
|
### `output_directory` (String)
|
425
438
|
|
426
|
-
The directory for output files. Default: `db/migrate
|
439
|
+
The directory for output files. Default: `db/migrate`.
|
427
440
|
|
428
441
|
### `renderer` (Class)
|
429
442
|
|
@@ -470,6 +483,142 @@ Parameters:
|
|
470
483
|
|
471
484
|
`klass` (Class) — The class to initialise with the arguments to the method. It should define a `template` instance method which will return a subclass of Cell::ViewModel from the Cells templating library and a `procedure` method that returns the name of the method. It may optionally define a `mixins` method, which will return an array of `Module`s to be mixed into any migration that uses this method.
|
472
485
|
|
486
|
+
## Multi-Database Support
|
487
|
+
|
488
|
+
Nandi 2.0+ supports managing migrations for multiple databases within a single Rails application.
|
489
|
+
|
490
|
+
**Note:** Single database configurations continue to work without any changes. Multi-database support is fully backward compatible.
|
491
|
+
|
492
|
+
### Configuring Multiple Databases
|
493
|
+
|
494
|
+
Instead of setting configuration values directly, register each database with its own configuration. If no values are specified, the existing defaults will be used.
|
495
|
+
|
496
|
+
**Database-specific options** (passed to `register_database`):
|
497
|
+
These options can be set individually for each database. **All are optional** - if not specified, the standard Nandi defaults are used:
|
498
|
+
|
499
|
+
- `migration_directory`: Where Nandi migrations are stored (default: `"db/safe_migrations"` for primary, `"db/<name>_safe_migrations"` for others)
|
500
|
+
- `output_directory`: Where compiled ActiveRecord migrations go (default: `"db/migrate"` for primary, `"db/<name>_migrate"` for others)
|
501
|
+
- `lockfile_name`: Name of the lockfile for this database (default: `".nandilock.yml"` for primary, `".<name>_nandilock.yml"` for others)
|
502
|
+
- `default`: Mark this database as the default when not named `:primary` (default: `false`)
|
503
|
+
- `access_exclusive_lock_timeout`: Timeout for ACCESS EXCLUSIVE locks (default: 5,000ms)
|
504
|
+
- `access_exclusive_statement_timeout`: Statement timeout for ACCESS EXCLUSIVE operations (default: 1,500ms)
|
505
|
+
- `access_exclusive_lock_timeout_limit`: Maximum allowed lock timeout (default: 5,000ms)
|
506
|
+
- `access_exclusive_statement_timeout_limit`: Maximum allowed statement timeout (default: 1,500ms)
|
507
|
+
- `concurrent_lock_timeout_limit`: Minimum timeout for concurrent operations (default: 3,600,000ms / 1 hour)
|
508
|
+
- `concurrent_statement_timeout_limit`: Minimum statement timeout for concurrent operations (default: 3,600,000ms / 1 hour)
|
509
|
+
|
510
|
+
**Global options** (set via config accessors):
|
511
|
+
|
512
|
+
These options apply to all databases:
|
513
|
+
|
514
|
+
- `config.lockfile_directory`: Directory where all lockfiles are stored (default: `"db"`)
|
515
|
+
- `config.compile_files`: Filter for which files to compile (default: `"all"`)
|
516
|
+
- `config.renderer`: Rendering backend (default: `Nandi::Renderers::ActiveRecord`)
|
517
|
+
- `config.post_process { |migration| ... }`: Optional post-processing block for formatting
|
518
|
+
|
519
|
+
```rb
|
520
|
+
# Minimal configuration - primary uses all defaults
|
521
|
+
Nandi.configure do |config|
|
522
|
+
config.register_database(:primary) # Uses all default paths and settings
|
523
|
+
|
524
|
+
config.register_database(:analytics)
|
525
|
+
|
526
|
+
# Global options (apply to all databases)
|
527
|
+
config.lockfile_directory = "db"
|
528
|
+
config.compile_files = "all"
|
529
|
+
end
|
530
|
+
|
531
|
+
# Full example with both database-specific and global options
|
532
|
+
Nandi.configure do |config|
|
533
|
+
# Primary database (automatically becomes default)
|
534
|
+
# If no values are specified, uses the standard defaults:
|
535
|
+
# - migration_directory: "db/safe_migrations"
|
536
|
+
# - output_directory: "db/migrate"
|
537
|
+
# - lockfile_name: ".nandilock.yml"
|
538
|
+
# - All timeout values use their defaults
|
539
|
+
config.register_database(:primary,
|
540
|
+
access_exclusive_lock_timeout: 5_000 # Only override what you need
|
541
|
+
)
|
542
|
+
|
543
|
+
# Analytics database with custom paths and relaxed timeouts
|
544
|
+
config.register_database(:analytics,
|
545
|
+
migration_directory: "db/analytics_safe_migrations",
|
546
|
+
output_directory: "db/analytics_migrate",
|
547
|
+
lockfile_name: ".analytics_nandilock.yml",
|
548
|
+
access_exclusive_lock_timeout: 30_000,
|
549
|
+
access_exclusive_statement_timeout: 10_000,
|
550
|
+
concurrent_statement_timeout_limit: 7_200_000
|
551
|
+
)
|
552
|
+
|
553
|
+
# Global configuration options (apply to all databases)
|
554
|
+
config.lockfile_directory = "db" # Where all lockfiles are stored
|
555
|
+
config.compile_files = "all" # Filter for compilation
|
556
|
+
config.renderer = Nandi::Renderers::ActiveRecord # Optional, this is the default
|
557
|
+
|
558
|
+
# Optional post-processing for all compiled migrations
|
559
|
+
config.post_process do |migration|
|
560
|
+
# Format, lint, etc.
|
561
|
+
migration
|
562
|
+
end
|
563
|
+
end
|
564
|
+
```
|
565
|
+
|
566
|
+
### Directory Structure
|
567
|
+
|
568
|
+
Each database maintains its own directory structure. The primary database uses the default paths if not specified:
|
569
|
+
|
570
|
+
```
|
571
|
+
db/
|
572
|
+
├── safe_migrations/ # Primary database (default path)
|
573
|
+
│ └── 20250901_add_users.rb
|
574
|
+
├── migrate/ # Primary database (default path)
|
575
|
+
│ └── 20250901_add_users.rb
|
576
|
+
├── .nandilock.yml # Primary database (default)
|
577
|
+
│
|
578
|
+
├── analytics_safe_migrations/ # Analytics database
|
579
|
+
│ └── 20250902_add_events.rb
|
580
|
+
├── analytics_migrate/
|
581
|
+
│ └── 20250902_add_events.rb
|
582
|
+
├── .analytics_nandilock.yml
|
583
|
+
│
|
584
|
+
├── reporting_safe_migrations/ # Reporting database
|
585
|
+
│ └── 20250903_add_reports.rb
|
586
|
+
├── reporting_migrate/
|
587
|
+
│ └── 20250903_add_reports.rb
|
588
|
+
└── .reporting_nandilock.yml
|
589
|
+
```
|
590
|
+
|
591
|
+
### Using Generators with Multiple Databases
|
592
|
+
|
593
|
+
All Nandi generators accept a `--database` option to specify which database to target:
|
594
|
+
|
595
|
+
```bash
|
596
|
+
# Generate for primary database (default)
|
597
|
+
rails generate nandi:migration create_users_table
|
598
|
+
|
599
|
+
# Generate for analytics database
|
600
|
+
rails generate nandi:migration create_events_table --database=analytics
|
601
|
+
```
|
602
|
+
|
603
|
+
### Compiling Migrations
|
604
|
+
|
605
|
+
The compile generator can compile all databases or a specific one:
|
606
|
+
|
607
|
+
```bash
|
608
|
+
# Compile all databases
|
609
|
+
rails generate nandi:compile
|
610
|
+
|
611
|
+
# Compile specific database with filter
|
612
|
+
rails generate nandi:compile --database=analytics --files=git-diff
|
613
|
+
```
|
614
|
+
|
615
|
+
### Default Database
|
616
|
+
|
617
|
+
- If you register a database named `:primary`, it automatically becomes the default per rails conventions
|
618
|
+
- Otherwise, mark a database as default with `default: true`
|
619
|
+
- Generators without `--database` option use the default database
|
620
|
+
- Single database configurations work without changes
|
621
|
+
|
473
622
|
## `.nandiignore`
|
474
623
|
|
475
624
|
To protect people from writing unsafe migrations, we provide a script [`nandi-enforce`](https://github.com/gocardless/nandi/blob/master/exe/nandi-enforce) that ensures all migrations in the specified directories are safe migrations generated by Nandi.
|
@@ -9,6 +9,8 @@ Example:
|
|
9
9
|
db/safe_migrations/20190424123727_add_check_constraint_baz_or_quux_not_null_on_foos.rb
|
10
10
|
db/safe_migrations/20190424123728_validate_check_constraint_baz_or_quux_not_null_on_foos.rb
|
11
11
|
|
12
|
+
If no --database option is specified, uses the default database.
|
13
|
+
|
12
14
|
Example:
|
13
15
|
rails generate nandi:check_constraint foos baz_or_quux_not_null --validation-timeout 20000
|
14
16
|
|
@@ -17,3 +19,10 @@ Example:
|
|
17
19
|
db/safe_migrations/20190424123728_validate_check_constraint_baz_or_quux_not_null_on_foos.rb
|
18
20
|
|
19
21
|
The statement timeout in the second migration will be set to 20,000ms.
|
22
|
+
|
23
|
+
Multi-database examples:
|
24
|
+
rails generate nandi:check_constraint users email_valid --database primary
|
25
|
+
creates check constraint migrations in primary database directory
|
26
|
+
|
27
|
+
rails generate nandi:check_constraint events status_valid --database analytics
|
28
|
+
creates check constraint migrations in analytics database directory
|
@@ -2,10 +2,12 @@
|
|
2
2
|
|
3
3
|
require "rails/generators"
|
4
4
|
require "nandi/formatting"
|
5
|
+
require "nandi/multi_db_generator"
|
5
6
|
|
6
7
|
module Nandi
|
7
8
|
class CheckConstraintGenerator < Rails::Generators::Base
|
8
9
|
include Nandi::Formatting
|
10
|
+
include Nandi::MultiDbGenerator
|
9
11
|
|
10
12
|
argument :table, type: :string
|
11
13
|
argument :name, type: :string
|
@@ -41,10 +43,6 @@ module Nandi
|
|
41
43
|
|
42
44
|
private
|
43
45
|
|
44
|
-
def base_path
|
45
|
-
Nandi.config.migration_directory || "db/safe_migrations"
|
46
|
-
end
|
47
|
-
|
48
46
|
def timestamp(offset = 0)
|
49
47
|
(Time.now.utc + offset).strftime("%Y%m%d%H%M%S")
|
50
48
|
end
|
@@ -1,10 +1,15 @@
|
|
1
1
|
Description:
|
2
|
-
Takes all files from the
|
3
|
-
them into
|
2
|
+
Takes all files from the safe migration directories and turns
|
3
|
+
them into ActiveRecord migration files. Supports both single
|
4
|
+
and multi-database configurations.
|
5
|
+
|
6
|
+
If no --database option is specified, compiles for all configured databases
|
7
|
+
(or the default database in single-database configurations).
|
4
8
|
|
5
9
|
Examples:
|
6
10
|
rails generate nandi:compile
|
7
11
|
compiles all migrations that have changed since last git commit
|
12
|
+
(for all configured databases in multi-database setups)
|
8
13
|
|
9
14
|
rails generate nandi:compile --files all
|
10
15
|
compiles all migrations ever
|
@@ -17,3 +22,10 @@ Examples:
|
|
17
22
|
|
18
23
|
rails generate nandi:compile --files >=20190101
|
19
24
|
compiles all migrations from January 1st 2019 and after
|
25
|
+
|
26
|
+
Multi-database examples:
|
27
|
+
rails generate nandi:compile --database primary
|
28
|
+
compiles migrations only for the primary database
|
29
|
+
|
30
|
+
rails generate nandi:compile --database analytics
|
31
|
+
compiles migrations only for the analytics database
|
@@ -10,6 +10,12 @@ module Nandi
|
|
10
10
|
class CompileGenerator < Rails::Generators::Base
|
11
11
|
source_root File.expand_path("templates", __dir__)
|
12
12
|
|
13
|
+
class_option :database,
|
14
|
+
type: :string,
|
15
|
+
default: nil,
|
16
|
+
desc: "Database to compile. " \
|
17
|
+
"If not specified, compiles for all databases"
|
18
|
+
|
13
19
|
class_option :files,
|
14
20
|
type: :string,
|
15
21
|
default: Nandi.config.compile_files,
|
@@ -22,41 +28,38 @@ module Nandi
|
|
22
28
|
DESC
|
23
29
|
|
24
30
|
def compile_migration_files
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
31
|
+
databases.each do |db_name|
|
32
|
+
Nandi.compile(files: files(db_name), db_name: db_name) do |results|
|
33
|
+
results.each do |result|
|
34
|
+
Nandi::Lockfile.for(db_name).add(
|
35
|
+
file_name: result.file_name,
|
36
|
+
source_digest: result.source_digest,
|
37
|
+
compiled_digest: result.compiled_digest,
|
38
|
+
)
|
39
|
+
unless result.migration_unchanged?
|
40
|
+
create_file result.output_path, result.body, force: true
|
41
|
+
end
|
35
42
|
end
|
36
43
|
end
|
44
|
+
Nandi::Lockfile.for(db_name).persist!
|
37
45
|
end
|
38
|
-
|
39
|
-
Nandi::Lockfile.persist!
|
40
46
|
end
|
41
47
|
|
42
48
|
private
|
43
49
|
|
44
|
-
def
|
45
|
-
if
|
46
|
-
|
47
|
-
|
48
|
-
File.expand_path(Nandi.config.migration_directory)
|
49
|
-
end
|
50
|
+
def databases
|
51
|
+
return [options[:database].to_sym] if options[:database]
|
52
|
+
|
53
|
+
Nandi.config.databases.names
|
50
54
|
end
|
51
55
|
|
52
|
-
def
|
53
|
-
Nandi.config.
|
56
|
+
def safe_migrations_dir(db_name)
|
57
|
+
File.expand_path(Nandi.config.migration_directory(db_name))
|
54
58
|
end
|
55
59
|
|
56
|
-
def files
|
57
|
-
safe_migration_files = Dir.chdir(safe_migrations_dir) { Dir["*.rb"] }
|
58
|
-
FileMatcher.call(files: safe_migration_files, spec: options["files"])
|
59
|
-
map { |file| File.join(safe_migrations_dir, file) }
|
60
|
+
def files(db_name)
|
61
|
+
safe_migration_files = Dir.chdir(safe_migrations_dir(db_name)) { Dir["*.rb"] }
|
62
|
+
FileMatcher.call(files: safe_migration_files, spec: options["files"])
|
60
63
|
end
|
61
64
|
end
|
62
65
|
end
|
@@ -14,6 +14,8 @@ Example:
|
|
14
14
|
new foreign key constraint on that column against the id column of bars, and
|
15
15
|
validate that constraint separately.
|
16
16
|
|
17
|
+
If no --database option is specified, uses the default database.
|
18
|
+
|
17
19
|
Example:
|
18
20
|
rails generate nandi:foreign_key foos bars --type text
|
19
21
|
|
@@ -45,3 +47,10 @@ Example:
|
|
45
47
|
|
46
48
|
Assumes that there is a column on table foos called special_bar_id that points to
|
47
49
|
bars. Will create an FK constraint called my_fk
|
50
|
+
|
51
|
+
Multi-database examples:
|
52
|
+
rails generate nandi:foreign_key posts users --database primary
|
53
|
+
creates foreign key migrations in primary database directory
|
54
|
+
|
55
|
+
rails generate nandi:foreign_key events sessions --database analytics
|
56
|
+
creates foreign key migrations in analytics database directory
|
@@ -2,10 +2,12 @@
|
|
2
2
|
|
3
3
|
require "rails/generators"
|
4
4
|
require "nandi/formatting"
|
5
|
+
require "nandi/multi_db_generator"
|
5
6
|
|
6
7
|
module Nandi
|
7
8
|
class ForeignKeyGenerator < Rails::Generators::Base
|
8
9
|
include Nandi::Formatting
|
10
|
+
include Nandi::MultiDbGenerator
|
9
11
|
|
10
12
|
argument :table, type: :string
|
11
13
|
argument :target, type: :string
|
@@ -68,10 +70,6 @@ module Nandi
|
|
68
70
|
:"#{target.singularize}_id"
|
69
71
|
end
|
70
72
|
|
71
|
-
def base_path
|
72
|
-
Nandi.config.migration_directory || "db/safe_migrations"
|
73
|
-
end
|
74
|
-
|
75
73
|
def timestamp(offset = 0)
|
76
74
|
(Time.now.utc + offset).strftime("%Y%m%d%H%M%S")
|
77
75
|
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
Description:
|
2
2
|
Generates new database indices
|
3
3
|
|
4
|
+
If no --database option is specified, uses the default database.
|
5
|
+
|
4
6
|
Example:
|
5
7
|
rails generate nandi:index table_name index_col
|
6
8
|
|
@@ -29,3 +31,10 @@ Example:
|
|
29
31
|
This will create:
|
30
32
|
db/safe_migrations/20190424123727_add_index_on_index_col_to_table_name.rb
|
31
33
|
with the specified bespoke index name
|
34
|
+
|
35
|
+
Multi-database examples:
|
36
|
+
rails generate nandi:index users email --database primary
|
37
|
+
creates index migration in primary database directory
|
38
|
+
|
39
|
+
rails generate nandi:index events created_at --database analytics
|
40
|
+
creates index migration in analytics database directory
|
@@ -2,10 +2,12 @@
|
|
2
2
|
|
3
3
|
require "rails/generators"
|
4
4
|
require "nandi/formatting"
|
5
|
+
require "nandi/multi_db_generator"
|
5
6
|
|
6
7
|
module Nandi
|
7
8
|
class IndexGenerator < Rails::Generators::Base
|
8
9
|
include Nandi::Formatting
|
10
|
+
include Nandi::MultiDbGenerator
|
9
11
|
|
10
12
|
argument :tables, type: :string
|
11
13
|
argument :columns, type: :string
|
@@ -42,10 +44,6 @@ module Nandi
|
|
42
44
|
(Time.now.utc + offset).strftime("%Y%m%d%H%M%S")
|
43
45
|
end
|
44
46
|
|
45
|
-
def base_path
|
46
|
-
Nandi.config.migration_directory || "db/safe_migrations"
|
47
|
-
end
|
48
|
-
|
49
47
|
def override_index_name
|
50
48
|
options["index_name"]&.to_sym
|
51
49
|
end
|
@@ -1,9 +1,19 @@
|
|
1
1
|
Description:
|
2
2
|
Generates a new database migration which uses the
|
3
|
-
nandi DSL
|
3
|
+
nandi DSL. Supports both single and multi-database
|
4
|
+
configurations.
|
4
5
|
|
5
|
-
|
6
|
+
If no --database option is specified, uses the default database.
|
7
|
+
|
8
|
+
Examples:
|
6
9
|
rails generate nandi:migration add_stuff_to_things
|
7
10
|
|
8
11
|
This will create:
|
9
12
|
db/safe_migrations/20190424123727_add_stuff_to_things.rb
|
13
|
+
|
14
|
+
Multi-database examples:
|
15
|
+
rails generate nandi:migration add_stuff_to_things --database primary
|
16
|
+
creates migration in primary database directory
|
17
|
+
|
18
|
+
rails generate nandi:migration add_analytics_table --database analytics
|
19
|
+
creates migration in analytics database directory
|
@@ -1,9 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "rails/generators"
|
4
|
+
require "nandi/multi_db_generator"
|
4
5
|
|
5
6
|
module Nandi
|
6
7
|
class MigrationGenerator < Rails::Generators::NamedBase
|
8
|
+
include Nandi::MultiDbGenerator
|
9
|
+
|
7
10
|
source_root File.expand_path("templates", __dir__)
|
8
11
|
|
9
12
|
def create_migration_file
|
@@ -14,11 +17,5 @@ module Nandi
|
|
14
17
|
"#{base_path}/#{timestamp}_#{file_name.underscore}.rb",
|
15
18
|
)
|
16
19
|
end
|
17
|
-
|
18
|
-
private
|
19
|
-
|
20
|
-
def base_path
|
21
|
-
Nandi.config.migration_directory || "db/safe_migrations"
|
22
|
-
end
|
23
20
|
end
|
24
21
|
end
|
@@ -2,6 +2,8 @@ Description:
|
|
2
2
|
Generates two new database migrations which will safely add a check that
|
3
3
|
a column is not null, and validate it separately.
|
4
4
|
|
5
|
+
If no --database option is specified, uses the default database.
|
6
|
+
|
5
7
|
Example:
|
6
8
|
rails generate nandi:not_null_check foos bar
|
7
9
|
|
@@ -17,3 +19,10 @@ Example:
|
|
17
19
|
db/safe_migrations/20190424123728_validate_not_null_check_on_bar_to_foos.rb
|
18
20
|
|
19
21
|
The statement timeout in the second migration will be set to 20,000ms.
|
22
|
+
|
23
|
+
Multi-database examples:
|
24
|
+
rails generate nandi:not_null_check users email --database primary
|
25
|
+
creates not null check migrations in primary database directory
|
26
|
+
|
27
|
+
rails generate nandi:not_null_check events user_id --database analytics
|
28
|
+
creates not null check migrations in analytics database directory
|
@@ -2,10 +2,12 @@
|
|
2
2
|
|
3
3
|
require "rails/generators"
|
4
4
|
require "nandi/formatting"
|
5
|
+
require "nandi/multi_db_generator"
|
5
6
|
|
6
7
|
module Nandi
|
7
8
|
class NotNullCheckGenerator < Rails::Generators::Base
|
8
9
|
include Nandi::Formatting
|
10
|
+
include Nandi::MultiDbGenerator
|
9
11
|
|
10
12
|
argument :table, type: :string
|
11
13
|
argument :column, type: :string
|
@@ -41,10 +43,6 @@ module Nandi
|
|
41
43
|
|
42
44
|
private
|
43
45
|
|
44
|
-
def base_path
|
45
|
-
Nandi.config.migration_directory || "db/safe_migrations"
|
46
|
-
end
|
47
|
-
|
48
46
|
def timestamp(offset = 0)
|
49
47
|
(Time.now.utc + offset).strftime("%Y%m%d%H%M%S")
|
50
48
|
end
|
@@ -6,15 +6,21 @@ module Nandi
|
|
6
6
|
class CompiledMigration
|
7
7
|
class InvalidMigrationError < StandardError; end
|
8
8
|
|
9
|
-
attr_reader :file_name, :source_file_path, :class_name
|
9
|
+
attr_reader :file_name, :source_file_path, :class_name, :db_config
|
10
10
|
|
11
|
-
def
|
12
|
-
|
11
|
+
def db_name
|
12
|
+
@db_config.name
|
13
13
|
end
|
14
14
|
|
15
|
-
def
|
16
|
-
|
17
|
-
|
15
|
+
def self.build(file_name:, db_name:)
|
16
|
+
new(file_name:, db_name:)
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(file_name:, db_name:)
|
20
|
+
@file_name = file_name
|
21
|
+
@db_config = Nandi.config.database(db_name)
|
22
|
+
@source_file_path = File.join(@db_config.migration_directory, file_name)
|
23
|
+
require File.expand_path(source_file_path)
|
18
24
|
|
19
25
|
@file_name, @class_name = /\d+_([a-z0-9_]+)\.rb\z/.match(source_file_path)[0..1]
|
20
26
|
end
|
@@ -40,7 +46,7 @@ module Nandi
|
|
40
46
|
end
|
41
47
|
|
42
48
|
def output_path
|
43
|
-
"#{
|
49
|
+
"#{db_config.output_directory}/#{file_name}"
|
44
50
|
end
|
45
51
|
|
46
52
|
def migration
|
@@ -58,14 +64,16 @@ module Nandi
|
|
58
64
|
def migration_unchanged?
|
59
65
|
return false unless File.exist?(output_path)
|
60
66
|
|
67
|
+
lockfile = Nandi::Lockfile.for(db_config.name)
|
68
|
+
|
61
69
|
source_migration_diff = Nandi::FileDiff.new(
|
62
70
|
file_path: source_file_path,
|
63
|
-
known_digest:
|
71
|
+
known_digest: lockfile.get(file_name).fetch(:source_digest),
|
64
72
|
)
|
65
73
|
|
66
74
|
compiled_migration_diff = Nandi::FileDiff.new(
|
67
75
|
file_path: output_path,
|
68
|
-
known_digest:
|
76
|
+
known_digest: lockfile.get(file_name).fetch(:compiled_digest),
|
69
77
|
)
|
70
78
|
|
71
79
|
source_migration_diff.unchanged? && compiled_migration_diff.unchanged?
|