dynamic_migrations 3.5.3 → 3.6.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/CHANGELOG.md +12 -0
- data/lib/dynamic_migrations/active_record/migrators/trigger.rb +12 -12
- data/lib/dynamic_migrations/postgres/generator/trigger.rb +83 -49
- data/lib/dynamic_migrations/postgres/generator/trigger_template_base.rb +38 -0
- data/lib/dynamic_migrations/postgres/generator/validation.rb +68 -33
- data/lib/dynamic_migrations/postgres/generator/validation_template_base.rb +74 -0
- data/lib/dynamic_migrations/postgres/server/database/schema/table/trigger.rb +12 -1
- data/lib/dynamic_migrations/postgres/server/database/schema/table/triggers.rb +2 -2
- data/lib/dynamic_migrations/postgres/server/database/schema/table/validation.rb +12 -1
- data/lib/dynamic_migrations/version.rb +1 -1
- data/lib/dynamic_migrations.rb +2 -0
- data/sig/dynamic_migrations/active_record/migrators/trigger.rbs +7 -2
- data/sig/dynamic_migrations/postgres/generator/trigger.rbs +11 -2
- data/sig/dynamic_migrations/postgres/generator/trigger_template_base.rbs +25 -0
- data/sig/dynamic_migrations/postgres/generator/validation.rbs +12 -0
- data/sig/dynamic_migrations/postgres/generator/validation_template_base.rbs +30 -0
- data/sig/dynamic_migrations/postgres/server/database/schema/table/trigger.rbs +5 -1
- data/sig/dynamic_migrations/postgres/server/database/schema/table/triggers.rbs +1 -1
- data/sig/dynamic_migrations/postgres/server/database/schema/table/validation.rbs +6 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a25d76d54d7129a77f16574c4b6a84cf82ca6105afe4279ba868b34b97fa4814
|
4
|
+
data.tar.gz: b60f87c21dd0e53aed9853d4eaece239cab1d2524ba9c500e3dc364eda1d40dd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ef75931965eb2dd877bd22a82b4ad6532df5ab4e9e5ff24cc160f9fcc81c3c1db7eca2698b30da99a29000c7c67cf4efd1f5d7eca8ff28fbcc31631a0d43225b
|
7
|
+
data.tar.gz: 4d4218e2872b79b68b79517696403f3aa15c1b87ac2c9b8afd47e1ebb4a1fcb1b3e3efbd0f0db61ad788e8c80472b2eef1d389e08dbf0153414dcfecab5b976c
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [3.6.0](https://github.com/craigulliott/dynamic_migrations/compare/v3.5.3...v3.6.0) (2023-09-13)
|
4
|
+
|
5
|
+
|
6
|
+
### Features
|
7
|
+
|
8
|
+
* plugin architecture for validation and trigger templates (allows for creating cleaner migrations with custom methods) ([f4e9d5e](https://github.com/craigulliott/dynamic_migrations/commit/f4e9d5eae803196e727a5b4d7314e773cd90ba00))
|
9
|
+
|
10
|
+
|
11
|
+
### Bug Fixes
|
12
|
+
|
13
|
+
* fixed badly generated trigger migration ([f4e9d5e](https://github.com/craigulliott/dynamic_migrations/commit/f4e9d5eae803196e727a5b4d7314e773cd90ba00))
|
14
|
+
|
3
15
|
## [3.5.3](https://github.com/craigulliott/dynamic_migrations/compare/v3.5.2...v3.5.3) (2023-09-11)
|
4
16
|
|
5
17
|
|
@@ -62,28 +62,28 @@ module DynamicMigrations
|
|
62
62
|
end
|
63
63
|
|
64
64
|
# wrappers for add_trigger which provide more friendly syntax
|
65
|
-
def before_insert table_name, name:, function_schema_name:, function_name:, action_condition: nil, action_reference_old_table: nil, action_reference_new_table: nil, comment: nil
|
66
|
-
add_trigger table_name, name: name, action_timing: :before, event_manipulation: :insert, action_orientation: :row, function_schema_name: function_schema_name, function_name: function_name, action_condition: action_condition, action_reference_old_table: action_reference_old_table, action_reference_new_table: action_reference_new_table, comment: comment
|
65
|
+
def before_insert table_name, name:, function_schema_name:, function_name:, parameters: nil, action_condition: nil, action_reference_old_table: nil, action_reference_new_table: nil, comment: nil
|
66
|
+
add_trigger table_name, name: name, action_timing: :before, event_manipulation: :insert, action_orientation: :row, function_schema_name: function_schema_name, function_name: function_name, parameters: parameters, action_condition: action_condition, action_reference_old_table: action_reference_old_table, action_reference_new_table: action_reference_new_table, comment: comment
|
67
67
|
end
|
68
68
|
|
69
|
-
def before_update table_name, name:, function_schema_name:, function_name:, action_condition: nil, action_reference_old_table: nil, action_reference_new_table: nil, comment: nil
|
70
|
-
add_trigger table_name, name: name, action_timing: :before, event_manipulation: :update, action_orientation: :row, function_schema_name: function_schema_name, function_name: function_name, action_condition: action_condition, action_reference_old_table: action_reference_old_table, action_reference_new_table: action_reference_new_table, comment: comment
|
69
|
+
def before_update table_name, name:, function_schema_name:, function_name:, parameters: nil, action_condition: nil, action_reference_old_table: nil, action_reference_new_table: nil, comment: nil
|
70
|
+
add_trigger table_name, name: name, action_timing: :before, event_manipulation: :update, action_orientation: :row, function_schema_name: function_schema_name, function_name: function_name, parameters: parameters, action_condition: action_condition, action_reference_old_table: action_reference_old_table, action_reference_new_table: action_reference_new_table, comment: comment
|
71
71
|
end
|
72
72
|
|
73
|
-
def before_delete table_name, name:, function_schema_name:, function_name:, action_condition: nil, action_reference_old_table: nil, action_reference_new_table: nil, comment: nil
|
74
|
-
add_trigger table_name, name: name, action_timing: :before, event_manipulation: :delete, action_orientation: :row, function_schema_name: function_schema_name, function_name: function_name, action_condition: action_condition, action_reference_old_table: action_reference_old_table, action_reference_new_table: action_reference_new_table, comment: comment
|
73
|
+
def before_delete table_name, name:, function_schema_name:, function_name:, parameters: nil, action_condition: nil, action_reference_old_table: nil, action_reference_new_table: nil, comment: nil
|
74
|
+
add_trigger table_name, name: name, action_timing: :before, event_manipulation: :delete, action_orientation: :row, function_schema_name: function_schema_name, function_name: function_name, parameters: parameters, action_condition: action_condition, action_reference_old_table: action_reference_old_table, action_reference_new_table: action_reference_new_table, comment: comment
|
75
75
|
end
|
76
76
|
|
77
|
-
def after_insert table_name, name:, function_schema_name:, function_name:, action_condition: nil, action_reference_old_table: nil, action_reference_new_table: nil, comment: nil
|
78
|
-
add_trigger table_name, name: name, action_timing: :after, event_manipulation: :insert, action_orientation: :row, function_schema_name: function_schema_name, function_name: function_name, action_condition: action_condition, action_reference_old_table: action_reference_old_table, action_reference_new_table: action_reference_new_table, comment: comment
|
77
|
+
def after_insert table_name, name:, function_schema_name:, function_name:, parameters: nil, action_condition: nil, action_reference_old_table: nil, action_reference_new_table: nil, comment: nil
|
78
|
+
add_trigger table_name, name: name, action_timing: :after, event_manipulation: :insert, action_orientation: :row, function_schema_name: function_schema_name, function_name: function_name, parameters: parameters, action_condition: action_condition, action_reference_old_table: action_reference_old_table, action_reference_new_table: action_reference_new_table, comment: comment
|
79
79
|
end
|
80
80
|
|
81
|
-
def after_update table_name, name:, function_schema_name:, function_name:, action_condition: nil, action_reference_old_table: nil, action_reference_new_table: nil, comment: nil
|
82
|
-
add_trigger table_name, name: name, action_timing: :after, event_manipulation: :update, action_orientation: :row, function_schema_name: function_schema_name, function_name: function_name, action_condition: action_condition, action_reference_old_table: action_reference_old_table, action_reference_new_table: action_reference_new_table, comment: comment
|
81
|
+
def after_update table_name, name:, function_schema_name:, function_name:, parameters: nil, action_condition: nil, action_reference_old_table: nil, action_reference_new_table: nil, comment: nil
|
82
|
+
add_trigger table_name, name: name, action_timing: :after, event_manipulation: :update, action_orientation: :row, function_schema_name: function_schema_name, function_name: function_name, parameters: parameters, action_condition: action_condition, action_reference_old_table: action_reference_old_table, action_reference_new_table: action_reference_new_table, comment: comment
|
83
83
|
end
|
84
84
|
|
85
|
-
def after_delete table_name, name:, function_schema_name:, function_name:, action_condition: nil, action_reference_old_table: nil, action_reference_new_table: nil, comment: nil
|
86
|
-
add_trigger table_name, name: name, action_timing: :after, event_manipulation: :delete, action_orientation: :row, function_schema_name: function_schema_name, function_name: function_name, action_condition: action_condition, action_reference_old_table: action_reference_old_table, action_reference_new_table: action_reference_new_table, comment: comment
|
85
|
+
def after_delete table_name, name:, function_schema_name:, function_name:, parameters: nil, action_condition: nil, action_reference_old_table: nil, action_reference_new_table: nil, comment: nil
|
86
|
+
add_trigger table_name, name: name, action_timing: :after, event_manipulation: :delete, action_orientation: :row, function_schema_name: function_schema_name, function_name: function_name, parameters: parameters, action_condition: action_condition, action_reference_old_table: action_reference_old_table, action_reference_new_table: action_reference_new_table, comment: comment
|
87
87
|
end
|
88
88
|
|
89
89
|
def remove_trigger table_name, trigger_name
|
@@ -2,62 +2,96 @@ module DynamicMigrations
|
|
2
2
|
module Postgres
|
3
3
|
class Generator
|
4
4
|
module Trigger
|
5
|
-
|
6
|
-
|
7
|
-
name: ":#{trigger.name}"
|
8
|
-
}
|
9
|
-
|
10
|
-
# if the trigger is a row trigger and the action timing is before or after
|
11
|
-
# then we can use some syntactic sugar to make the migration look nicer
|
12
|
-
# we use method names like before_insert, after_update, etc. and drop the
|
13
|
-
# unnessessary options
|
14
|
-
if trigger.action_orientation == :row && [:before, :after].include?(trigger.action_timing)
|
15
|
-
method_name = "#{trigger.action_timing}_#{trigger.event_manipulation}"
|
16
|
-
else
|
17
|
-
method_name = "add_trigger"
|
18
|
-
options[:action_timing] = ":#{trigger.action_timing}"
|
19
|
-
options[:event_manipulation] = ":#{trigger.event_manipulation}"
|
20
|
-
options[:action_orientation] = ":#{trigger.action_orientation}"
|
21
|
-
end
|
22
|
-
|
23
|
-
# added here because we want the timing and manipulation to visually appear first
|
24
|
-
options[:function_schema_name] = ":#{trigger.function.schema.name}"
|
25
|
-
options[:function_name] = ":#{trigger.function.name}"
|
5
|
+
class UnexpectedTemplateError < StandardError
|
6
|
+
end
|
26
7
|
|
27
|
-
|
28
|
-
|
29
|
-
end
|
8
|
+
class TemplateAlreadyExistsError < StandardError
|
9
|
+
end
|
30
10
|
|
31
|
-
|
32
|
-
|
33
|
-
|
11
|
+
def self.template template_name
|
12
|
+
@templates && @templates[template_name]
|
13
|
+
end
|
34
14
|
|
35
|
-
|
36
|
-
|
37
|
-
|
15
|
+
def self.has_template? template_name
|
16
|
+
@templates&.key?(template_name) || false
|
17
|
+
end
|
38
18
|
|
39
|
-
|
40
|
-
|
41
|
-
|
19
|
+
# install a template into the migration generator, this can be used from outside this
|
20
|
+
# library to clean up common migrations (replace common migrations with syntatic sugar)
|
21
|
+
def self.add_template name, template_class
|
22
|
+
@templates ||= {}
|
23
|
+
raise TemplateAlreadyExistsError, name if @templates.key?(name)
|
24
|
+
@templates[name] = template_class
|
25
|
+
end
|
42
26
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
end
|
27
|
+
def add_trigger trigger, code_comment = nil
|
28
|
+
# if we have a corresponding template, then use it
|
29
|
+
if trigger.template
|
30
|
+
unless (template_class = Trigger.template(trigger.template))
|
31
|
+
raise UnexpectedTemplateError, "Unrecognised template #{trigger.template}"
|
32
|
+
end
|
50
33
|
|
51
|
-
|
34
|
+
arguments = template_class.new(trigger, code_comment).fragment_arguments
|
35
|
+
add_fragment(**arguments)
|
52
36
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
37
|
+
# no template, process this as a default trigger (takes all options)
|
38
|
+
else
|
39
|
+
options = {
|
40
|
+
name: ":#{trigger.name}"
|
41
|
+
}
|
42
|
+
|
43
|
+
# if the trigger is a row trigger and the action timing is before or after
|
44
|
+
# then we can use some syntactic sugar to make the migration look nicer
|
45
|
+
# we use method names like before_insert, after_update, etc. and drop the
|
46
|
+
# unnessessary options
|
47
|
+
if trigger.action_orientation == :row && [:before, :after].include?(trigger.action_timing)
|
48
|
+
method_name = "#{trigger.action_timing}_#{trigger.event_manipulation}"
|
49
|
+
else
|
50
|
+
method_name = "add_trigger"
|
51
|
+
options[:action_timing] = ":#{trigger.action_timing}"
|
52
|
+
options[:event_manipulation] = ":#{trigger.event_manipulation}"
|
53
|
+
options[:action_orientation] = ":#{trigger.action_orientation}"
|
54
|
+
end
|
55
|
+
|
56
|
+
# added here because we want the timing and manipulation to visually appear first
|
57
|
+
options[:function_schema_name] = ":#{trigger.function.schema.name}"
|
58
|
+
options[:function_name] = ":#{trigger.function.name}"
|
59
|
+
|
60
|
+
unless trigger.action_condition.nil?
|
61
|
+
options[:action_condition] = "\"#{trigger.action_condition}\""
|
62
|
+
end
|
63
|
+
|
64
|
+
unless trigger.parameters.nil?
|
65
|
+
options[:parameters] = "\"#{trigger.parameters}\""
|
66
|
+
end
|
67
|
+
|
68
|
+
unless trigger.action_reference_old_table.nil?
|
69
|
+
options[:action_reference_old_table] = ":#{trigger.action_reference_old_table}"
|
70
|
+
end
|
71
|
+
|
72
|
+
unless trigger.action_reference_new_table.nil?
|
73
|
+
options[:action_reference_new_table] = ":#{trigger.action_reference_new_table}"
|
74
|
+
end
|
75
|
+
|
76
|
+
unless trigger.description.nil?
|
77
|
+
options[:comment] = <<~RUBY
|
78
|
+
<<~COMMENT
|
79
|
+
#{indent trigger.description}
|
80
|
+
COMMENT
|
81
|
+
RUBY
|
82
|
+
end
|
83
|
+
|
84
|
+
options_syntax = options.map { |k, v| "#{k}: #{v}" }.join(", ")
|
85
|
+
|
86
|
+
add_fragment schema: trigger.table.schema,
|
87
|
+
table: trigger.table,
|
88
|
+
migration_method: :add_trigger,
|
89
|
+
object: trigger,
|
90
|
+
code_comment: code_comment,
|
91
|
+
migration: <<~RUBY
|
92
|
+
#{method_name} :#{trigger.table.name}, #{options_syntax}
|
93
|
+
RUBY
|
94
|
+
end
|
61
95
|
end
|
62
96
|
|
63
97
|
def remove_trigger trigger, code_comment = nil
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module DynamicMigrations
|
2
|
+
module Postgres
|
3
|
+
class Generator
|
4
|
+
class TriggerTemplateBase
|
5
|
+
class TemplateError < StandardError
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_reader :trigger
|
9
|
+
|
10
|
+
def initialize trigger, code_comment
|
11
|
+
@trigger = trigger
|
12
|
+
@code_comment = code_comment
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def assert_column_count! count = 1
|
18
|
+
if @trigger.columns.count != count
|
19
|
+
raise TemplateError, "#{self.class.name} trigger template requires a trigger with only #{count} column"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def first_column
|
24
|
+
column = @trigger.columns.first
|
25
|
+
if column.nil?
|
26
|
+
raise TemplateError, "#{self.class.name} trigger template requires a first column"
|
27
|
+
end
|
28
|
+
column
|
29
|
+
end
|
30
|
+
|
31
|
+
def indent multi_line_string, levels = 1
|
32
|
+
spaces = " " * levels
|
33
|
+
multi_line_string.gsub("\n", "\n#{spaces}")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -2,44 +2,79 @@ module DynamicMigrations
|
|
2
2
|
module Postgres
|
3
3
|
class Generator
|
4
4
|
module Validation
|
5
|
+
class UnexpectedTemplateError < StandardError
|
6
|
+
end
|
7
|
+
|
8
|
+
class TemplateAlreadyExistsError < StandardError
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.template template_name
|
12
|
+
@templates && @templates[template_name]
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.has_template? template_name
|
16
|
+
@templates&.key?(template_name) || false
|
17
|
+
end
|
18
|
+
|
19
|
+
# install a template into the migration generator, this can be used from outside this
|
20
|
+
# library to clean up common migrations (replace common migrations with syntatic sugar)
|
21
|
+
def self.add_template name, template_class
|
22
|
+
@templates ||= {}
|
23
|
+
raise TemplateAlreadyExistsError, name if @templates.key?(name)
|
24
|
+
@templates[name] = template_class
|
25
|
+
end
|
26
|
+
|
5
27
|
def add_validation validation, code_comment = nil
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
28
|
+
# if we have a corresponding template, then use it
|
29
|
+
if validation.template
|
30
|
+
unless (template_class = Validation.template(validation.template))
|
31
|
+
raise UnexpectedTemplateError, "Unrecognised template #{validation.template}"
|
32
|
+
end
|
33
|
+
|
34
|
+
arguments = template_class.new(validation, code_comment).fragment_arguments
|
35
|
+
add_fragment(**arguments)
|
36
|
+
|
37
|
+
# no template, process this as a default validation (takes all options)
|
14
38
|
else
|
15
|
-
comment_sql = <<~RUBY
|
16
|
-
#{validation.name}_comment = <<~COMMENT
|
17
|
-
#{indent validation.description || ""}
|
18
|
-
COMMENT
|
19
|
-
RUBY
|
20
|
-
options[:comment] = "#{validation.name}_comment"
|
21
|
-
end
|
22
39
|
|
23
|
-
|
40
|
+
options = {
|
41
|
+
name: ":#{validation.name}",
|
42
|
+
deferrable: validation.deferrable,
|
43
|
+
initially_deferred: validation.initially_deferred
|
44
|
+
}
|
24
45
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
46
|
+
if validation.description.nil?
|
47
|
+
comment_sql = ""
|
48
|
+
else
|
49
|
+
comment_sql = <<~RUBY
|
50
|
+
#{validation.name}_comment = <<~COMMENT
|
51
|
+
#{indent validation.description || ""}
|
52
|
+
COMMENT
|
53
|
+
RUBY
|
54
|
+
options[:comment] = "#{validation.name}_comment"
|
55
|
+
end
|
30
56
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
57
|
+
options_syntax = options.map { |k, v| "#{k}: #{v}" }.join(", ")
|
58
|
+
|
59
|
+
validation_sql = validation.check_clause.strip
|
60
|
+
# ensure that the validation ends with a semicolon
|
61
|
+
unless validation_sql.end_with? ";"
|
62
|
+
validation_sql << ";"
|
63
|
+
end
|
64
|
+
|
65
|
+
add_fragment schema: validation.table.schema,
|
66
|
+
table: validation.table,
|
67
|
+
migration_method: :add_validation,
|
68
|
+
object: validation,
|
69
|
+
code_comment: code_comment,
|
70
|
+
migration: comment_sql + <<~RUBY
|
71
|
+
add_validation :#{validation.table.name}, #{options_syntax} do
|
72
|
+
<<~SQL
|
73
|
+
#{indent validation_sql}
|
74
|
+
SQL
|
75
|
+
end
|
76
|
+
RUBY
|
77
|
+
end
|
43
78
|
end
|
44
79
|
|
45
80
|
def remove_validation validation, code_comment = nil
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module DynamicMigrations
|
2
|
+
module Postgres
|
3
|
+
class Generator
|
4
|
+
class ValidationTemplateBase
|
5
|
+
class TemplateError < StandardError
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_reader :validation
|
9
|
+
|
10
|
+
def initialize validation, code_comment
|
11
|
+
@validation = validation
|
12
|
+
@code_comment = code_comment
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def assert_not_deferred!
|
18
|
+
if @validation.initially_deferred || @validation.deferrable
|
19
|
+
raise TemplateError, "#{self.class.name} validation template requires constraints to be are not deferrable"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def assert_column_count! count = 1
|
24
|
+
if @validation.columns.count != count
|
25
|
+
raise TemplateError, "#{self.class.name} validation template requires a validation with only #{count} column"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def first_column
|
30
|
+
column = @validation.columns.first
|
31
|
+
if column.nil?
|
32
|
+
raise TemplateError, "#{self.class.name} validation template requires a first column"
|
33
|
+
end
|
34
|
+
column
|
35
|
+
end
|
36
|
+
|
37
|
+
def value_from_check_clause regex
|
38
|
+
matches = @validation.check_clause.strip.match(regex)
|
39
|
+
unless matches
|
40
|
+
raise TemplateError, "#{self.class.name} validation template check_clause was not an expected format"
|
41
|
+
end
|
42
|
+
if matches[:value].nil?
|
43
|
+
raise TemplateError, "#{self.class.name} validation template check_clause could not parse out value from regex (expected `value` named capture group in the regex)"
|
44
|
+
end
|
45
|
+
matches[:value]
|
46
|
+
end
|
47
|
+
|
48
|
+
def name_and_description_options_string default_name
|
49
|
+
options = {}
|
50
|
+
# we only need to provide a name if it is different than the default
|
51
|
+
unless @validation.name == default_name
|
52
|
+
options[:name] = @validation.name
|
53
|
+
end
|
54
|
+
# only provide a comment if it is not nil
|
55
|
+
unless @validation.description.nil?
|
56
|
+
options[:comment] = <<~RUBY
|
57
|
+
<<~COMMENT
|
58
|
+
#{indent @validation.description || ""}
|
59
|
+
COMMENT
|
60
|
+
RUBY
|
61
|
+
end
|
62
|
+
|
63
|
+
options_string = options.map { |k, v| "#{k}: #{v}" }.join(", ")
|
64
|
+
options_string.empty? ? nil : ", #{options_string}"
|
65
|
+
end
|
66
|
+
|
67
|
+
def indent multi_line_string, levels = 1
|
68
|
+
spaces = " " * levels
|
69
|
+
multi_line_string.gsub("\n", "\n#{spaces}")
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -35,6 +35,9 @@ module DynamicMigrations
|
|
35
35
|
class UnexpectedActionOrderError < StandardError
|
36
36
|
end
|
37
37
|
|
38
|
+
class UnexpectedTemplateError < StandardError
|
39
|
+
end
|
40
|
+
|
38
41
|
attr_reader :table
|
39
42
|
attr_reader :name
|
40
43
|
attr_reader :event_manipulation
|
@@ -46,9 +49,10 @@ module DynamicMigrations
|
|
46
49
|
attr_reader :action_reference_old_table
|
47
50
|
attr_reader :action_reference_new_table
|
48
51
|
attr_reader :description
|
52
|
+
attr_reader :template
|
49
53
|
|
50
54
|
# initialize a new object to represent a validation in a postgres table
|
51
|
-
def initialize source, table, name, action_timing:, event_manipulation:, parameters:, action_orientation:, function:, action_order: nil, action_condition: nil, action_reference_old_table: nil, action_reference_new_table: nil, description: nil
|
55
|
+
def initialize source, table, name, action_timing:, event_manipulation:, parameters:, action_orientation:, function:, action_order: nil, action_condition: nil, action_reference_old_table: nil, action_reference_new_table: nil, description: nil, template: nil
|
52
56
|
super source
|
53
57
|
|
54
58
|
unless table.is_a? Table
|
@@ -125,6 +129,13 @@ module DynamicMigrations
|
|
125
129
|
@description = description.strip
|
126
130
|
@description = nil if description == ""
|
127
131
|
end
|
132
|
+
|
133
|
+
unless template.nil?
|
134
|
+
unless Generator::Trigger.has_template? template
|
135
|
+
raise UnexpectedTemplateError, template
|
136
|
+
end
|
137
|
+
@template = template
|
138
|
+
end
|
128
139
|
end
|
129
140
|
|
130
141
|
def action_order
|
@@ -38,13 +38,13 @@ module DynamicMigrations
|
|
38
38
|
end
|
39
39
|
|
40
40
|
# adds a new trigger to this table, and returns it
|
41
|
-
def add_trigger name, action_timing:, event_manipulation:, parameters:, action_orientation:, function:, action_order: nil, action_condition: nil, action_reference_old_table: nil, action_reference_new_table: nil, description: nil
|
41
|
+
def add_trigger name, action_timing:, event_manipulation:, parameters:, action_orientation:, function:, action_order: nil, action_condition: nil, action_reference_old_table: nil, action_reference_new_table: nil, description: nil, template: nil
|
42
42
|
if has_trigger? name
|
43
43
|
raise(TriggerAlreadyExistsError, "Trigger #{name} already exists")
|
44
44
|
end
|
45
45
|
included_target = self
|
46
46
|
if included_target.is_a? Table
|
47
|
-
new_trigger = @triggers[name] = Trigger.new source, included_target, name, action_timing: action_timing, event_manipulation: event_manipulation, action_order: action_order, parameters: parameters, action_orientation: action_orientation, function: function, action_condition: action_condition, action_reference_old_table: action_reference_old_table, action_reference_new_table: action_reference_new_table, description: description
|
47
|
+
new_trigger = @triggers[name] = Trigger.new source, included_target, name, action_timing: action_timing, event_manipulation: event_manipulation, action_order: action_order, parameters: parameters, action_orientation: action_orientation, function: function, action_condition: action_condition, action_reference_old_table: action_reference_old_table, action_reference_new_table: action_reference_new_table, description: description, template: template
|
48
48
|
else
|
49
49
|
raise ModuleIncludedIntoUnexpectedTargetError, included_target
|
50
50
|
end
|
@@ -17,15 +17,19 @@ module DynamicMigrations
|
|
17
17
|
class DuplicateColumnError < StandardError
|
18
18
|
end
|
19
19
|
|
20
|
+
class UnexpectedTemplateError < StandardError
|
21
|
+
end
|
22
|
+
|
20
23
|
attr_reader :table
|
21
24
|
attr_reader :name
|
22
25
|
attr_reader :check_clause
|
23
26
|
attr_reader :deferrable
|
24
27
|
attr_reader :initially_deferred
|
25
28
|
attr_reader :description
|
29
|
+
attr_reader :template
|
26
30
|
|
27
31
|
# initialize a new object to represent a validation in a postgres table
|
28
|
-
def initialize source, table, columns, name, check_clause, description: nil, deferrable: false, initially_deferred: false
|
32
|
+
def initialize source, table, columns, name, check_clause, description: nil, deferrable: false, initially_deferred: false, template: nil
|
29
33
|
super source
|
30
34
|
raise ExpectedTableError, table unless table.is_a? Table
|
31
35
|
@table = table
|
@@ -57,6 +61,13 @@ module DynamicMigrations
|
|
57
61
|
|
58
62
|
raise ExpectedBooleanError, initially_deferred unless [true, false].include?(initially_deferred)
|
59
63
|
@initially_deferred = initially_deferred
|
64
|
+
|
65
|
+
unless template.nil?
|
66
|
+
unless Generator::Validation.has_template? template
|
67
|
+
raise UnexpectedTemplateError, "Unrecognised template #{template}"
|
68
|
+
end
|
69
|
+
@template = template
|
70
|
+
end
|
60
71
|
end
|
61
72
|
|
62
73
|
# return true if this has a description, otherwise false
|
data/lib/dynamic_migrations.rb
CHANGED
@@ -77,6 +77,8 @@ require "dynamic_migrations/postgres/generator/primary_key"
|
|
77
77
|
require "dynamic_migrations/postgres/generator/trigger"
|
78
78
|
require "dynamic_migrations/postgres/generator/unique_constraint"
|
79
79
|
require "dynamic_migrations/postgres/generator/validation"
|
80
|
+
require "dynamic_migrations/postgres/generator/validation_template_base"
|
81
|
+
require "dynamic_migrations/postgres/generator/trigger_template_base"
|
80
82
|
require "dynamic_migrations/postgres/generator"
|
81
83
|
require "dynamic_migrations/postgres/generator/fragment"
|
82
84
|
require "dynamic_migrations/postgres/generator/migration"
|
@@ -1,5 +1,3 @@
|
|
1
|
-
# TypeProf 0.21.7
|
2
|
-
|
3
1
|
# Classes
|
4
2
|
module DynamicMigrations
|
5
3
|
module ActiveRecord
|
@@ -10,6 +8,13 @@ module DynamicMigrations
|
|
10
8
|
def set_trigger_comment: (Symbol table_name, Symbol trigger_name, String comment) -> void
|
11
9
|
def remove_trigger_comment: (Symbol table_name, Symbol trigger_name) -> void
|
12
10
|
|
11
|
+
def before_insert: (Symbol table_name, name: Symbol, function_schema_name: Symbol, function_name: Symbol, ?parameters: String?, ?action_condition: String?, ?action_reference_old_table: Symbol?, ?action_reference_new_table: Symbol?, ?comment: String?) -> void
|
12
|
+
def before_update: (Symbol table_name, name: Symbol, function_schema_name: Symbol, function_name: Symbol, ?parameters: String?, ?action_condition: String?, ?action_reference_old_table: Symbol?, ?action_reference_new_table: Symbol?, ?comment: String?) -> void
|
13
|
+
def before_delete: (Symbol table_name, name: Symbol, function_schema_name: Symbol, function_name: Symbol, ?parameters: String?, ?action_condition: String?, ?action_reference_old_table: Symbol?, ?action_reference_new_table: Symbol?, ?comment: String?) -> void
|
14
|
+
def after_insert: (Symbol table_name, name: Symbol, function_schema_name: Symbol, function_name: Symbol, ?parameters: String?, ?action_condition: String?, ?action_reference_old_table: Symbol?, ?action_reference_new_table: Symbol?, ?comment: String?) -> void
|
15
|
+
def after_update: (Symbol table_name, name: Symbol, function_schema_name: Symbol, function_name: Symbol, ?parameters: String?, ?action_condition: String?, ?action_reference_old_table: Symbol?, ?action_reference_new_table: Symbol?, ?comment: String?) -> void
|
16
|
+
def after_delete: (Symbol table_name, name: Symbol, function_schema_name: Symbol, function_name: Symbol, ?parameters: String?, ?action_condition: String?, ?action_reference_old_table: Symbol?, ?action_reference_new_table: Symbol?, ?comment: String?) -> void
|
17
|
+
|
13
18
|
# stubbing these out, as they are available on the module which includes this module
|
14
19
|
def execute: (String sql) -> void
|
15
20
|
def schema_name: () -> Symbol
|
@@ -1,10 +1,14 @@
|
|
1
|
-
# TypeProf 0.21.7
|
2
|
-
|
3
1
|
# Classes
|
4
2
|
module DynamicMigrations
|
5
3
|
module Postgres
|
6
4
|
class Generator
|
7
5
|
module Trigger
|
6
|
+
self.@templates: Hash[Symbol, singleton(TriggerTemplateBase)]
|
7
|
+
|
8
|
+
def self.template: (Symbol template_name) -> singleton(TriggerTemplateBase)
|
9
|
+
def self.has_template?: (Symbol template_name) -> bool
|
10
|
+
def self.add_template: (Symbol template_name, singleton(TriggerTemplateBase) template_class) -> void
|
11
|
+
|
8
12
|
def add_trigger: (Server::Database::Schema::Table::Trigger trigger, ?String? code_comment) -> Fragment
|
9
13
|
def remove_trigger: (Server::Database::Schema::Table::Trigger trigger, ?String? code_comment) -> Fragment
|
10
14
|
def recreate_trigger: (Server::Database::Schema::Table::Trigger original_trigger, Server::Database::Schema::Table::Trigger updated_trigger) -> Array[Fragment]
|
@@ -16,6 +20,11 @@ module DynamicMigrations
|
|
16
20
|
|
17
21
|
def indent: (String migration, ?Integer levels) -> String
|
18
22
|
|
23
|
+
class UnexpectedTemplateError < StandardError
|
24
|
+
end
|
25
|
+
|
26
|
+
class TemplateAlreadyExistsError < StandardError
|
27
|
+
end
|
19
28
|
end
|
20
29
|
end
|
21
30
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Classes
|
2
|
+
module DynamicMigrations
|
3
|
+
module Postgres
|
4
|
+
class Generator
|
5
|
+
class TriggerTemplateBase
|
6
|
+
@code_comment: untyped
|
7
|
+
|
8
|
+
attr_reader trigger: untyped
|
9
|
+
|
10
|
+
def initialize: (untyped trigger, untyped code_comment) -> void
|
11
|
+
|
12
|
+
# abstract method (should actually be added to child classes)
|
13
|
+
def fragment_arguments: -> {schema: Postgres::Server::Database::Schema, table: Postgres::Server::Database::Schema::Table, migration_method: :add_validation, object: Postgres::Server::Database::Schema::Table::Validation, code_comment: String?, migration: String}
|
14
|
+
|
15
|
+
private
|
16
|
+
def assert_column_count!: (?Integer count) -> nil
|
17
|
+
def first_column: -> untyped
|
18
|
+
def indent: (untyped multi_line_string, ?Integer levels) -> untyped
|
19
|
+
|
20
|
+
class TemplateError < StandardError
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -5,6 +5,12 @@ module DynamicMigrations
|
|
5
5
|
module Postgres
|
6
6
|
class Generator
|
7
7
|
module Validation
|
8
|
+
self.@templates: Hash[Symbol, singleton(ValidationTemplateBase)]
|
9
|
+
|
10
|
+
def self.template: (Symbol template_name) -> singleton(ValidationTemplateBase)
|
11
|
+
def self.has_template?: (Symbol template_name) -> bool
|
12
|
+
def self.add_template: (Symbol template_name, singleton(ValidationTemplateBase) template_class) -> void
|
13
|
+
|
8
14
|
def add_validation: (Postgres::Server::Database::Schema::Table::Validation validation, ?String? code_comment) -> Fragment
|
9
15
|
def remove_validation: (Postgres::Server::Database::Schema::Table::Validation validation, ?String? code_comment) -> Fragment
|
10
16
|
def recreate_validation: (Postgres::Server::Database::Schema::Table::Validation original_validation, Postgres::Server::Database::Schema::Table::Validation updated_validation) -> Array[Fragment]
|
@@ -15,7 +21,13 @@ module DynamicMigrations
|
|
15
21
|
def add_fragment: (migration_method: Symbol, object: untyped, migration: String, ?schema: Server::Database::Schema?, ?table: Server::Database::Schema::Table?, ?code_comment: String?, ?dependent_table: Server::Database::Schema::Table?) -> untyped
|
16
22
|
|
17
23
|
def indent: (String migration, ?Integer levels) -> String
|
24
|
+
|
25
|
+
class UnexpectedTemplateError < StandardError
|
26
|
+
end
|
27
|
+
|
28
|
+
class TemplateAlreadyExistsError < StandardError
|
18
29
|
end
|
30
|
+
end
|
19
31
|
end
|
20
32
|
end
|
21
33
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# TypeProf 0.21.8
|
2
|
+
|
3
|
+
# Classes
|
4
|
+
module DynamicMigrations
|
5
|
+
module Postgres
|
6
|
+
class Generator
|
7
|
+
class ValidationTemplateBase
|
8
|
+
@code_comment: untyped
|
9
|
+
|
10
|
+
attr_reader validation: untyped
|
11
|
+
|
12
|
+
def initialize: (untyped validation, untyped code_comment) -> void
|
13
|
+
|
14
|
+
# abstract method (should actually be added to child classes)
|
15
|
+
def fragment_arguments: -> {schema: Postgres::Server::Database::Schema, table: Postgres::Server::Database::Schema::Table, migration_method: :add_validation, object: Postgres::Server::Database::Schema::Table::Validation, code_comment: String?, migration: String}
|
16
|
+
|
17
|
+
private
|
18
|
+
def assert_not_deferred!: -> nil
|
19
|
+
def assert_column_count!: (?Integer count) -> nil
|
20
|
+
def first_column: -> untyped
|
21
|
+
def value_from_check_clause: (untyped regex) -> untyped
|
22
|
+
def name_and_description_options_string: (untyped default_name) -> String?
|
23
|
+
def indent: (String multi_line_string, ?Integer levels) -> String
|
24
|
+
|
25
|
+
class TemplateError < StandardError
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -20,8 +20,9 @@ module DynamicMigrations
|
|
20
20
|
attr_reader action_reference_old_table: Symbol?
|
21
21
|
attr_reader action_reference_new_table: Symbol?
|
22
22
|
attr_reader description: String?
|
23
|
+
attr_reader template: Symbol?
|
23
24
|
|
24
|
-
def initialize: (database_or_configuration source, Table table, Symbol name, action_timing: Symbol, event_manipulation: Symbol, parameters: String?, action_orientation: Symbol, function: Function, ?action_order: Integer?, ?action_condition: String?, ?action_reference_old_table: Symbol?, ?action_reference_new_table: Symbol?, ?description: String?) -> void
|
25
|
+
def initialize: (database_or_configuration source, Table table, Symbol name, action_timing: Symbol, event_manipulation: Symbol, parameters: String?, action_orientation: Symbol, function: Function, ?action_order: Integer?, ?action_condition: String?, ?action_reference_old_table: Symbol?, ?action_reference_new_table: Symbol?, ?description: String?, ?template: Symbol?) -> void
|
25
26
|
def action_order: -> Integer
|
26
27
|
def has_description?: -> false
|
27
28
|
def differences_descriptions: (Trigger other_trigger) -> Array[String]
|
@@ -52,6 +53,9 @@ module DynamicMigrations
|
|
52
53
|
|
53
54
|
class UnexpectedActionOrderError < StandardError
|
54
55
|
end
|
56
|
+
|
57
|
+
class UnexpectedTemplateError < StandardError
|
58
|
+
end
|
55
59
|
end
|
56
60
|
end
|
57
61
|
end
|
@@ -14,7 +14,7 @@ module DynamicMigrations
|
|
14
14
|
def has_trigger?: (untyped name) -> bool
|
15
15
|
def triggers: -> Array[Trigger]
|
16
16
|
def triggers_hash: -> Hash[Symbol, Trigger]
|
17
|
-
def add_trigger: (Symbol name, action_timing: Symbol, event_manipulation: Symbol, parameters: String, action_orientation: Symbol, function: Function, ?action_order: Integer?, ?action_condition: String?, ?action_reference_old_table: Symbol?, ?action_reference_new_table: Symbol?, ?description: String?) -> Trigger
|
17
|
+
def add_trigger: (Symbol name, action_timing: Symbol, event_manipulation: Symbol, parameters: String, action_orientation: Symbol, function: Function, ?action_order: Integer?, ?action_condition: String?, ?action_reference_old_table: Symbol?, ?action_reference_new_table: Symbol?, ?description: String?, ?template: Symbol?) -> Trigger
|
18
18
|
|
19
19
|
# these come from the table object (which this module is included into)
|
20
20
|
def source: -> database_or_configuration
|
@@ -13,8 +13,9 @@ module DynamicMigrations
|
|
13
13
|
attr_reader deferrable: bool
|
14
14
|
attr_reader initially_deferred: bool
|
15
15
|
attr_reader description: String?
|
16
|
+
attr_reader template: Symbol?
|
16
17
|
|
17
|
-
def initialize: (database_or_configuration source, Table table, Array[Column] columns, Symbol name, String check_clause, ?deferrable: bool, ?initially_deferred: bool, ?description: String?) -> void
|
18
|
+
def initialize: (database_or_configuration source, Table table, Array[Column] columns, Symbol name, String check_clause, ?deferrable: bool, ?initially_deferred: bool, ?description: String?, ?template: Symbol?) -> void
|
18
19
|
def columns: -> Array[Column]
|
19
20
|
def column_names: -> Array[Symbol]
|
20
21
|
def has_description?: -> bool
|
@@ -34,6 +35,10 @@ module DynamicMigrations
|
|
34
35
|
|
35
36
|
class ModuleIncludedIntoUnexpectedTargetError < StandardError
|
36
37
|
end
|
38
|
+
|
39
|
+
class UnexpectedTemplateError < StandardError
|
40
|
+
end
|
41
|
+
|
37
42
|
end
|
38
43
|
end
|
39
44
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dynamic_migrations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Craig Ulliott
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-09-
|
11
|
+
date: 2023-09-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pg
|
@@ -102,8 +102,10 @@ files:
|
|
102
102
|
- lib/dynamic_migrations/postgres/generator/table.rb
|
103
103
|
- lib/dynamic_migrations/postgres/generator/table_migration.rb
|
104
104
|
- lib/dynamic_migrations/postgres/generator/trigger.rb
|
105
|
+
- lib/dynamic_migrations/postgres/generator/trigger_template_base.rb
|
105
106
|
- lib/dynamic_migrations/postgres/generator/unique_constraint.rb
|
106
107
|
- lib/dynamic_migrations/postgres/generator/validation.rb
|
108
|
+
- lib/dynamic_migrations/postgres/generator/validation_template_base.rb
|
107
109
|
- lib/dynamic_migrations/postgres/server.rb
|
108
110
|
- lib/dynamic_migrations/postgres/server/database.rb
|
109
111
|
- lib/dynamic_migrations/postgres/server/database/configured_extensions.rb
|
@@ -192,8 +194,10 @@ files:
|
|
192
194
|
- sig/dynamic_migrations/postgres/generator/table.rbs
|
193
195
|
- sig/dynamic_migrations/postgres/generator/table_migration.rbs
|
194
196
|
- sig/dynamic_migrations/postgres/generator/trigger.rbs
|
197
|
+
- sig/dynamic_migrations/postgres/generator/trigger_template_base.rbs
|
195
198
|
- sig/dynamic_migrations/postgres/generator/unique_constraint.rbs
|
196
199
|
- sig/dynamic_migrations/postgres/generator/validation.rbs
|
200
|
+
- sig/dynamic_migrations/postgres/generator/validation_template_base.rbs
|
197
201
|
- sig/dynamic_migrations/postgres/server.rbs
|
198
202
|
- sig/dynamic_migrations/postgres/server/database.rbs
|
199
203
|
- sig/dynamic_migrations/postgres/server/database/configured_extensions.rbs
|