chrono_model 1.2.2 → 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.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +19 -20
  3. data/README.md +62 -40
  4. data/lib/active_record/connection_adapters/chronomodel_adapter.rb +17 -11
  5. data/lib/active_record/tasks/chronomodel_database_tasks.rb +64 -23
  6. data/lib/chrono_model/adapter/ddl.rb +168 -153
  7. data/lib/chrono_model/adapter/indexes.rb +99 -94
  8. data/lib/chrono_model/adapter/migrations.rb +81 -104
  9. data/lib/chrono_model/adapter/migrations_modules/legacy.rb +41 -0
  10. data/lib/chrono_model/adapter/migrations_modules/stable.rb +41 -0
  11. data/lib/chrono_model/adapter/tsrange.rb +20 -5
  12. data/lib/chrono_model/adapter/upgrade.rb +89 -91
  13. data/lib/chrono_model/adapter.rb +64 -31
  14. data/lib/chrono_model/chrono.rb +17 -0
  15. data/lib/chrono_model/conversions.rb +15 -9
  16. data/lib/chrono_model/db_console.rb +9 -0
  17. data/lib/chrono_model/json.rb +9 -6
  18. data/lib/chrono_model/patches/as_of_time_holder.rb +2 -2
  19. data/lib/chrono_model/patches/as_of_time_relation.rb +2 -2
  20. data/lib/chrono_model/patches/association.rb +15 -12
  21. data/lib/chrono_model/patches/batches.rb +17 -0
  22. data/lib/chrono_model/patches/db_console.rb +20 -4
  23. data/lib/chrono_model/patches/join_node.rb +4 -4
  24. data/lib/chrono_model/patches/preloader.rb +41 -11
  25. data/lib/chrono_model/patches/relation.rb +53 -8
  26. data/lib/chrono_model/patches.rb +3 -1
  27. data/lib/chrono_model/railtie.rb +29 -24
  28. data/lib/chrono_model/time_gate.rb +3 -3
  29. data/lib/chrono_model/time_machine/history_model.rb +65 -31
  30. data/lib/chrono_model/time_machine/time_query.rb +65 -49
  31. data/lib/chrono_model/time_machine/timeline.rb +52 -28
  32. data/lib/chrono_model/time_machine.rb +66 -25
  33. data/lib/chrono_model/utilities.rb +3 -3
  34. data/lib/chrono_model/version.rb +3 -1
  35. data/lib/chrono_model.rb +31 -36
  36. metadata +39 -136
  37. data/.gitignore +0 -21
  38. data/.rspec +0 -2
  39. data/.travis.yml +0 -41
  40. data/Gemfile +0 -4
  41. data/README.sql +0 -161
  42. data/Rakefile +0 -25
  43. data/chrono_model.gemspec +0 -33
  44. data/gemfiles/rails_5.0.gemfile +0 -6
  45. data/gemfiles/rails_5.1.gemfile +0 -6
  46. data/gemfiles/rails_5.2.gemfile +0 -6
  47. data/spec/aruba/dbconsole_spec.rb +0 -25
  48. data/spec/aruba/fixtures/database_with_default_username_and_password.yml +0 -14
  49. data/spec/aruba/fixtures/database_without_username_and_password.yml +0 -11
  50. data/spec/aruba/fixtures/empty_structure.sql +0 -27
  51. data/spec/aruba/fixtures/migrations/56/20160812190335_create_impressions.rb +0 -10
  52. data/spec/aruba/fixtures/migrations/56/20171115195229_add_temporal_extension_to_impressions.rb +0 -10
  53. data/spec/aruba/fixtures/railsapp/config/application.rb +0 -17
  54. data/spec/aruba/fixtures/railsapp/config/boot.rb +0 -5
  55. data/spec/aruba/fixtures/railsapp/config/environments/development.rb +0 -38
  56. data/spec/aruba/migrations_spec.rb +0 -48
  57. data/spec/aruba/rake_task_spec.rb +0 -71
  58. data/spec/chrono_model/adapter/base_spec.rb +0 -157
  59. data/spec/chrono_model/adapter/ddl_spec.rb +0 -243
  60. data/spec/chrono_model/adapter/indexes_spec.rb +0 -72
  61. data/spec/chrono_model/adapter/migrations_spec.rb +0 -312
  62. data/spec/chrono_model/conversions_spec.rb +0 -43
  63. data/spec/chrono_model/history_models_spec.rb +0 -32
  64. data/spec/chrono_model/json_ops_spec.rb +0 -59
  65. data/spec/chrono_model/time_machine/as_of_spec.rb +0 -188
  66. data/spec/chrono_model/time_machine/changes_spec.rb +0 -50
  67. data/spec/chrono_model/time_machine/counter_cache_race_spec.rb +0 -46
  68. data/spec/chrono_model/time_machine/default_scope_spec.rb +0 -37
  69. data/spec/chrono_model/time_machine/history_spec.rb +0 -104
  70. data/spec/chrono_model/time_machine/keep_cool_spec.rb +0 -27
  71. data/spec/chrono_model/time_machine/manipulations_spec.rb +0 -84
  72. data/spec/chrono_model/time_machine/model_identification_spec.rb +0 -46
  73. data/spec/chrono_model/time_machine/sequence_spec.rb +0 -74
  74. data/spec/chrono_model/time_machine/sti_spec.rb +0 -100
  75. data/spec/chrono_model/time_machine/time_query_spec.rb +0 -261
  76. data/spec/chrono_model/time_machine/timeline_spec.rb +0 -63
  77. data/spec/chrono_model/time_machine/timestamps_spec.rb +0 -43
  78. data/spec/chrono_model/time_machine/transactions_spec.rb +0 -69
  79. data/spec/config.travis.yml +0 -5
  80. data/spec/config.yml.example +0 -9
  81. data/spec/spec_helper.rb +0 -33
  82. data/spec/support/adapter/helpers.rb +0 -53
  83. data/spec/support/adapter/structure.rb +0 -44
  84. data/spec/support/aruba.rb +0 -44
  85. data/spec/support/connection.rb +0 -70
  86. data/spec/support/matchers/base.rb +0 -56
  87. data/spec/support/matchers/column.rb +0 -99
  88. data/spec/support/matchers/function.rb +0 -79
  89. data/spec/support/matchers/index.rb +0 -69
  90. data/spec/support/matchers/schema.rb +0 -39
  91. data/spec/support/matchers/table.rb +0 -275
  92. data/spec/support/time_machine/helpers.rb +0 -47
  93. data/spec/support/time_machine/structure.rb +0 -111
  94. data/sql/json_ops.sql +0 -56
  95. data/sql/uninstall-json_ops.sql +0 -24
@@ -1,56 +0,0 @@
1
- module ChronoTest::Matchers
2
- class Base
3
- include ActiveRecord::Sanitization::ClassMethods
4
-
5
- attr_reader :table
6
-
7
- def matches?(table)
8
- table = table.table_name if table.respond_to?(:table_name)
9
- @table = table
10
- end
11
- private :matches? # This is an abstract class
12
-
13
- def failure_message_for_should_not
14
- failure_message_for_should.gsub(/to /, 'to not ')
15
- end
16
-
17
- protected
18
-
19
- def connection
20
- ChronoTest.connection
21
- end
22
-
23
- def temporal_schema
24
- ChronoModel::Adapter::TEMPORAL_SCHEMA
25
- end
26
-
27
- def history_schema
28
- ChronoModel::Adapter::HISTORY_SCHEMA
29
- end
30
-
31
- def public_schema
32
- 'public'
33
- end
34
-
35
- def select_value(sql, binds, name = nil)
36
- result = exec_query(sql, binds, name || 'select_value')
37
- result.rows.first.try(:[], 0)
38
- end
39
-
40
- def select_values(sql, binds, name = nil)
41
- result = exec_query(sql, binds, name || 'select_values')
42
- result.rows.map(&:first)
43
- end
44
-
45
- def select_rows(sql, binds, name = nil)
46
- exec_query(sql, binds, name || 'select_rows').rows
47
- end
48
-
49
- private
50
- def exec_query(sql, binds, name)
51
- sql = sanitize_sql_array([ sql, *Array.wrap(binds) ])
52
- connection.exec_query(sql, name)
53
- end
54
- end
55
-
56
- end
@@ -1,99 +0,0 @@
1
- module ChronoTest::Matchers
2
-
3
- module Column
4
- class HaveColumns < ChronoTest::Matchers::Base
5
- def initialize(columns, schema = 'public')
6
- @columns = columns
7
- @schema = schema
8
- end
9
-
10
- def description
11
- 'have columns'
12
- end
13
-
14
- def matches?(table)
15
- super(table)
16
-
17
- @matches = @columns.inject({}) do |h, (name, type)|
18
- h.update([name, type] => has_column?(name, type))
19
- end
20
-
21
- @matches.values.all?
22
- end
23
-
24
- def failure_message
25
- message_matches("expected #{@schema}.#{table} to have")
26
- end
27
-
28
- def failure_message_when_negated
29
- message_matches("expected #{@schema}.#{table} to not have")
30
- end
31
-
32
- protected
33
- def has_column?(name, type)
34
- column_type(name) == [name, type]
35
- end
36
-
37
- def column_type(name)
38
- table = "#{@schema}.#{self.table}"
39
-
40
- select_rows(<<-SQL, [table, name], 'Check column').first
41
- SELECT attname, FORMAT_TYPE(atttypid, atttypmod)
42
- FROM pg_attribute
43
- WHERE attrelid = ?::regclass::oid
44
- AND attname = ?
45
- SQL
46
- end
47
-
48
- private
49
- def message_matches(message)
50
- (message << ' ').tap do |message|
51
- message << @matches.map do |(name, type), match|
52
- "a #{name}(#{type}) column" unless match
53
- end.compact.to_sentence
54
- end
55
- end
56
- end
57
-
58
- def have_columns(*args)
59
- HaveColumns.new(*args)
60
- end
61
-
62
-
63
- class HaveTemporalColumns < HaveColumns
64
- def initialize(columns)
65
- super(columns, temporal_schema)
66
- end
67
- end
68
-
69
- def have_temporal_columns(*args)
70
- HaveTemporalColumns.new(*args)
71
- end
72
-
73
-
74
- class HaveHistoryColumns < HaveColumns
75
- def initialize(columns)
76
- super(columns, history_schema)
77
- end
78
- end
79
-
80
- def have_history_columns(*args)
81
- HaveHistoryColumns.new(*args)
82
- end
83
-
84
-
85
- class HaveHistoryExtraColumns < HaveColumns
86
- def initialize
87
- super([
88
- ['validity', 'tsrange'],
89
- ['recorded_at', 'timestamp without time zone'],
90
- ['hid', 'integer']
91
- ], history_schema)
92
- end
93
- end
94
-
95
- def have_history_extra_columns
96
- HaveHistoryExtraColumns.new
97
- end
98
- end
99
- end
@@ -1,79 +0,0 @@
1
- module ChronoTest::Matchers
2
-
3
- module Column
4
- class HaveFunctions < ChronoTest::Matchers::Base
5
- def initialize(functions, schema = 'public')
6
- @functions = functions
7
- @schema = schema
8
- end
9
-
10
- def description
11
- 'have functions'
12
- end
13
-
14
- def matches?(table)
15
- super(table)
16
-
17
- @matches = @functions.inject({}) do |h, name|
18
- h.update(name => has_function?(name))
19
- end
20
-
21
- @matches.values.all?
22
- end
23
-
24
- def failure_message
25
- message_matches("expected #{@schema}.#{table} to have")
26
- end
27
-
28
- def failure_message_when_negated
29
- message_matches("expected #{@schema}.#{table} to not have")
30
- end
31
-
32
- protected
33
- def has_function?(name)
34
- select_value(<<-SQL, [name], 'Check function') == true
35
- SELECT EXISTS(
36
- SELECT 1
37
- FROM pg_catalog.pg_proc p, pg_catalog.pg_namespace n
38
- WHERE p.pronamespace = n.oid
39
- AND n.nspname = 'public'
40
- AND p.proname = ?
41
- )
42
- SQL
43
- end
44
-
45
- private
46
- def message_matches(message)
47
- (message << ' ').tap do |message|
48
- message << @matches.map do |name, match|
49
- "a #{name} function"
50
- end.compact.to_sentence
51
- end
52
- end
53
- end
54
-
55
- def have_functions(*args)
56
- HaveFunctions.new(*args)
57
- end
58
-
59
- class HaveHistoryFunctions < HaveFunctions
60
- def initialize
61
- @function_templates = [
62
- 'chronomodel_%s_insert',
63
- 'chronomodel_%s_update',
64
- 'chronomodel_%s_delete',
65
- ]
66
- end
67
-
68
- def matches?(table)
69
- @functions = @function_templates.map {|t| t % [table] }
70
-
71
- super(table)
72
- end
73
- end
74
-
75
- def have_history_functions
76
- HaveHistoryFunctions.new
77
- end
78
- end
79
- end
@@ -1,69 +0,0 @@
1
- module ChronoTest::Matchers
2
-
3
- module Index
4
- class HaveIndex < ChronoTest::Matchers::Base
5
- attr_reader :name, :columns, :schema
6
-
7
- def initialize(name, columns, schema = 'public')
8
- @name = name
9
- @columns = columns.sort
10
- @schema = schema
11
- end
12
-
13
- def description
14
- 'have index'
15
- end
16
-
17
- def matches?(table)
18
- super(table)
19
-
20
- select_values(<<-SQL, [ table, name, schema ], 'Check index') == columns
21
- SELECT a.attname
22
- FROM pg_class t
23
- JOIN pg_index d ON t.oid = d.indrelid
24
- JOIN pg_class i ON i.oid = d.indexrelid
25
- JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(d.indkey)
26
- WHERE i.relkind = 'i'
27
- AND t.relname = ?
28
- AND i.relname = ?
29
- AND i.relnamespace = (
30
- SELECT oid FROM pg_namespace WHERE nspname = ?
31
- )
32
- ORDER BY a.attname
33
- SQL
34
- end
35
-
36
- def failure_message
37
- "expected #{schema}.#{table} to have a #{name} index on #{columns}"
38
- end
39
-
40
- def failure_message_when_negated
41
- "expected #{schema}.#{table} to not have a #{name} index on #{columns}"
42
- end
43
- end
44
-
45
- def have_index(*args)
46
- HaveIndex.new(*args)
47
- end
48
-
49
- class HaveTemporalIndex < HaveIndex
50
- def initialize(name, columns)
51
- super(name, columns, temporal_schema)
52
- end
53
- end
54
-
55
- def have_temporal_index(*args)
56
- HaveTemporalIndex.new(*args)
57
- end
58
-
59
- class HaveHistoryIndex < HaveIndex
60
- def initialize(name, columns)
61
- super(name, columns, history_schema)
62
- end
63
- end
64
-
65
- def have_history_index(*args)
66
- HaveHistoryIndex.new(*args)
67
- end
68
- end
69
- end
@@ -1,39 +0,0 @@
1
- require 'support/matchers/base'
2
-
3
- module ChronoTest::Matchers
4
-
5
- module Schema
6
- class BeInSchema < ChronoTest::Matchers::Base
7
-
8
- def initialize(expected)
9
- @expected = expected
10
- @expected = '"$user", public' if @expected == :default
11
- end
12
-
13
- def description
14
- 'be in schema'
15
- end
16
-
17
- def failure_message
18
- "expected to be in schema #@expected, but was in #@current"
19
- end
20
-
21
- def failure_message_when_negated
22
- "expected to be in schema #@current, but was in #@expected"
23
- end
24
-
25
- def matches?(*)
26
- @current = select_value(<<-SQL, [], 'Current schema')
27
- SHOW search_path
28
- SQL
29
-
30
- @current == @expected
31
- end
32
- end
33
-
34
- def be_in_schema(schema)
35
- BeInSchema.new(schema)
36
- end
37
- end
38
-
39
- end
@@ -1,275 +0,0 @@
1
- require 'support/matchers/base'
2
-
3
- module ChronoTest::Matchers
4
-
5
- module Table
6
- class Base < ChronoTest::Matchers::Base
7
-
8
- protected
9
- # Database statements
10
- #
11
- def relation_exists?(options)
12
- schema = options[:in]
13
- kind = options[:kind] == :view ? 'v' : 'r'
14
-
15
- select_value(<<-SQL, [ table, schema ], 'Check table exists') == true
16
- SELECT EXISTS (
17
- SELECT 1
18
- FROM pg_class c
19
- LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
20
- WHERE c.relkind = '#{kind}'
21
- AND c.relname = ?
22
- AND n.nspname = ?
23
- )
24
- SQL
25
- end
26
- end
27
-
28
- # ##################################################################
29
- # Checks that a table exists in the Public schema
30
- #
31
- class HavePublicBacking < Base
32
- def matches?(table)
33
- super(table)
34
-
35
- relation_exists? :in => public_schema
36
- end
37
-
38
- def description
39
- 'be in the public schema'
40
- end
41
-
42
- def failure_message
43
- "expected #{table} to exist in the #{public_schema} schema"
44
- end
45
-
46
- def failure_message_when_negated
47
- "expected #{table} to not exist in the #{public_schema} schema"
48
- end
49
- end
50
-
51
- def have_public_backing
52
- HavePublicBacking.new
53
- end
54
-
55
-
56
- # ##################################################################
57
- # Checks that a table exists in the Temporal schema
58
- #
59
- class HaveTemporalBacking < Base
60
- def matches?(table)
61
- super(table)
62
-
63
- relation_exists? :in => temporal_schema
64
- end
65
-
66
- def description
67
- 'be in the temporal schema'
68
- end
69
-
70
- def failure_message
71
- "expected #{table} to exist in the #{temporal_schema} schema"
72
- end
73
-
74
- def failure_message_when_negated
75
- "expected #{table} to not exist in the #{temporal_schema} schema"
76
- end
77
- end
78
-
79
- def have_temporal_backing
80
- HaveTemporalBacking.new
81
- end
82
-
83
-
84
- # ##################################################################
85
- # Checks that a table exists in the History schema and inherits from
86
- # the one in the Temporal schema
87
- #
88
- class HaveHistoryBacking < Base
89
- def matches?(table)
90
- super(table)
91
-
92
- table_exists? &&
93
- inherits_from_temporal? &&
94
- has_consistency_constraint? &&
95
- has_history_indexes?
96
- end
97
-
98
- def description
99
- 'be in history schema'
100
- end
101
-
102
- def failure_message
103
- "expected #{table} ".tap do |message|
104
- message << [
105
- ("to exist in the #{history_schema} schema" unless @existance),
106
- ("to inherit from #{temporal_schema}.#{table}" unless @inheritance),
107
- ("to have a timeline consistency constraint" unless @constraint),
108
- ("to have history indexes" unless @indexes)
109
- ].compact.to_sentence
110
- end
111
- end
112
-
113
- def failure_message_when_negated
114
- "expected #{table} ".tap do |message|
115
- message << [
116
- ("to not exist in the #{history_schema} schema" if @existance),
117
- ("to not inherit from #{temporal_schema}.#{table}" if @inheritance),
118
- ("to not have a timeline consistency constraint" if @constraint),
119
- ("to not have history indexes" if @indexes)
120
- ].compact.to_sentence
121
- end
122
- end
123
-
124
- private
125
- def table_exists?
126
- @existance = relation_exists? :in => history_schema
127
- end
128
-
129
- def inherits_from_temporal?
130
- binds = ["#{history_schema}.#{table}", "#{temporal_schema}.#{table}"]
131
-
132
- @inheritance = select_value(<<-SQL, binds, 'Check inheritance') == true
133
- SELECT EXISTS (
134
- SELECT 1 FROM pg_catalog.pg_inherits
135
- WHERE inhrelid = ?::regclass::oid
136
- AND inhparent = ?::regclass::oid
137
- )
138
- SQL
139
- end
140
-
141
- def has_history_indexes?
142
- binds = [ history_schema, table ]
143
-
144
- indexes = select_values(<<-SQL, binds, 'Check history indexes')
145
- SELECT indexdef FROM pg_indexes
146
- WHERE schemaname = ?
147
- AND tablename = ?
148
- SQL
149
-
150
- fqtn = [history_schema, table].join('.')
151
-
152
- expected = [
153
- "CREATE INDEX index_#{table}_temporal_on_lower_validity ON #{fqtn} USING btree (lower(validity))",
154
- "CREATE INDEX index_#{table}_temporal_on_upper_validity ON #{fqtn} USING btree (upper(validity))",
155
- "CREATE INDEX index_#{table}_temporal_on_validity ON #{fqtn} USING gist (validity)",
156
-
157
- "CREATE INDEX #{table}_inherit_pkey ON #{fqtn} USING btree (id)",
158
- "CREATE INDEX #{table}_instance_history ON #{fqtn} USING btree (id, recorded_at)",
159
- "CREATE UNIQUE INDEX #{table}_pkey ON #{fqtn} USING btree (hid)",
160
- "CREATE INDEX #{table}_recorded_at ON #{fqtn} USING btree (recorded_at)",
161
- "CREATE INDEX #{table}_timeline_consistency ON #{fqtn} USING gist (id, validity)"
162
- ]
163
-
164
- @indexes = (expected - indexes).empty?
165
- end
166
-
167
- def has_consistency_constraint?
168
- binds = {
169
- conname: connection.timeline_consistency_constraint_name(table),
170
- connamespace: history_schema,
171
- conrelid: [history_schema, table].join('.'),
172
- attname: connection.primary_key(table)
173
- }
174
-
175
- @constraint = select_value(<<-SQL, binds, 'Check Consistency Constraint') == true
176
- SELECT EXISTS (
177
- SELECT 1 FROM pg_catalog.pg_constraint
178
- WHERE conname = :conname
179
- AND contype = 'x'
180
- AND conrelid = :conrelid::regclass
181
- AND connamespace = (
182
- SELECT oid FROM pg_catalog.pg_namespace WHERE nspname = :connamespace
183
- )
184
- AND conkey = (
185
- SELECT array_agg(attnum) FROM pg_catalog.pg_attribute
186
- WHERE attname IN (:attname, 'validity')
187
- AND attrelid = :conrelid::regclass
188
- )
189
- )
190
- SQL
191
- end
192
- end
193
-
194
- def have_history_backing
195
- HaveHistoryBacking.new
196
- end
197
-
198
-
199
- # ##################################################################
200
- # Checks that a table exists in the Public schema, is an updatable
201
- # view and has an INSERT, UPDATE and DELETE triggers.
202
- #
203
- class HavePublicInterface < Base
204
- def matches?(table)
205
- super(table)
206
-
207
- view_exists? && [ is_updatable?, has_triggers? ].all?
208
- end
209
-
210
- def description
211
- 'be an updatable view'
212
- end
213
-
214
- def failure_message
215
- "expected #{table} ".tap do |message|
216
- message << [
217
- ("to exist in the #{public_schema} schema" unless @existance ),
218
- ('to be an updatable view' unless @updatable ),
219
- ('to have an INSERT trigger' unless @insert_trigger),
220
- ('to have an UPDATE trigger' unless @update_trigger),
221
- ('to have a DELETE trigger' unless @delete_trigger)
222
- ].compact.to_sentence
223
- end
224
- end
225
-
226
- def failure_message_when_negated
227
- "expected #{table} ".tap do |message|
228
- message << [
229
- ("to not exist in the #{public_schema} schema" if @existance ),
230
- ('to not be an updatable view' if @updatable ),
231
- ('to not have an INSERT trigger' if @insert_trigger),
232
- ('to not have an UPDATE trigger' if @update_trigger),
233
- ('to not have a DELETE trigger' if @delete_trigger)
234
- ].compact.to_sentence
235
- end
236
- end
237
-
238
- private
239
- def view_exists?
240
- @existance = relation_exists? :in => public_schema, :kind => :view
241
- end
242
-
243
- def is_updatable?
244
- binds = [ public_schema, table ]
245
-
246
- @updatable = select_value(<<-SQL, binds, 'Check updatable') == 'YES'
247
- SELECT is_updatable FROM information_schema.views
248
- WHERE table_schema = ? AND table_name = ?
249
- SQL
250
- end
251
-
252
- def has_triggers?
253
- triggers = select_values(<<-SQL, [ public_schema, table ], 'Check triggers')
254
- SELECT t.tgname
255
- FROM pg_catalog.pg_trigger t, pg_catalog.pg_class c, pg_catalog.pg_namespace n
256
- WHERE t.tgrelid = c.relfilenode
257
- AND n.oid = c.relnamespace
258
- AND n.nspname = ?
259
- AND c.relname = ?;
260
- SQL
261
-
262
- @insert_trigger = triggers.include? 'chronomodel_insert'
263
- @update_trigger = triggers.include? 'chronomodel_update'
264
- @delete_trigger = triggers.include? 'chronomodel_delete'
265
-
266
- @insert_trigger && @update_trigger && @delete_trigger
267
- end
268
- end
269
-
270
- def have_public_interface
271
- HavePublicInterface.new
272
- end
273
- end
274
-
275
- end
@@ -1,47 +0,0 @@
1
- module ChronoTest::TimeMachine
2
-
3
- # This module contains helpers used throughout the
4
- # +ChronoModel::TimeMachine+ specs.
5
- #
6
- module Helpers
7
- def self.included(base)
8
- base.extend(self)
9
- end
10
-
11
- def adapter
12
- ChronoTest.connection
13
- end
14
-
15
- def with_revert
16
- adapter.transaction do
17
- adapter.create_savepoint 'revert'
18
-
19
- yield
20
-
21
- adapter.exec_rollback_to_savepoint 'revert'
22
- end
23
- end
24
-
25
- # If a context object is given, evaluates the given
26
- # block in its instance context, then defines a `ts`
27
- # on it, backed by an Array, and adds the current
28
- # database timestamp to it.
29
- #
30
- # If a context object is not given, the block is
31
- # evaluated in the current context and the above
32
- # mangling is done on the blocks' return value.
33
- #
34
- def ts_eval(ctx = nil, &block)
35
- ret = (ctx || self).instance_eval(&block)
36
- (ctx || ret).tap do |obj|
37
- obj.singleton_class.instance_eval do
38
- define_method(:ts) { @_ts ||= [] }
39
- end unless obj.methods.include?(:ts)
40
-
41
- now = ChronoTest.connection.select_value('select now()::timestamp') + 'Z'
42
- obj.ts.push(Time.parse(now))
43
- end
44
- end
45
- end
46
-
47
- end