fx 0.8.0 → 0.10.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.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +2 -7
  3. data/CHANGELOG.md +150 -0
  4. data/CONTRIBUTING.md +3 -3
  5. data/Gemfile +11 -1
  6. data/README.md +2 -0
  7. data/bin/rake +2 -3
  8. data/bin/rspec +13 -3
  9. data/bin/standardrb +27 -0
  10. data/bin/yard +13 -3
  11. data/fx.gemspec +10 -15
  12. data/lib/fx/adapters/postgres/connection.rb +20 -0
  13. data/lib/fx/adapters/postgres/functions.rb +11 -28
  14. data/lib/fx/adapters/postgres/query_executor.rb +34 -0
  15. data/lib/fx/adapters/postgres/triggers.rb +14 -29
  16. data/lib/fx/adapters/postgres.rb +16 -24
  17. data/lib/fx/command_recorder.rb +87 -6
  18. data/lib/fx/configuration.rb +2 -27
  19. data/lib/fx/definition.rb +16 -6
  20. data/lib/fx/function.rb +3 -3
  21. data/lib/fx/schema_dumper.rb +37 -5
  22. data/lib/fx/statements.rb +231 -6
  23. data/lib/fx/trigger.rb +3 -3
  24. data/lib/fx/version.rb +1 -1
  25. data/lib/fx.rb +30 -12
  26. data/lib/generators/fx/function/function_generator.rb +50 -53
  27. data/lib/generators/fx/function/templates/db/migrate/create_function.erb +1 -1
  28. data/lib/generators/fx/function/templates/db/migrate/update_function.erb +1 -1
  29. data/lib/generators/fx/migration_helper.rb +53 -0
  30. data/lib/generators/fx/name_helper.rb +33 -0
  31. data/lib/generators/fx/trigger/templates/db/migrate/create_trigger.erb +1 -1
  32. data/lib/generators/fx/trigger/templates/db/migrate/update_trigger.erb +1 -1
  33. data/lib/generators/fx/trigger/trigger_generator.rb +44 -67
  34. data/lib/generators/fx/version_helper.rb +55 -0
  35. data/spec/acceptance/user_manages_functions_spec.rb +7 -7
  36. data/spec/acceptance/user_manages_triggers_spec.rb +11 -11
  37. data/spec/acceptance_helper.rb +4 -4
  38. data/spec/dummy/config/application.rb +5 -1
  39. data/spec/features/functions/migrations_spec.rb +5 -5
  40. data/spec/features/functions/revert_spec.rb +5 -5
  41. data/spec/features/triggers/migrations_spec.rb +7 -7
  42. data/spec/features/triggers/revert_spec.rb +9 -9
  43. data/spec/fx/adapters/postgres/functions_spec.rb +33 -30
  44. data/spec/fx/adapters/postgres/query_executor_spec.rb +75 -0
  45. data/spec/fx/adapters/postgres/triggers_spec.rb +41 -38
  46. data/spec/fx/adapters/postgres_spec.rb +155 -115
  47. data/spec/fx/command_recorder_spec.rb +27 -25
  48. data/spec/fx/configuration_spec.rb +20 -9
  49. data/spec/fx/definition_spec.rb +31 -39
  50. data/spec/fx/function_spec.rb +45 -48
  51. data/spec/fx/schema_dumper_spec.rb +169 -0
  52. data/spec/fx/statements_spec.rb +217 -0
  53. data/spec/fx/trigger_spec.rb +37 -40
  54. data/spec/fx_spec.rb +28 -0
  55. data/spec/generators/fx/function/function_generator_spec.rb +11 -11
  56. data/spec/generators/fx/migration_helper_spec.rb +133 -0
  57. data/spec/generators/fx/name_helper_spec.rb +114 -0
  58. data/spec/generators/fx/trigger/trigger_generator_spec.rb +45 -22
  59. data/spec/generators/fx/version_helper_spec.rb +157 -0
  60. data/spec/spec_helper.rb +7 -0
  61. data/spec/support/definition_helpers.rb +2 -6
  62. data/spec/support/generator_setup.rb +46 -5
  63. data/spec/support/warning_helper.rb +5 -0
  64. metadata +40 -165
  65. data/lib/fx/command_recorder/arguments.rb +0 -43
  66. data/lib/fx/command_recorder/function.rb +0 -30
  67. data/lib/fx/command_recorder/trigger.rb +0 -30
  68. data/lib/fx/schema_dumper/function.rb +0 -38
  69. data/lib/fx/schema_dumper/trigger.rb +0 -29
  70. data/lib/fx/statements/function.rb +0 -113
  71. data/lib/fx/statements/trigger.rb +0 -144
  72. data/spec/fx/command_recorder/arguments_spec.rb +0 -41
  73. data/spec/fx/schema_dumper/function_spec.rb +0 -78
  74. data/spec/fx/schema_dumper/trigger_spec.rb +0 -40
  75. data/spec/fx/statements/function_spec.rb +0 -103
  76. data/spec/fx/statements/trigger_spec.rb +0 -132
@@ -1,42 +1,49 @@
1
1
  require "rails/generators"
2
2
  require "rails/generators/active_record"
3
+ require "generators/fx/version_helper"
4
+ require "generators/fx/migration_helper"
5
+ require "generators/fx/name_helper"
3
6
 
4
7
  module Fx
5
8
  module Generators
6
9
  # @api private
7
10
  class FunctionGenerator < Rails::Generators::NamedBase
8
11
  include Rails::Generators::Migration
12
+
9
13
  source_root File.expand_path("../templates", __FILE__)
10
14
 
15
+ DEFINITION_PATH = %w[db functions].freeze
16
+
11
17
  class_option :migration, type: :boolean
12
18
 
13
19
  def create_functions_directory
14
- unless function_definition_path.exist?
15
- empty_directory(function_definition_path)
16
- end
20
+ return if function_definition_path.exist?
21
+
22
+ empty_directory(function_definition_path)
17
23
  end
18
24
 
19
25
  def create_function_definition
20
- if creating_new_function?
21
- create_file definition.path
26
+ if version_helper.creating_new?
27
+ create_file(definition.path)
22
28
  else
23
- copy_file previous_definition.full_path, definition.full_path
29
+ copy_file(previous_definition.full_path, definition.full_path)
24
30
  end
25
31
  end
26
32
 
27
33
  def create_migration_file
28
- return if skip_migration_creation?
29
- if updating_existing_function?
30
- migration_template(
31
- "db/migrate/update_function.erb",
32
- "db/migrate/update_function_#{file_name}_to_version_#{version}.rb"
33
- )
34
- else
35
- migration_template(
36
- "db/migrate/create_function.erb",
37
- "db/migrate/create_function_#{file_name}.rb"
38
- )
39
- end
34
+ return if migration_helper.skip_creation?
35
+
36
+ template_info = migration_helper.migration_template_info(
37
+ object_type: :function,
38
+ file_name: file_name,
39
+ updating_existing: version_helper.updating_existing?,
40
+ version: version_helper.current_version
41
+ )
42
+
43
+ migration_template(
44
+ template_info.fetch(:template),
45
+ template_info.fetch(:filename)
46
+ )
40
47
  end
41
48
 
42
49
  def self.next_migration_number(dir)
@@ -45,75 +52,65 @@ module Fx
45
52
 
46
53
  no_tasks do
47
54
  def previous_version
48
- @_previous_version ||= Dir.entries(function_definition_path)
49
- .map { |name| version_regex.match(name).try(:[], "version").to_i }
50
- .max
55
+ version_helper.previous_version
51
56
  end
52
57
 
53
58
  def version
54
- @_version ||= previous_version.next
59
+ version_helper.current_version
55
60
  end
56
61
 
57
62
  def migration_class_name
58
- if updating_existing_function?
59
- "UpdateFunction#{class_name}ToVersion#{version}"
63
+ if version_helper.updating_existing?
64
+ migration_helper.update_migration_class_name(
65
+ object_type: :function,
66
+ class_name: class_name,
67
+ version: version
68
+ )
60
69
  else
61
70
  super
62
71
  end
63
72
  end
64
73
 
65
- def activerecord_migration_class
66
- if ActiveRecord::Migration.respond_to?(:current_version)
67
- "ActiveRecord::Migration[#{ActiveRecord::Migration.current_version}]"
68
- else
69
- "ActiveRecord::Migration"
70
- end
74
+ def active_record_migration_class
75
+ migration_helper.active_record_migration_class
71
76
  end
72
77
 
73
78
  def formatted_name
74
- if singular_name.include?(".")
75
- "\"#{singular_name}\""
76
- else
77
- ":#{singular_name}"
78
- end
79
+ NameHelper.format_for_migration(singular_name)
79
80
  end
80
81
  end
81
82
 
82
83
  private
83
84
 
84
85
  def function_definition_path
85
- @_function_definition_path ||= Rails.root.join(*%w[db functions])
86
- end
87
-
88
- def version_regex
89
- /\A#{file_name}_v(?<version>\d+)\.sql\z/
86
+ @_function_definition_path ||= Rails.root.join(*DEFINITION_PATH)
90
87
  end
91
88
 
92
- def updating_existing_function?
93
- previous_version > 0
89
+ def version_helper
90
+ @_version_helper ||= Fx::Generators::VersionHelper.new(
91
+ file_name: file_name,
92
+ definition_path: function_definition_path
93
+ )
94
94
  end
95
95
 
96
- def creating_new_function?
97
- previous_version == 0
96
+ def migration_helper
97
+ @_migration_helper ||= Fx::Generators::MigrationHelper.new(options)
98
98
  end
99
99
 
100
100
  def definition
101
- Fx::Definition.new(name: file_name, version: version)
101
+ version_helper.definition_for_version(version: version, type: :function)
102
102
  end
103
103
 
104
104
  def previous_definition
105
- Fx::Definition.new(name: file_name, version: previous_version)
105
+ version_helper.definition_for_version(version: previous_version, type: :function)
106
106
  end
107
107
 
108
- # Skip creating migration file if:
109
- # - migrations option is nil or false
110
- def skip_migration_creation?
111
- !migration
108
+ def updating_existing_function?
109
+ version_helper.updating_existing?
112
110
  end
113
111
 
114
- # True unless explicitly false
115
- def migration
116
- options[:migration] != false
112
+ def creating_new_function?
113
+ version_helper.creating_new?
117
114
  end
118
115
  end
119
116
  end
@@ -1,4 +1,4 @@
1
- class <%= migration_class_name %> < <%= activerecord_migration_class %>
1
+ class <%= migration_class_name %> < <%= active_record_migration_class %>
2
2
  def change
3
3
  create_function <%= formatted_name %>
4
4
  end
@@ -1,4 +1,4 @@
1
- class <%= migration_class_name %> < <%= activerecord_migration_class %>
1
+ class <%= migration_class_name %> < <%= active_record_migration_class %>
2
2
  def change
3
3
  update_function <%= formatted_name %>, version: <%= version %>, revert_to_version: <%= previous_version %>
4
4
  end
@@ -0,0 +1,53 @@
1
+ module Fx
2
+ module Generators
3
+ # @api private
4
+ class MigrationHelper
5
+ def initialize(options)
6
+ @options = options
7
+ end
8
+
9
+ def skip_creation?
10
+ !should_create_migration?
11
+ end
12
+
13
+ def active_record_migration_class
14
+ if ActiveRecord::Migration.respond_to?(:current_version)
15
+ "ActiveRecord::Migration[#{ActiveRecord::Migration.current_version}]"
16
+ else
17
+ "ActiveRecord::Migration"
18
+ end
19
+ end
20
+
21
+ def update_migration_class_name(object_type:, class_name:, version:)
22
+ "Update#{object_type.capitalize}#{class_name}ToVersion#{version}"
23
+ end
24
+
25
+ def migration_template_info(
26
+ object_type:,
27
+ file_name:,
28
+ updating_existing:,
29
+ version:
30
+ )
31
+ if updating_existing
32
+ {
33
+ template: "db/migrate/update_#{object_type}.erb",
34
+ filename: "db/migrate/update_#{object_type}_#{file_name}_to_version_#{version}.rb"
35
+ }
36
+ else
37
+ {
38
+ template: "db/migrate/create_#{object_type}.erb",
39
+ filename: "db/migrate/create_#{object_type}_#{file_name}.rb"
40
+ }
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ attr_reader :options
47
+
48
+ def should_create_migration?
49
+ options.fetch(:migration, true)
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,33 @@
1
+ module Fx
2
+ module Generators
3
+ # @api private
4
+ class NameHelper
5
+ def self.format_for_migration(name)
6
+ if name.include?(".")
7
+ "\"#{name}\""
8
+ else
9
+ ":#{name}"
10
+ end
11
+ end
12
+
13
+ def self.format_table_name_from_hash(table_hash)
14
+ name = table_hash["table_name"] || table_hash["on"]
15
+
16
+ if name.nil?
17
+ raise(
18
+ ArgumentError,
19
+ "Either `table_name:NAME` or `on:NAME` must be specified"
20
+ )
21
+ end
22
+
23
+ format_for_migration(name)
24
+ end
25
+
26
+ def self.validate_and_format(name)
27
+ raise ArgumentError, "Name cannot be blank" if name.blank?
28
+
29
+ format_for_migration(name)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,4 +1,4 @@
1
- class <%= migration_class_name %> < <%= activerecord_migration_class %>
1
+ class <%= migration_class_name %> < <%= active_record_migration_class %>
2
2
  def change
3
3
  create_trigger <%= formatted_name %>, on: <%= formatted_table_name %>
4
4
  end
@@ -1,4 +1,4 @@
1
- class <%= migration_class_name %> < <%= activerecord_migration_class %>
1
+ class <%= migration_class_name %> < <%= active_record_migration_class %>
2
2
  def change
3
3
  update_trigger <%= formatted_name %>, on: <%= formatted_table_name %>, version: <%= version %>, revert_to_version: <%= previous_version %>
4
4
  end
@@ -1,39 +1,43 @@
1
1
  require "rails/generators"
2
2
  require "rails/generators/active_record"
3
+ require "generators/fx/version_helper"
4
+ require "generators/fx/migration_helper"
5
+ require "generators/fx/name_helper"
3
6
 
4
7
  module Fx
5
8
  module Generators
6
9
  # @api private
7
10
  class TriggerGenerator < Rails::Generators::NamedBase
8
11
  include Rails::Generators::Migration
12
+
9
13
  source_root File.expand_path("../templates", __FILE__)
10
14
  argument :table_name, type: :hash, required: true
11
15
 
16
+ DEFINITION_PATH = %w[db triggers].freeze
17
+
12
18
  class_option :migration, type: :boolean
13
19
 
14
20
  def create_triggers_directory
15
- unless trigger_definition_path.exist?
16
- empty_directory(trigger_definition_path)
17
- end
21
+ return if trigger_definition_path.exist?
22
+
23
+ empty_directory(trigger_definition_path)
18
24
  end
19
25
 
20
26
  def create_trigger_definition
21
- create_file definition.path
27
+ create_file(definition.path)
22
28
  end
23
29
 
24
30
  def create_migration_file
25
- return if skip_migration_creation?
26
- if updating_existing_trigger?
27
- migration_template(
28
- "db/migrate/update_trigger.erb",
29
- "db/migrate/update_trigger_#{file_name}_to_version_#{version}.rb"
30
- )
31
- else
32
- migration_template(
33
- "db/migrate/create_trigger.erb",
34
- "db/migrate/create_trigger_#{file_name}.rb"
35
- )
36
- end
31
+ return if migration_helper.skip_creation?
32
+
33
+ template_info = migration_helper.migration_template_info(
34
+ object_type: :trigger,
35
+ file_name: file_name,
36
+ updating_existing: version_helper.updating_existing?,
37
+ version: version_helper.current_version
38
+ )
39
+
40
+ migration_template(template_info[:template], template_info[:filename])
37
41
  end
38
42
 
39
43
  def self.next_migration_number(dir)
@@ -42,88 +46,61 @@ module Fx
42
46
 
43
47
  no_tasks do
44
48
  def previous_version
45
- @_previous_version ||= Dir.entries(trigger_definition_path)
46
- .map { |name| version_regex.match(name).try(:[], "version").to_i }
47
- .max
49
+ version_helper.previous_version
48
50
  end
49
51
 
50
52
  def version
51
- @_version ||= previous_version.next
53
+ version_helper.current_version
52
54
  end
53
55
 
54
56
  def migration_class_name
55
- if updating_existing_trigger?
56
- "UpdateTrigger#{class_name}ToVersion#{version}"
57
+ if version_helper.updating_existing?
58
+ migration_helper.update_migration_class_name(
59
+ object_type: :trigger,
60
+ class_name: class_name,
61
+ version: version
62
+ )
57
63
  else
58
64
  super
59
65
  end
60
66
  end
61
67
 
62
- def activerecord_migration_class
63
- if ActiveRecord::Migration.respond_to?(:current_version)
64
- "ActiveRecord::Migration[#{ActiveRecord::Migration.current_version}]"
65
- else
66
- "ActiveRecord::Migration"
67
- end
68
+ def active_record_migration_class
69
+ migration_helper.active_record_migration_class
68
70
  end
69
71
 
70
72
  def formatted_name
71
- if singular_name.include?(".")
72
- "\"#{singular_name}\""
73
- else
74
- ":#{singular_name}"
75
- end
73
+ NameHelper.format_for_migration(singular_name)
76
74
  end
77
75
 
78
76
  def formatted_table_name
79
- name = table_name["table_name"] || table_name["on"]
80
-
81
- if name.nil?
82
- raise(
83
- ArgumentError,
84
- "Either `table_name:NAME` or `on:NAME` must be specified"
85
- )
86
- end
87
-
88
- if name.include?(".")
89
- "\"#{name}\""
90
- else
91
- ":#{name}"
92
- end
77
+ NameHelper.format_table_name_from_hash(table_name)
93
78
  end
94
79
  end
95
80
 
96
81
  private
97
82
 
98
- def version_regex
99
- /\A#{file_name}_v(?<version>\d+)\.sql\z/
100
- end
101
-
102
- def updating_existing_trigger?
103
- previous_version > 0
83
+ def trigger_definition_path
84
+ @_trigger_definition_path ||= Rails.root.join(*DEFINITION_PATH)
104
85
  end
105
86
 
106
- def definition
107
- Fx::Definition.new(
108
- name: file_name,
109
- version: version,
110
- type: "trigger"
87
+ def version_helper
88
+ @_version_helper ||= Fx::Generators::VersionHelper.new(
89
+ file_name: file_name,
90
+ definition_path: trigger_definition_path
111
91
  )
112
92
  end
113
93
 
114
- def trigger_definition_path
115
- @_trigger_definition_path ||= Rails.root.join("db", "triggers")
94
+ def migration_helper
95
+ @_migration_helper ||= Fx::Generators::MigrationHelper.new(options)
116
96
  end
117
97
 
118
- # Skip creating migration file if:
119
- # - migrations option is nil or false
120
- def skip_migration_creation?
121
- !migration
98
+ def definition
99
+ version_helper.definition_for_version(version: version, type: :trigger)
122
100
  end
123
101
 
124
- # True unless explicitly false
125
- def migration
126
- options[:migration] != false
102
+ def updating_existing_trigger?
103
+ version_helper.updating_existing?
127
104
  end
128
105
  end
129
106
  end
@@ -0,0 +1,55 @@
1
+ module Fx
2
+ module Generators
3
+ # @api private
4
+ class VersionHelper
5
+ def initialize(file_name:, definition_path:)
6
+ @file_name = file_name
7
+ @definition_path = definition_path
8
+ end
9
+
10
+ def previous_version
11
+ @previous_version ||= existing_versions.max || 0
12
+ end
13
+
14
+ def current_version
15
+ previous_version.next
16
+ end
17
+
18
+ def updating_existing?
19
+ previous_version > 0
20
+ end
21
+
22
+ def creating_new?
23
+ previous_version == 0
24
+ end
25
+
26
+ def definition_for_version(version:, type:)
27
+ case type
28
+ when :function
29
+ Fx::Definition.function(name: file_name, version: version)
30
+ when :trigger
31
+ Fx::Definition.trigger(name: file_name, version: version)
32
+ else
33
+ raise(
34
+ ArgumentError,
35
+ "Unknown type: #{type}. Must be :function or :trigger"
36
+ )
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ VERSION_PATTERN = /v(\d+)/
43
+ private_constant :VERSION_PATTERN
44
+
45
+ attr_reader :file_name, :definition_path
46
+
47
+ def existing_versions
48
+ Dir
49
+ .glob("#{file_name}_v*.sql", base: definition_path)
50
+ .map { |file| file[VERSION_PATTERN, 1].to_i }
51
+ .compact
52
+ end
53
+ end
54
+ end
55
+ end
@@ -1,16 +1,16 @@
1
1
  require "acceptance_helper"
2
2
 
3
- describe "User manages functions" do
3
+ RSpec.describe "User manages functions" do
4
4
  it "handles simple functions" do
5
5
  successfully "rails generate fx:function test"
6
- write_function_definition "test_v01", <<-EOS
6
+ write_function_definition "test_v01", <<~SQL
7
7
  CREATE OR REPLACE FUNCTION test()
8
8
  RETURNS text AS $$
9
9
  BEGIN
10
10
  RETURN 'test';
11
11
  END;
12
12
  $$ LANGUAGE plpgsql;
13
- EOS
13
+ SQL
14
14
  successfully "rake db:migrate"
15
15
 
16
16
  result = execute("SELECT * FROM test() AS result")
@@ -21,14 +21,14 @@ describe "User manages functions" do
21
21
  "db/functions/test_v01.sql",
22
22
  "db/functions/test_v02.sql"
23
23
  )
24
- write_function_definition "test_v02", <<-EOS
24
+ write_function_definition "test_v02", <<~SQL
25
25
  CREATE OR REPLACE FUNCTION test()
26
26
  RETURNS text AS $$
27
27
  BEGIN
28
28
  RETURN 'testest';
29
29
  END;
30
30
  $$ LANGUAGE plpgsql;
31
- EOS
31
+ SQL
32
32
  successfully "rake db:migrate"
33
33
 
34
34
  result = execute("SELECT * FROM test() AS result")
@@ -37,14 +37,14 @@ describe "User manages functions" do
37
37
 
38
38
  it "handles functions with arguments" do
39
39
  successfully "rails generate fx:function adder"
40
- write_function_definition "adder_v01", <<-EOS
40
+ write_function_definition "adder_v01", <<~SQL
41
41
  CREATE FUNCTION adder(x int, y int)
42
42
  RETURNS int AS $$
43
43
  BEGIN
44
44
  RETURN $1 + $2;
45
45
  END;
46
46
  $$ LANGUAGE plpgsql;
47
- EOS
47
+ SQL
48
48
  successfully "rake db:migrate"
49
49
 
50
50
  result = execute("SELECT * FROM adder(1, 2) AS result")
@@ -1,10 +1,10 @@
1
1
  require "acceptance_helper"
2
2
 
3
- describe "User manages triggers" do
3
+ RSpec.describe "User manages triggers" do
4
4
  it "handles simple triggers" do
5
5
  successfully "rails generate model user name:string upper_name:string"
6
6
  successfully "rails generate fx:function uppercase_users_name"
7
- write_function_definition "uppercase_users_name_v01", <<-EOS
7
+ write_function_definition "uppercase_users_name_v01", <<~SQL
8
8
  CREATE OR REPLACE FUNCTION uppercase_users_name()
9
9
  RETURNS trigger AS $$
10
10
  BEGIN
@@ -12,38 +12,38 @@ describe "User manages triggers" do
12
12
  RETURN NEW;
13
13
  END;
14
14
  $$ LANGUAGE plpgsql;
15
- EOS
15
+ SQL
16
16
  successfully "rails generate fx:trigger uppercase_users_name table_name:users"
17
- write_trigger_definition "uppercase_users_name_v01", <<-EOS
17
+ write_trigger_definition "uppercase_users_name_v01", <<~SQL
18
18
  CREATE TRIGGER uppercase_users_name
19
19
  BEFORE INSERT ON users
20
20
  FOR EACH ROW
21
21
  EXECUTE FUNCTION uppercase_users_name();
22
- EOS
22
+ SQL
23
23
  successfully "rake db:migrate"
24
24
 
25
- execute <<-EOS
25
+ execute <<~SQL
26
26
  INSERT INTO users
27
27
  (name, created_at, updated_at)
28
28
  VALUES
29
29
  ('Bob', NOW(), NOW());
30
- EOS
30
+ SQL
31
31
  result = execute("SELECT upper_name FROM users WHERE name = 'Bob';")
32
32
  expect(result).to eq("upper_name" => "BOB")
33
33
 
34
34
  successfully "rails generate fx:trigger uppercase_users_name table_name:users"
35
- write_trigger_definition "uppercase_users_name_v02", <<-EOS
35
+ write_trigger_definition "uppercase_users_name_v02", <<~SQL
36
36
  CREATE TRIGGER uppercase_users_name
37
37
  BEFORE UPDATE ON users
38
38
  FOR EACH ROW
39
39
  EXECUTE FUNCTION uppercase_users_name();
40
- EOS
40
+ SQL
41
41
  successfully "rake db:migrate"
42
- execute <<-EOS
42
+ execute <<~SQL
43
43
  UPDATE users
44
44
  SET name = 'Alice'
45
45
  WHERE id = 1;
46
- EOS
46
+ SQL
47
47
 
48
48
  result = execute("SELECT upper_name FROM users WHERE name = 'Alice';")
49
49
  expect(result).to eq("upper_name" => "ALICE")
@@ -11,10 +11,10 @@ RSpec.configure do |config|
11
11
 
12
12
  config.before(:suite) do
13
13
  Dir.chdir("spec/dummy") do
14
- system <<-CMD
14
+ system <<~CMD
15
15
  git init -b master 1>/dev/null &&
16
- git config user.email "fx@example.com"
17
- git config user.name "Fx"
16
+ git config user.email "fx@example.com" &&
17
+ git config user.name "Fx" &&
18
18
  git add -A &&
19
19
  git commit --no-gpg-sign --message 'initial' 1>/dev/null
20
20
  CMD
@@ -24,7 +24,7 @@ RSpec.configure do |config|
24
24
  config.after(:suite) do
25
25
  Dir.chdir("spec/dummy") do
26
26
  ActiveRecord::Base.connection.disconnect!
27
- system <<-CMD
27
+ system <<~CMD
28
28
  echo &&
29
29
  rake db:environment:set db:drop db:create 1>/dev/null &&
30
30
  git add -A &&
@@ -12,6 +12,10 @@ module Dummy
12
12
  config.eager_load = false
13
13
  config.active_support.deprecation = :stderr
14
14
 
15
- config.active_record.legacy_connection_handling = false
15
+ config.load_defaults 7.0
16
+
17
+ if Rails.version >= "8.0"
18
+ config.active_support.to_time_preserves_timezone = :zone
19
+ end
16
20
  end
17
21
  end