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,261 +0,0 @@
1
- require 'spec_helper'
2
- require 'support/time_machine/structure'
3
-
4
- describe ChronoModel::TimeMachine::TimeQuery do
5
- include ChronoTest::TimeMachine::Helpers
6
-
7
- adapter.create_table 'events' do |t|
8
- t.string :name
9
- t.daterange :interval
10
- end
11
-
12
- class ::Event < ActiveRecord::Base
13
- extend ChronoModel::TimeMachine::TimeQuery
14
- end
15
-
16
- # Main timeline quick test
17
- #
18
- it { expect(Foo.history.time_query(:after, :now, inclusive: true ).count).to eq 3 }
19
- it { expect(Foo.history.time_query(:after, :now, inclusive: false).count).to eq 0 }
20
- it { expect(Foo.history.time_query(:before, :now, inclusive: true ).count).to eq 5 }
21
- it { expect(Foo.history.time_query(:before, :now, inclusive: false).count).to eq 2 }
22
-
23
- it { expect(Foo.history.past.size).to eq 2 }
24
-
25
- # Extended thorough test.
26
- #
27
- # Create a set of events and then run time queries on them.
28
- #
29
- think = Event.create! name: 'think', interval: (15.days.ago.to_date...13.days.ago.to_date)
30
- plan = Event.create! name: 'plan', interval: (14.days.ago.to_date...12.days.ago.to_date)
31
- collect = Event.create! name: 'collect', interval: (12.days.ago.to_date...10.days.ago.to_date)
32
- start = Event.create! name: 'start', interval: (8.days.ago.to_date...7.days.ago.to_date)
33
- build = Event.create! name: 'build', interval: (7.days.ago.to_date...Date.yesterday)
34
- profit = Event.create! name: 'profit', interval: (Date.tomorrow...1.year.from_now.to_date)
35
-
36
- describe :at do
37
- describe 'with a single timestamp' do
38
- subject { Event.time_query(:at, time.try(:to_date) || time, on: :interval).to_a }
39
-
40
- context 'no records' do
41
- let(:time) { 16.days.ago }
42
- it { is_expected.to be_empty }
43
- end
44
-
45
- context 'single record' do
46
- let(:time) { 15.days.ago }
47
- it { is_expected.to eq [think] }
48
- end
49
-
50
- context 'multiple overlapping records' do
51
- let(:time) { 14.days.ago }
52
- it { is_expected.to match_array [think, plan] }
53
- end
54
-
55
- context 'on an edge of an open interval' do
56
- let(:time) { 10.days.ago }
57
- it { is_expected.to be_empty }
58
- end
59
-
60
- context 'in an hole' do
61
- let(:time) { 9.days.ago }
62
- it { is_expected.to be_empty }
63
- end
64
-
65
- context 'today' do
66
- let(:time) { Date.today }
67
- it { is_expected.to be_empty }
68
- end
69
-
70
- context 'server-side :today' do
71
- let(:time) { :today }
72
- it { is_expected.to be_empty }
73
- end
74
- end
75
-
76
- describe 'with a range' do
77
- subject { Event.time_query(:at, times.map!(&:to_date), on: :interval, type: :daterange).to_a }
78
-
79
- context 'that is empty' do
80
- let(:times) { [ 14.days.ago, 14.days.ago ] }
81
- it { is_expected.to_not be_empty }
82
- end
83
-
84
- context 'overlapping no records' do
85
- let(:times) { [ 20.days.ago, 16.days.ago ] }
86
- it { is_expected.to be_empty }
87
- end
88
-
89
- context 'overlapping a single record' do
90
- let(:times) { [ 16.days.ago, 14.days.ago ] }
91
- it { is_expected.to eq [think] }
92
- end
93
-
94
- context 'overlapping more records' do
95
- let(:times) { [ 16.days.ago, 11.days.ago ] }
96
- it { is_expected.to match_array [think, plan, collect] }
97
- end
98
-
99
- context 'on the edge of an open interval and an hole' do
100
- let(:times) { [ 10.days.ago, 9.days.ago ] }
101
- it { is_expected.to be_empty }
102
- end
103
- end
104
- end
105
-
106
- describe :before do
107
- let(:inclusive) { true }
108
- subject { Event.time_query(:before, time.try(:to_date) || time, on: :interval, type: :daterange, inclusive: inclusive).to_a }
109
-
110
- context '16 days ago' do
111
- let(:time) { 16.days.ago }
112
- it { is_expected.to be_empty }
113
- end
114
-
115
- context '14 days ago' do
116
- let(:time) { 14.days.ago }
117
- it { is_expected.to eq [think] }
118
-
119
- context 'not inclusive' do
120
- let(:inclusive) { false }
121
- it { is_expected.to be_empty }
122
- end
123
- end
124
-
125
- context '11 days ago' do
126
- let(:time) { 11.days.ago }
127
- it { is_expected.to match_array [think, plan, collect] }
128
-
129
- context 'not inclusive' do
130
- let(:inclusive) { false }
131
- it { is_expected.to eq [think, plan] }
132
- end
133
- end
134
-
135
- context '10 days ago' do
136
- let(:time) { 10.days.ago }
137
- it { is_expected.to match_array [think, plan, collect] }
138
- end
139
-
140
- context '8 days ago' do
141
- let(:time) { 8.days.ago }
142
- it { is_expected.to match_array [think, plan, collect] }
143
- end
144
-
145
- context 'today' do
146
- let(:time) { Date.today }
147
- it { is_expected.to match_array [think, plan, collect, start, build] }
148
- end
149
-
150
- context ':today' do
151
- let(:time) { :today }
152
- it { is_expected.to match_array [think, plan, collect, start, build] }
153
- end
154
- end
155
-
156
- describe :after do
157
- let(:inclusive) { true }
158
- subject { Event.time_query(:after, time.try(:to_date) || time, on: :interval, type: :daterange, inclusive: inclusive).to_a }
159
-
160
- context 'one month ago' do
161
- let(:time) { 1.month.ago }
162
- it { is_expected.to match_array [think, plan, collect, start, build, profit] }
163
- end
164
-
165
- context '10 days ago' do
166
- let(:time) { 10.days.ago }
167
- it { is_expected.to match_array [start, build, profit] }
168
- end
169
-
170
- context 'yesterday' do
171
- let(:time) { Date.yesterday }
172
- it { is_expected.to eq [profit] }
173
- end
174
-
175
- context 'today' do
176
- let(:time) { Date.today }
177
- it { is_expected.to eq [profit] }
178
- end
179
-
180
- context 'server-side :today' do
181
- let(:time) { :today }
182
- it { is_expected.to eq [profit] }
183
- end
184
-
185
- context 'tomorrow' do
186
- let(:time) { Date.tomorrow }
187
- it { is_expected.to eq [profit] }
188
- end
189
-
190
- context 'one month from now' do
191
- let(:time) { 1.month.from_now }
192
- it { is_expected.to eq [profit] }
193
-
194
- context 'not inclusive' do
195
- let(:inclusive) { false }
196
- it { is_expected.to be_empty }
197
- end
198
- end
199
-
200
- context 'far future' do
201
- let(:time) { 1.year.from_now }
202
- it { is_expected.to be_empty }
203
- end
204
- end
205
-
206
- describe :not do
207
- context 'with a single timestamp' do
208
- subject { Event.time_query(:not, time.try(:to_date) || time, on: :interval, type: :daterange).to_a }
209
-
210
- context '14 days ago' do
211
- let(:time) { 14.days.ago }
212
- it { is_expected.to match_array [collect, start, build, profit] }
213
- end
214
-
215
- context '9 days ago' do
216
- let(:time) { 9.days.ago }
217
- it { is_expected.to match_array [think, plan, collect, start, build, profit] }
218
- end
219
-
220
- context '8 days ago' do
221
- let(:time) { 8.days.ago }
222
- it { is_expected.to match_array [think, plan, collect, build, profit] }
223
- end
224
-
225
- context 'today' do
226
- let(:time) { Date.today }
227
- it { is_expected.to match_array [think, plan, collect, start, build, profit] }
228
- end
229
-
230
- context ':today' do
231
- let(:time) { :today }
232
- it { is_expected.to match_array [think, plan, collect, start, build, profit] }
233
- end
234
-
235
- context '1 month from now' do
236
- let(:time) { 1.month.from_now }
237
- it { is_expected.to match_array [think, plan, collect, start, build] }
238
- end
239
- end
240
-
241
- context 'with a range' do
242
- subject { Event.time_query(:not, time.map(&:to_date), on: :interval, type: :daterange).to_a }
243
-
244
- context 'eliminating a single record' do
245
- let(:time) { [1.month.ago, 14.days.ago] }
246
- it { is_expected.to match_array [plan, collect, start, build, profit] }
247
- end
248
-
249
- context 'eliminating multiple records' do
250
- let(:time) { [1.month.ago, Date.today] }
251
- it { is_expected.to eq [profit] }
252
- end
253
-
254
- context 'from an edge' do
255
- let(:time) { [14.days.ago, 10.days.ago] }
256
- it { is_expected.to eq [start, build, profit] }
257
- end
258
- end
259
- end
260
-
261
- end
@@ -1,63 +0,0 @@
1
- require 'spec_helper'
2
- require 'support/time_machine/structure'
3
-
4
- describe ChronoModel::TimeMachine do
5
- include ChronoTest::TimeMachine::Helpers
6
-
7
- describe '#timeline' do
8
- split = lambda {|ts| ts.map!{|t| [t.to_i, t.usec]} }
9
-
10
- timestamps_from = lambda {|*records|
11
- records.map(&:history).flatten!.inject([]) {|ret, rec|
12
- ret.push [rec.valid_from.to_i, rec.valid_from.usec] if rec.try(:valid_from)
13
- ret.push [rec.valid_to .to_i, rec.valid_to .usec] if rec.try(:valid_to)
14
- ret
15
- }.sort.uniq
16
- }
17
-
18
- describe 'on records having an :has_many relationship' do
19
- describe 'by default returns timestamps of the record only' do
20
- subject { split.call($t.foo.timeline) }
21
-
22
- it { expect(subject.size).to eq $t.foo.ts.size }
23
- it { is_expected.to eq timestamps_from.call($t.foo) }
24
- end
25
-
26
- describe 'when asked, returns timestamps including the related objects' do
27
- subject { split.call($t.foo.timeline(with: :bars)) }
28
-
29
- it { expect(subject.size).to eq($t.foo.ts.size + $t.bar.ts.size) }
30
- it { is_expected.to eq(timestamps_from.call($t.foo, *$t.foo.bars)) }
31
- end
32
- end
33
-
34
- describe 'on records using has_timeline :with' do
35
- subject { split.call($t.bar.timeline) }
36
-
37
- describe 'returns timestamps of the record and its associations' do
38
-
39
- let!(:expected) do
40
- creat = $t.bar.history.first.valid_from
41
- c_sec, c_usec = creat.to_i, creat.usec
42
-
43
- timestamps_from.call($t.foo, $t.bar).reject {|sec, usec|
44
- sec < c_sec || ( sec == c_sec && usec < c_usec )
45
- }
46
- end
47
-
48
- it { expect(subject.size).to eq expected.size }
49
- it { is_expected.to eq expected }
50
- end
51
- end
52
-
53
- describe 'on non-temporal records using has_timeline :with' do
54
- subject { split.call($t.baz.timeline) }
55
-
56
- describe 'returns timestamps of its temporal associations' do
57
- it { expect(subject.size).to eq $t.bar.ts.size }
58
- it { is_expected.to eq timestamps_from.call($t.bar) }
59
- end
60
- end
61
- end
62
-
63
- end
@@ -1,43 +0,0 @@
1
- require 'spec_helper'
2
- require 'support/time_machine/structure'
3
-
4
- describe ChronoModel::TimeMachine do
5
- include ChronoTest::TimeMachine::Helpers
6
-
7
- history_methods = %w( valid_from valid_to recorded_at )
8
- current_methods = %w( as_of_time )
9
-
10
- context 'on history records' do
11
- let(:record) { $t.foo.history.first }
12
-
13
- (history_methods + current_methods).each do |attr|
14
- describe ['#', attr].join do
15
- subject { record.public_send(attr) }
16
-
17
- it { is_expected.to be_present }
18
- it { is_expected.to be_a(Time) }
19
- it { is_expected.to be_utc }
20
- end
21
- end
22
- end
23
-
24
- context 'on current records' do
25
- let(:record) { $t.foo }
26
-
27
- history_methods.each do |attr|
28
- describe ['#', attr].join do
29
- subject { record.public_send(attr) }
30
-
31
- it { expect { subject }.to raise_error(NoMethodError) }
32
- end
33
- end
34
-
35
- current_methods.each do |attr|
36
- describe ['#', attr].join do
37
- subject { record.public_send(attr) }
38
-
39
- it { is_expected.to be(nil) }
40
- end
41
- end
42
- end
43
- end
@@ -1,69 +0,0 @@
1
- require 'spec_helper'
2
- require 'support/time_machine/structure'
3
-
4
- describe ChronoModel::TimeMachine do
5
- include ChronoTest::TimeMachine::Helpers
6
-
7
- # Transactions
8
- context 'multiple updates to an existing record' do
9
- let!(:r1) do
10
- Foo.create!(:name => 'xact test').tap do |record|
11
- Foo.transaction do
12
- record.update_attribute 'name', 'lost into oblivion'
13
- record.update_attribute 'name', 'does work'
14
- end
15
- end
16
- end
17
-
18
- it "generate only a single history record" do
19
- expect(r1.history.size).to eq(2)
20
-
21
- expect(r1.history.first.name).to eq 'xact test'
22
- expect(r1.history.last.name).to eq 'does work'
23
- end
24
-
25
- after do
26
- r1.destroy
27
- r1.history.delete_all
28
- end
29
- end
30
-
31
- context 'insertion and subsequent update' do
32
- let!(:r2) do
33
- Foo.transaction do
34
- Foo.create!(:name => 'lost into oblivion').tap do |record|
35
- record.update_attribute 'name', 'I am Bar'
36
- record.update_attribute 'name', 'I am Foo'
37
- end
38
- end
39
- end
40
-
41
- it 'generates a single history record' do
42
- expect(r2.history.size).to eq(1)
43
- expect(r2.history.first.name).to eq 'I am Foo'
44
- end
45
-
46
- after do
47
- r2.destroy
48
- r2.history.delete_all
49
- end
50
- end
51
-
52
- context 'insertion and subsequent deletion' do
53
- let!(:r3) do
54
- Foo.transaction do
55
- Foo.create!(:name => 'it never happened').destroy
56
- end
57
- end
58
-
59
- it 'does not generate any history' do
60
- expect(Foo.history.where(:id => r3.id)).to be_empty
61
- end
62
-
63
- after do
64
- r3.destroy
65
- r3.history.delete_all
66
- end
67
- end
68
-
69
- end
@@ -1,5 +0,0 @@
1
- hostname: localhost
2
- username: postgres
3
- password: ""
4
- database: chronomodel
5
- pool: 11
@@ -1,9 +0,0 @@
1
- # CREATE ROLE chronomodel LOGIN ENCRYPTED PASSWORD 'chronomodel' CREATEDB;
2
- #
3
- adapter: chronomodel
4
- hostname: localhost
5
- username: chronomodel
6
- password: chronomodel
7
- database: chronomodel
8
- pool: 11
9
- #
data/spec/spec_helper.rb DELETED
@@ -1,33 +0,0 @@
1
- # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
2
- #
3
- require 'simplecov'
4
- SimpleCov.start
5
-
6
- require 'byebug'
7
-
8
- require 'chrono_model'
9
-
10
- require 'support/connection'
11
- require 'support/matchers/schema'
12
- require 'support/matchers/table'
13
- require 'support/matchers/column'
14
- require 'support/matchers/index'
15
- require 'support/matchers/function'
16
- require 'support/aruba'
17
-
18
- puts "Testing against Active Record #{ActiveRecord::VERSION::STRING} with Arel #{Arel::VERSION}"
19
-
20
- RSpec.configure do |config|
21
- config.include(ChronoTest::Matchers::Schema)
22
- config.include(ChronoTest::Matchers::Table)
23
- config.include(ChronoTest::Matchers::Column)
24
- config.include(ChronoTest::Matchers::Index)
25
- config.include(ChronoTest::Aruba, type: :aruba)
26
-
27
- ChronoTest.recreate_database!
28
-
29
- config.before(:example, type: :aruba) do
30
- copy_dummy_app_into_aruba_working_directory
31
- recreate_railsapp_database
32
- end
33
- end
@@ -1,53 +0,0 @@
1
- module ChronoTest::Adapter
2
-
3
- module Helpers
4
- def self.included(base)
5
- base.extend DSL
6
-
7
- base.instance_eval do
8
- delegate :adapter, :to => ChronoTest
9
- delegate :columns, :table, :pk_type, :to => DSL
10
- end
11
- end
12
-
13
- module DSL
14
- def with_temporal_table(&block)
15
- context ':temporal => true' do
16
- before(:all) { adapter.create_table(table, :temporal => true, &DSL.columns) }
17
- after(:all) { adapter.drop_table table }
18
-
19
- instance_eval(&block)
20
- end
21
- end
22
-
23
- def with_plain_table(&block)
24
- context ':temporal => false' do
25
- before(:all) { adapter.create_table(table, :temporal => false, &DSL.columns) }
26
- after(:all) { adapter.drop_table table }
27
-
28
- instance_eval(&block)
29
- end
30
- end
31
-
32
- def self.table(table = nil)
33
- @table = table if table
34
- @table
35
- end
36
-
37
- def self.columns(&block)
38
- @columns = block.call if block
39
- @columns
40
- end
41
-
42
- def self.pk_type
43
- @pk_type ||= if ActiveRecord::VERSION::MAJOR == 5 && ActiveRecord::VERSION::MINOR >= 1
44
- 'bigint'
45
- else
46
- 'integer'
47
- end
48
- end
49
- delegate :columns, :table, :pk_type, :to => self
50
- end
51
- end
52
-
53
- end
@@ -1,44 +0,0 @@
1
- require 'support/adapter/helpers'
2
-
3
- # This module contains the definition of a test structure that is used by the
4
- # adapter methods tests, that look up in the database directly whether the
5
- # expected objects have been created.
6
- #
7
- # The structure defintiion below serves as a blueprint of what it can be
8
- # defined, ans as a reference of what it is expected to have been created by
9
- # the +ChronoModel::Adapter+ methods.
10
- #
11
- module ChronoTest::Adapter
12
-
13
- module Structure
14
- extend ActiveSupport::Concern
15
-
16
- included do
17
- table 'test_table'
18
- subject { table }
19
-
20
- columns do
21
- native = [
22
- ['test', 'character varying'],
23
- ['foo', 'integer'],
24
- ['bar', 'double precision'],
25
- ['baz', 'text']
26
- ]
27
-
28
- def native.to_proc
29
- proc {|t|
30
- t.string :test, null: false, default: 'default-value'
31
- t.integer :foo
32
- t.float :bar
33
- t.text :baz
34
- t.integer :ary, array: true, null: false, default: []
35
- t.boolean :bool, null: false, default: false
36
- }
37
- end
38
-
39
- native
40
- end
41
- end
42
- end
43
-
44
- end
@@ -1,44 +0,0 @@
1
- require 'aruba/rspec'
2
- require 'arel'
3
-
4
- module ChronoTest
5
-
6
- module Aruba
7
- def aruba_working_directory
8
- File.expand_path("../../#{::Aruba.config.working_directory}", __dir__)
9
- end
10
-
11
- def dummy_app_directory
12
- File.expand_path("../../tmp/railsapp/", __dir__)
13
- end
14
-
15
- def copy_dummy_app_into_aruba_working_directory
16
- unless File.file?(Pathname.new(dummy_app_directory).join('Rakefile'))
17
- raise %q(
18
- The dummy application does not exist
19
- Run `bundle exec rake testapp:create`
20
- )
21
- end
22
- FileUtils.rm_rf(Dir.glob("#{aruba_working_directory}/*"))
23
- FileUtils.cp_r(Dir.glob("#{dummy_app_directory}/*"), aruba_working_directory)
24
- end
25
-
26
- def recreate_railsapp_database
27
- connection = AR.connection # we're still the 'chronomodel' user
28
- database = 'chronomodel_railsapp'
29
- connection.drop_database database
30
- connection.create_database database
31
- end
32
-
33
- def file_mangle!(file, &block)
34
- # Read
35
- file_contents = read(file).join("\n")
36
-
37
- # Mangle
38
- file_contents = block.call(file_contents)
39
-
40
- # Write
41
- write_file file, file_contents
42
- end
43
- end
44
- end
@@ -1,70 +0,0 @@
1
- require 'pathname'
2
- require 'active_record'
3
-
4
- module ChronoTest
5
- extend self
6
-
7
- AR = ActiveRecord::Base
8
- log = ENV['VERBOSE'].present? ? $stderr : 'spec/debug.log'.tap{|f| File.open(f, "ab") { |ft| ft.truncate(0) }}
9
- AR.logger = ::Logger.new(log).tap do |l|
10
- l.level = 0
11
- end
12
-
13
- def connect!(spec = self.config)
14
- unless ENV['VERBOSE'].present?
15
- spec = spec.merge(:min_messages => 'WARNING')
16
- end
17
- AR.establish_connection spec
18
- end
19
-
20
- def logger
21
- AR.logger
22
- end
23
-
24
- def connection
25
- AR.connection
26
- end
27
- alias :adapter :connection
28
-
29
- def recreate_database!
30
- database = config.fetch(:database)
31
- connect! config.merge(:database => :postgres)
32
-
33
- connection.drop_database database
34
- connection.create_database database
35
- connect! config
36
-
37
- connection.execute 'CREATE EXTENSION btree_gist'
38
- logger.info "Connected to #{config}"
39
- end
40
-
41
- def config
42
- @config ||= YAML.load(config_file.read).tap do |conf|
43
- conf.symbolize_keys!
44
- conf.update(:adapter => 'chronomodel')
45
-
46
- def conf.to_s
47
- 'pgsql://%s:%s@%s/%s' % [
48
- self[:username], self[:password], self[:hostname], self[:database]
49
- ]
50
- end
51
- end
52
-
53
- rescue Errno::ENOENT
54
- $stderr.puts <<EOM
55
-
56
- Please define your AR database configuration
57
- in spec/config.yml or reference your own configuration
58
- file using the TEST_CONFIG environment variable
59
- EOM
60
-
61
- abort
62
- end
63
-
64
- def config_file
65
- Pathname(ENV['TEST_CONFIG'] ||
66
- File.join(File.dirname(__FILE__), '..', 'config.yml')
67
- )
68
- end
69
-
70
- end