pg_trunk 0.1.0 → 0.2.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/.github/workflows/ci.yml +4 -15
- data/CHANGELOG.md +21 -0
- data/README.md +3 -1
- data/lib/pg_trunk/core/operation/attributes.rb +1 -1
- data/lib/pg_trunk/core/railtie/custom_types.rb +5 -6
- data/lib/pg_trunk/operations/check_constraints/add_check_constraint.rb +42 -33
- data/lib/pg_trunk/operations/check_constraints/drop_check_constraint.rb +51 -40
- data/lib/pg_trunk/operations/check_constraints/rename_check_constraint.rb +39 -30
- data/lib/pg_trunk/operations/check_constraints/validate_check_constraint.rb +28 -21
- data/lib/pg_trunk/operations/composite_types/change_composite_type.rb +59 -50
- data/lib/pg_trunk/operations/composite_types/create_composite_type.rb +23 -19
- data/lib/pg_trunk/operations/composite_types/drop_composite_type.rb +48 -43
- data/lib/pg_trunk/operations/composite_types/rename_composite_type.rb +15 -12
- data/lib/pg_trunk/operations/domains/change_domain.rb +53 -47
- data/lib/pg_trunk/operations/domains/create_domain.rb +28 -25
- data/lib/pg_trunk/operations/domains/drop_domain.rb +50 -41
- data/lib/pg_trunk/operations/domains/rename_domain.rb +17 -12
- data/lib/pg_trunk/operations/enums/change_enum.rb +37 -32
- data/lib/pg_trunk/operations/enums/create_enum.rb +23 -20
- data/lib/pg_trunk/operations/enums/drop_enum.rb +50 -39
- data/lib/pg_trunk/operations/enums/rename_enum.rb +17 -12
- data/lib/pg_trunk/operations/foreign_keys/add_foreign_key.rb +58 -49
- data/lib/pg_trunk/operations/foreign_keys/drop_foreign_key.rb +57 -48
- data/lib/pg_trunk/operations/foreign_keys/rename_foreign_key.rb +38 -29
- data/lib/pg_trunk/operations/functions/change_function.rb +53 -47
- data/lib/pg_trunk/operations/functions/create_function.rb +75 -64
- data/lib/pg_trunk/operations/functions/drop_function.rb +78 -65
- data/lib/pg_trunk/operations/functions/rename_function.rb +29 -22
- data/lib/pg_trunk/operations/materialized_views/change_materialized_view.rb +65 -55
- data/lib/pg_trunk/operations/materialized_views/create_materialized_view.rb +82 -71
- data/lib/pg_trunk/operations/materialized_views/drop_materialized_view.rb +59 -46
- data/lib/pg_trunk/operations/materialized_views/refresh_materialized_view.rb +29 -24
- data/lib/pg_trunk/operations/materialized_views/rename_materialized_view.rb +29 -22
- data/lib/pg_trunk/operations/procedures/change_procedure.rb +53 -46
- data/lib/pg_trunk/operations/procedures/create_procedure.rb +63 -52
- data/lib/pg_trunk/operations/procedures/drop_procedure.rb +56 -45
- data/lib/pg_trunk/operations/procedures/rename_procedure.rb +29 -22
- data/lib/pg_trunk/operations/rules/base.rb +77 -0
- data/lib/pg_trunk/operations/rules/create_rule.rb +155 -0
- data/lib/pg_trunk/operations/rules/drop_rule.rb +94 -0
- data/lib/pg_trunk/operations/rules/rename_rule.rb +62 -0
- data/lib/pg_trunk/operations/rules.rb +13 -0
- data/lib/pg_trunk/operations/sequences/base.rb +79 -0
- data/lib/pg_trunk/operations/sequences/change_sequence.rb +142 -0
- data/lib/pg_trunk/operations/sequences/create_sequence.rb +180 -0
- data/lib/pg_trunk/operations/sequences/drop_sequence.rb +82 -0
- data/lib/pg_trunk/operations/sequences/rename_sequence.rb +64 -0
- data/lib/pg_trunk/operations/sequences.rb +14 -0
- data/lib/pg_trunk/operations/statistics/create_statistics.rb +67 -56
- data/lib/pg_trunk/operations/statistics/drop_statistics.rb +64 -53
- data/lib/pg_trunk/operations/statistics/rename_statistics.rb +18 -13
- data/lib/pg_trunk/operations/triggers/change_trigger.rb +23 -18
- data/lib/pg_trunk/operations/triggers/create_trigger.rb +63 -54
- data/lib/pg_trunk/operations/triggers/drop_trigger.rb +55 -46
- data/lib/pg_trunk/operations/triggers/rename_trigger.rb +51 -48
- data/lib/pg_trunk/operations/views/change_view.rb +47 -38
- data/lib/pg_trunk/operations/views/create_view.rb +56 -45
- data/lib/pg_trunk/operations/views/drop_view.rb +59 -46
- data/lib/pg_trunk/operations/views/rename_view.rb +27 -20
- data/lib/pg_trunk/operations.rb +2 -0
- data/lib/pg_trunk/version.rb +1 -1
- data/pg_trunk.gemspec +0 -1
- data/spec/operations/rules/create_rule_spec.rb +119 -0
- data/spec/operations/rules/drop_rule_spec.rb +117 -0
- data/spec/operations/rules/rename_rule_spec.rb +148 -0
- data/spec/operations/sequences/change_sequence_spec.rb +134 -0
- data/spec/operations/sequences/create_sequence_spec.rb +156 -0
- data/spec/operations/sequences/drop_sequence_spec.rb +102 -0
- data/spec/operations/sequences/rename_sequence_spec.rb +100 -0
- metadata +22 -68
@@ -1,44 +1,53 @@
|
|
1
1
|
# frozen_string_literal: false
|
2
2
|
|
3
|
-
# @!
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
# @
|
8
|
-
# @
|
9
|
-
# @
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
3
|
+
# @!parse
|
4
|
+
# class ActiveRecord::Migration
|
5
|
+
# # Modify a view
|
6
|
+
# #
|
7
|
+
# # @param [#to_s] name (nil) The qualified name of the view
|
8
|
+
# # @option options [Boolean] :if_exists (false) Suppress the error when the view is absent
|
9
|
+
# # @yield [v] the block with the view's definition
|
10
|
+
# # @yieldparam Object receiver of methods specifying the view
|
11
|
+
# # @return [void]
|
12
|
+
# #
|
13
|
+
# # The operation replaces the view with a new definition(s):
|
14
|
+
# #
|
15
|
+
# # ```ruby
|
16
|
+
# # change_view "admin_users" do |v|
|
17
|
+
# # v.sql_definition: <<~SQL, from: <<~SQL
|
18
|
+
# # SELECT id, name FROM users WHERE admin;
|
19
|
+
# # SQL
|
20
|
+
# # SELECT * FROM users WHERE admin;
|
21
|
+
# # SQL
|
22
|
+
# # end
|
23
|
+
# # ```
|
24
|
+
# #
|
25
|
+
# # For some compatibility to the `scenic` gem, we also support
|
26
|
+
# # adding a definition via its version:
|
27
|
+
# #
|
28
|
+
# # ```ruby
|
29
|
+
# # change_view "admin_users" do |v|
|
30
|
+
# # v.version 2, from: 1
|
31
|
+
# # end
|
32
|
+
# # ```
|
33
|
+
# #
|
34
|
+
# # It is expected, that both `db/views/admin_users_v01.sql`
|
35
|
+
# # and `db/views/admin_users_v02.sql` to contain SQL snippets.
|
36
|
+
# #
|
37
|
+
# # Please, notice that neither deletion of columns,
|
38
|
+
# # nor changing their types is supported by the PostgreSQL.
|
39
|
+
# #
|
40
|
+
# # You can also (re)set a comment describing the view,
|
41
|
+
# # and the check option (either `:local` or `:cascaded`):
|
42
|
+
# #
|
43
|
+
# # ```ruby
|
44
|
+
# # change_view "admin_users" do |v|
|
45
|
+
# # v.check :local, from: :cascaded
|
46
|
+
# # v.comment "Admin users only", from: ""
|
47
|
+
# # end
|
48
|
+
# # ```
|
49
|
+
# def change_view(name, **options, &block); end
|
19
50
|
# end
|
20
|
-
#
|
21
|
-
# For some compatibility to the `scenic` gem, we also support
|
22
|
-
# adding a definition via its version:
|
23
|
-
#
|
24
|
-
# change_view "admin_users" do |v|
|
25
|
-
# v.version 2, from: 1
|
26
|
-
# end
|
27
|
-
#
|
28
|
-
# It is expected, that both `db/views/admin_users_v01.sql`
|
29
|
-
# and `db/views/admin_users_v02.sql` to contain SQL snippets.
|
30
|
-
#
|
31
|
-
# Please, notice that neither deletion of columns,
|
32
|
-
# nor changing their types is supported by the PostgreSQL.
|
33
|
-
#
|
34
|
-
# You can also (re)set a comment describing the view,
|
35
|
-
# and the check option (either `:local` or `:cascaded`):
|
36
|
-
#
|
37
|
-
# change_view "admin_users" do |v|
|
38
|
-
# v.check :local, from: :cascaded
|
39
|
-
# v.comment "Admin users only", from: ""
|
40
|
-
# end
|
41
|
-
|
42
51
|
module PGTrunk::Operations::Views
|
43
52
|
# @private
|
44
53
|
class ChangeView < Base
|
@@ -1,51 +1,62 @@
|
|
1
1
|
# frozen_string_literal: false
|
2
2
|
|
3
|
-
# @!
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
# @
|
8
|
-
# @option [
|
9
|
-
# @option [#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
# @
|
15
|
-
# @
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
3
|
+
# @!parse
|
4
|
+
# class ActiveRecord::Migration
|
5
|
+
# # Create a view
|
6
|
+
# #
|
7
|
+
# # @param [#to_s] name (nil) The qualified name of the view
|
8
|
+
# # @option options [Boolean] :replace_existing (false) If the view should overwrite an existing one
|
9
|
+
# # @option options [#to_s] :sql_definition (nil) The snippet containing the query
|
10
|
+
# # @option options [#to_i] :version (nil)
|
11
|
+
# # The alternative way to set sql_definition by referencing to a file containing the snippet
|
12
|
+
# # @option options [#to_s] :check (nil) Controls the behavior of automatically updatable views
|
13
|
+
# # Supported values: :local, :cascaded
|
14
|
+
# # @option options [#to_s] :comment (nil) The comment describing the view
|
15
|
+
# # @yield [v] the block with the view's definition
|
16
|
+
# # @yieldparam Object receiver of methods specifying the view
|
17
|
+
# # @return [void]
|
18
|
+
# #
|
19
|
+
# # The operation creates the view using its `sql_definition`:
|
20
|
+
# #
|
21
|
+
# # ```ruby
|
22
|
+
# # create_view("views.admin_users", sql_definition: <<~SQL)
|
23
|
+
# # SELECT id, name FROM users WHERE admin;
|
24
|
+
# # SQL
|
25
|
+
# # ```
|
26
|
+
# #
|
27
|
+
# # For compatibility to the `scenic` gem, we also support
|
28
|
+
# # adding a definition via its version:
|
29
|
+
# #
|
30
|
+
# # ```ruby
|
31
|
+
# # create_view "admin_users", version: 1
|
32
|
+
# # ```
|
33
|
+
# #
|
34
|
+
# # It is expected, that a `db/views/admin_users_v01.sql`
|
35
|
+
# # to contain the SQL snippet.
|
36
|
+
# #
|
37
|
+
# # You can also set a comment describing the view, and the check option
|
38
|
+
# # (either `:local` or `:cascaded`):
|
39
|
+
# #
|
40
|
+
# # ```ruby
|
41
|
+
# # create_view "admin_users" do |v|
|
42
|
+
# # v.sql_definition "SELECT id, name FROM users WHERE admin;"
|
43
|
+
# # v.check :local
|
44
|
+
# # v.comment "Admin users only"
|
45
|
+
# # end
|
46
|
+
# # ```
|
47
|
+
# #
|
48
|
+
# # With the `replace_existing: true` option the operation
|
49
|
+
# # would use `CREATE OR REPLACE VIEW` command, so it
|
50
|
+
# # can be used to "update" (or reload) the existing view.
|
51
|
+
# #
|
52
|
+
# # ```ruby
|
53
|
+
# # create_view "admin_users", version: 1, replace_existing: true
|
54
|
+
# # ```
|
55
|
+
# #
|
56
|
+
# # This option makes an operation irreversible due to uncertainty
|
57
|
+
# # of the previous state of the database.
|
58
|
+
# def create_view(name, **options, &block); end
|
38
59
|
# end
|
39
|
-
#
|
40
|
-
# With the `replace_existing: true` option the operation
|
41
|
-
# would use `CREATE OR REPLACE VIEW` command, so it
|
42
|
-
# can be used to "update" (or reload) the existing view.
|
43
|
-
#
|
44
|
-
# create_view "admin_users", version: 1, replace_existing: true
|
45
|
-
#
|
46
|
-
# This option makes an operation irreversible due to uncertainty
|
47
|
-
# of the previous state of the database.
|
48
|
-
|
49
60
|
module PGTrunk::Operations::Views
|
50
61
|
# @private
|
51
62
|
class CreateView < Base
|
@@ -1,52 +1,65 @@
|
|
1
1
|
# frozen_string_literal: false
|
2
2
|
|
3
|
-
# @!
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
# @
|
8
|
-
# @option [Boolean] :
|
9
|
-
# @option [
|
10
|
-
# @option [
|
11
|
-
# @option [#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
# @
|
17
|
-
# @
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
3
|
+
# @!parse
|
4
|
+
# class ActiveRecord::Migration
|
5
|
+
# # Drop a view
|
6
|
+
# #
|
7
|
+
# # @param [#to_s] name (nil) The qualified name of the view
|
8
|
+
# # @option options [Boolean] :replace_existing (false) If the view should overwrite an existing one
|
9
|
+
# # @option options [Boolean] :if_exists (false) Suppress the error when the view is absent
|
10
|
+
# # @option options [Symbol] :force (:restrict) How to process dependent objects (`:cascade` or `:restrict`)
|
11
|
+
# # @option options [#to_s] :sql_definition (nil) The snippet containing the query
|
12
|
+
# # @option options [#to_i] :revert_to_version (nil)
|
13
|
+
# # The alternative way to set sql_definition by referencing to a file containing the snippet
|
14
|
+
# # @option options [#to_s] :check (nil) Controls the behavior of automatically updatable views
|
15
|
+
# # Supported values: :local, :cascaded
|
16
|
+
# # @option options [#to_s] :comment (nil) The comment describing the view
|
17
|
+
# # @yield [v] the block with the view's definition
|
18
|
+
# # @yieldparam Object receiver of methods specifying the view
|
19
|
+
# # @return [void]
|
20
|
+
# #
|
21
|
+
# # The operation drops the existing view identified by its
|
22
|
+
# # qualified name (it can include a schema).
|
23
|
+
# #
|
24
|
+
# # ```ruby
|
25
|
+
# # drop_view "views.admin_users"
|
26
|
+
# # ```
|
27
|
+
# #
|
28
|
+
# # To make the operation invertible, use the same options
|
29
|
+
# # as in the `create_view` operation.
|
30
|
+
# #
|
31
|
+
# # ```ruby
|
32
|
+
# # drop_view "views.admin_users" do |v|
|
33
|
+
# # v.sql_definition "SELECT name, email FROM users WHERE admin;"
|
34
|
+
# # v.check :local
|
35
|
+
# # v.comment "Admin users only"
|
36
|
+
# # end
|
37
|
+
# # ```
|
38
|
+
# #
|
39
|
+
# # You can also use a version-base SQL definition like:
|
40
|
+
# #
|
41
|
+
# # ```ruby
|
42
|
+
# # drop_view "views.admin_users", revert_to_version: 1
|
43
|
+
# # ```
|
44
|
+
# #
|
45
|
+
# # With the `force: :cascade` option the operation would remove
|
46
|
+
# # all the objects which depend on the view.
|
47
|
+
# #
|
48
|
+
# # ```ruby
|
49
|
+
# # drop_view "views.admin_users", force: :cascade
|
50
|
+
# # ```
|
51
|
+
# #
|
52
|
+
# # With the `if_exists: true` option the operation won't fail
|
53
|
+
# # even when the view was absent in the database.
|
54
|
+
# #
|
55
|
+
# # ```ruby
|
56
|
+
# # drop_view "views.admin_users", if_exists: true
|
57
|
+
# # ```
|
58
|
+
# #
|
59
|
+
# # Both options make an operation irreversible due to uncertainty
|
60
|
+
# # of the previous state of the database.
|
61
|
+
# def drop_view(name, **options, &block); end
|
31
62
|
# end
|
32
|
-
#
|
33
|
-
# You can also use a version-base SQL definition like:
|
34
|
-
#
|
35
|
-
# drop_view "views.admin_users", revert_to_version: 1
|
36
|
-
#
|
37
|
-
# With the `force: :cascade` option the operation would remove
|
38
|
-
# all the objects which depend on the view.
|
39
|
-
#
|
40
|
-
# drop_view "views.admin_users", force: :cascade
|
41
|
-
#
|
42
|
-
# With the `if_exists: true` option the operation won't fail
|
43
|
-
# even when the view was absent in the database.
|
44
|
-
#
|
45
|
-
# drop_view "views.admin_users", if_exists: true
|
46
|
-
#
|
47
|
-
# Both options make an operation irreversible due to uncertainty
|
48
|
-
# of the previous state of the database.
|
49
|
-
|
50
63
|
module PGTrunk::Operations::Views
|
51
64
|
# @private
|
52
65
|
class DropView < Base
|
@@ -1,25 +1,32 @@
|
|
1
1
|
# frozen_string_literal: false
|
2
2
|
|
3
|
-
# @!
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
# @
|
8
|
-
# @option [
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
|
3
|
+
# @!parse
|
4
|
+
# class ActiveRecord::Migration
|
5
|
+
# # Change the name and/or schema of a view
|
6
|
+
# #
|
7
|
+
# # @param [#to_s] :name (nil) The qualified name of the view
|
8
|
+
# # @option options [#to_s] :to (nil) The new qualified name for the view
|
9
|
+
# # @option options [Boolean] :if_exists (false) Suppress the error when the view is absent
|
10
|
+
# # @return [void]
|
11
|
+
# #
|
12
|
+
# # A view can be renamed by changing both the name
|
13
|
+
# # and the schema (namespace) it belongs to.
|
14
|
+
# #
|
15
|
+
# # ```ruby
|
16
|
+
# # rename_view "views.admin_users", to: "admins"
|
17
|
+
# # ```
|
18
|
+
# #
|
19
|
+
# # With the `if_exists: true` option, the operation won't fail
|
20
|
+
# # even when the view wasn't existed.
|
21
|
+
# #
|
22
|
+
# # ```ruby
|
23
|
+
# # rename_view "views.admin_users", to: "admins", if_exists: true
|
24
|
+
# # ```
|
25
|
+
# #
|
26
|
+
# # At the same time, the option makes a view irreversible
|
27
|
+
# # due to uncertainty of the previous state of the database.
|
28
|
+
# def rename_view(name, **options); end
|
29
|
+
# end
|
23
30
|
module PGTrunk::Operations::Views
|
24
31
|
# @private
|
25
32
|
class RenameView < Base
|
data/lib/pg_trunk/operations.rb
CHANGED
@@ -9,6 +9,7 @@ module PGTrunk
|
|
9
9
|
require_relative "operations/enums"
|
10
10
|
require_relative "operations/composite_types"
|
11
11
|
require_relative "operations/domains"
|
12
|
+
require_relative "operations/sequences"
|
12
13
|
require_relative "operations/tables"
|
13
14
|
require_relative "operations/views"
|
14
15
|
require_relative "operations/materialized_views"
|
@@ -18,6 +19,7 @@ module PGTrunk
|
|
18
19
|
require_relative "operations/foreign_keys"
|
19
20
|
require_relative "operations/procedures"
|
20
21
|
require_relative "operations/triggers"
|
22
|
+
require_relative "operations/rules"
|
21
23
|
require_relative "operations/statistics"
|
22
24
|
end
|
23
25
|
end
|
data/lib/pg_trunk/version.rb
CHANGED
data/pg_trunk.gemspec
CHANGED
@@ -23,7 +23,6 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.metadata["rubygems_mfa_required"] = "true"
|
24
24
|
|
25
25
|
spec.files = `git ls-files -z`.split("\x0")
|
26
|
-
spec.test_files = spec.files.grep(%r{^spec/})
|
27
26
|
spec.require_paths = ["lib"]
|
28
27
|
|
29
28
|
spec.add_dependency "activerecord", ">= 4.0.0"
|
@@ -0,0 +1,119 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
describe ActiveRecord::Migration, "#create_rule" do
|
4
|
+
before_all do
|
5
|
+
run_migration <<~RUBY
|
6
|
+
create_table :users do |t|
|
7
|
+
t.string :name
|
8
|
+
end
|
9
|
+
|
10
|
+
create_table :user_updates do |t|
|
11
|
+
t.timestamps
|
12
|
+
end
|
13
|
+
RUBY
|
14
|
+
end
|
15
|
+
|
16
|
+
context "with a minimal definition" do
|
17
|
+
let(:migration) do
|
18
|
+
<<~RUBY
|
19
|
+
create_rule "users", "prevent_insertion" do |r|
|
20
|
+
r.event :insert
|
21
|
+
r.kind :instead
|
22
|
+
r.comment "Prevent insertion to users"
|
23
|
+
end
|
24
|
+
RUBY
|
25
|
+
end
|
26
|
+
|
27
|
+
its(:execution) { is_expected.to insert(migration).into_schema }
|
28
|
+
its(:inversion) { is_expected.not_to change_schema }
|
29
|
+
end
|
30
|
+
|
31
|
+
context "with a commands definition" do
|
32
|
+
let(:migration) do
|
33
|
+
<<~RUBY
|
34
|
+
create_rule "users", "count_updates" do |r|
|
35
|
+
r.event :update
|
36
|
+
r.command <<~Q.chomp
|
37
|
+
INSERT INTO user_updates (created_at) VALUES (now())
|
38
|
+
Q
|
39
|
+
r.comment "Count updates of users"
|
40
|
+
end
|
41
|
+
RUBY
|
42
|
+
end
|
43
|
+
|
44
|
+
its(:execution) { is_expected.to insert(migration).into_schema }
|
45
|
+
its(:inversion) { is_expected.not_to change_schema }
|
46
|
+
end
|
47
|
+
|
48
|
+
context "without an explicit name of the rule" do
|
49
|
+
let(:migration) do
|
50
|
+
<<~RUBY
|
51
|
+
create_rule "users" do |r|
|
52
|
+
r.event :update
|
53
|
+
r.command <<~Q.chomp
|
54
|
+
INSERT INTO user_updates (created_at) VALUES (now())
|
55
|
+
Q
|
56
|
+
r.comment "Count updates of users"
|
57
|
+
end
|
58
|
+
RUBY
|
59
|
+
end
|
60
|
+
|
61
|
+
its(:execution) { is_expected.to insert(migration).into_schema }
|
62
|
+
its(:inversion) { is_expected.not_to change_schema }
|
63
|
+
end
|
64
|
+
|
65
|
+
context "with the `replace_existing: true` option" do
|
66
|
+
let(:migration) do
|
67
|
+
<<~RUBY
|
68
|
+
create_rule "users", replace_existing: true do |r|
|
69
|
+
r.event :update
|
70
|
+
r.command <<~Q.chomp
|
71
|
+
INSERT INTO user_updates (created_at) VALUES (now());
|
72
|
+
Q
|
73
|
+
r.comment "Count updates of users"
|
74
|
+
end
|
75
|
+
RUBY
|
76
|
+
end
|
77
|
+
let(:snippet) do
|
78
|
+
<<~RUBY
|
79
|
+
create_rule "users" do |r|
|
80
|
+
r.event :update
|
81
|
+
r.command <<~Q.chomp
|
82
|
+
INSERT INTO user_updates (created_at) VALUES (now())
|
83
|
+
Q
|
84
|
+
r.comment "Count updates of users"
|
85
|
+
end
|
86
|
+
RUBY
|
87
|
+
end
|
88
|
+
|
89
|
+
its(:execution) { is_expected.to insert(snippet).into_schema }
|
90
|
+
it { is_expected.to be_irreversible.because_of(/replace_existing: true/i) }
|
91
|
+
end
|
92
|
+
|
93
|
+
context "without an event" do
|
94
|
+
let(:migration) do
|
95
|
+
<<~RUBY
|
96
|
+
create_rule "users" do |r|
|
97
|
+
r.kind :instead
|
98
|
+
r.comment "Prevent insertion to users"
|
99
|
+
end
|
100
|
+
RUBY
|
101
|
+
end
|
102
|
+
|
103
|
+
it { is_expected.to fail_validation.because(/event can't be blank/i) }
|
104
|
+
end
|
105
|
+
|
106
|
+
context "without a table" do
|
107
|
+
let(:migration) do
|
108
|
+
<<~RUBY
|
109
|
+
create_rule do |r|
|
110
|
+
r.event :insert
|
111
|
+
r.kind :instead
|
112
|
+
r.comment "Prevent insertion to users"
|
113
|
+
end
|
114
|
+
RUBY
|
115
|
+
end
|
116
|
+
|
117
|
+
it { is_expected.to fail_validation.because(/table can't be blank/i) }
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
describe ActiveRecord::Migration, "#drop_rule" do
|
4
|
+
before_all do
|
5
|
+
run_migration <<~RUBY
|
6
|
+
create_table :users do |t|
|
7
|
+
t.string :name
|
8
|
+
end
|
9
|
+
RUBY
|
10
|
+
end
|
11
|
+
before { run_migration(snippet) }
|
12
|
+
|
13
|
+
context "when a rule was named" do
|
14
|
+
let(:snippet) do
|
15
|
+
<<~RUBY
|
16
|
+
create_rule "users", "prevent_insertion" do |r|
|
17
|
+
r.event :insert
|
18
|
+
r.kind :instead
|
19
|
+
r.comment "Prevent insertion to users"
|
20
|
+
end
|
21
|
+
RUBY
|
22
|
+
end
|
23
|
+
|
24
|
+
context "with a full definition" do
|
25
|
+
let(:migration) do
|
26
|
+
<<~RUBY
|
27
|
+
drop_rule "users", "prevent_insertion" do |r|
|
28
|
+
r.event :insert
|
29
|
+
r.kind :instead
|
30
|
+
r.comment "Prevent insertion to users"
|
31
|
+
end
|
32
|
+
RUBY
|
33
|
+
end
|
34
|
+
|
35
|
+
its(:execution) { is_expected.to remove(snippet).from_schema }
|
36
|
+
its(:inversion) { is_expected.not_to change_schema }
|
37
|
+
end
|
38
|
+
|
39
|
+
context "with a name only" do
|
40
|
+
let(:migration) do
|
41
|
+
<<~RUBY
|
42
|
+
drop_rule "users", "prevent_insertion"
|
43
|
+
RUBY
|
44
|
+
end
|
45
|
+
|
46
|
+
its(:execution) { is_expected.to remove(snippet).from_schema }
|
47
|
+
it { is_expected.to be_irreversible.because(/event can't be blank/i) }
|
48
|
+
end
|
49
|
+
|
50
|
+
context "with if_exists: true option" do
|
51
|
+
let(:migration) do
|
52
|
+
<<~RUBY
|
53
|
+
drop_rule "users", "prevent_insertion", if_exists: true do |r|
|
54
|
+
r.event :insert
|
55
|
+
r.kind :instead
|
56
|
+
r.comment "Prevent insertion to users"
|
57
|
+
end
|
58
|
+
RUBY
|
59
|
+
end
|
60
|
+
|
61
|
+
its(:execution) { is_expected.to remove(snippet).from_schema }
|
62
|
+
it { is_expected.to be_irreversible.because_of(/if_exists: true/i) }
|
63
|
+
end
|
64
|
+
|
65
|
+
context "with force: :cascade option" do
|
66
|
+
let(:migration) do
|
67
|
+
<<~RUBY
|
68
|
+
drop_rule "users", "prevent_insertion", force: :cascade do |r|
|
69
|
+
r.event :insert
|
70
|
+
r.kind :instead
|
71
|
+
r.comment "Prevent insertion to users"
|
72
|
+
end
|
73
|
+
RUBY
|
74
|
+
end
|
75
|
+
|
76
|
+
its(:execution) { is_expected.to remove(snippet).from_schema }
|
77
|
+
it { is_expected.to be_irreversible.because_of(/force: :cascade/i) }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
context "when a rule was anonymous" do
|
82
|
+
let(:snippet) do
|
83
|
+
<<~RUBY
|
84
|
+
create_rule "users" do |r|
|
85
|
+
r.event :insert
|
86
|
+
r.kind :instead
|
87
|
+
r.comment "Prevent insertion to users"
|
88
|
+
end
|
89
|
+
RUBY
|
90
|
+
end
|
91
|
+
|
92
|
+
context "with a full definition" do
|
93
|
+
let(:migration) do
|
94
|
+
<<~RUBY
|
95
|
+
drop_rule "users" do |r|
|
96
|
+
r.event :insert
|
97
|
+
r.kind :instead
|
98
|
+
r.comment "Prevent insertion to users"
|
99
|
+
end
|
100
|
+
RUBY
|
101
|
+
end
|
102
|
+
|
103
|
+
its(:execution) { is_expected.to remove(snippet).from_schema }
|
104
|
+
its(:inversion) { is_expected.not_to change_schema }
|
105
|
+
end
|
106
|
+
|
107
|
+
context "with a table only" do
|
108
|
+
let(:migration) do
|
109
|
+
<<~RUBY
|
110
|
+
drop_rule "users"
|
111
|
+
RUBY
|
112
|
+
end
|
113
|
+
|
114
|
+
it { is_expected.to fail_validation.because(/name can't be blank/i) }
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|