temporal_tables 0.8.1 → 1.0.1
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/test.yml +53 -0
- data/.rubocop.yml +158 -0
- data/.ruby-version +1 -1
- data/.travis.yml +5 -5
- data/Gemfile +2 -0
- data/README.md +15 -5
- data/Rakefile +7 -2
- data/config.ru +2 -0
- data/gemfiles/Gemfile.6.0.mysql.lock +84 -84
- data/gemfiles/Gemfile.6.0.pg.lock +103 -98
- data/gemfiles/Gemfile.6.1.mysql.lock +180 -0
- data/gemfiles/Gemfile.6.1.pg.lock +180 -0
- data/gemfiles/{Gemfile.5.2.mysql → Gemfile.7.0.mysql} +2 -2
- data/gemfiles/Gemfile.7.0.mysql.lock +173 -0
- data/gemfiles/{Gemfile.5.2.pg → Gemfile.7.0.pg} +1 -1
- data/gemfiles/Gemfile.7.0.pg.lock +173 -0
- data/lib/temporal_tables/arel_table.rb +10 -9
- data/lib/temporal_tables/association_extensions.rb +2 -0
- data/lib/temporal_tables/connection_adapters/mysql_adapter.rb +5 -3
- data/lib/temporal_tables/connection_adapters/postgresql_adapter.rb +5 -3
- data/lib/temporal_tables/history_hook.rb +8 -5
- data/lib/temporal_tables/preloader_extensions.rb +2 -0
- data/lib/temporal_tables/reflection_extensions.rb +11 -14
- data/lib/temporal_tables/relation_extensions.rb +11 -24
- data/lib/temporal_tables/temporal_adapter.rb +77 -90
- data/lib/temporal_tables/temporal_class.rb +29 -28
- data/lib/temporal_tables/version.rb +3 -1
- data/lib/temporal_tables/whodunnit.rb +5 -3
- data/lib/temporal_tables.rb +42 -32
- data/spec/basic_history_spec.rb +52 -43
- data/spec/internal/app/models/broom.rb +2 -0
- data/spec/internal/app/models/cat.rb +3 -1
- data/spec/internal/app/models/cat_life.rb +2 -0
- data/spec/internal/app/models/coven.rb +2 -0
- data/spec/internal/app/models/flying_machine.rb +2 -0
- data/spec/internal/app/models/person.rb +2 -0
- data/spec/internal/app/models/rocket_broom.rb +2 -0
- data/spec/internal/app/models/wart.rb +3 -1
- data/spec/internal/config/database.ci.yml +12 -0
- data/spec/internal/db/schema.rb +8 -4
- data/spec/spec_helper.rb +39 -5
- data/spec/support/database.rb +10 -6
- data/temporal_tables.gemspec +31 -18
- metadata +103 -35
- data/.github/workflow/test.yml +0 -44
- data/gemfiles/Gemfile.5.1.mysql +0 -16
- data/gemfiles/Gemfile.5.1.mysql.lock +0 -147
- data/gemfiles/Gemfile.5.1.pg +0 -16
- data/gemfiles/Gemfile.5.1.pg.lock +0 -147
- data/gemfiles/Gemfile.5.2.mysql.lock +0 -155
- data/gemfiles/Gemfile.5.2.pg.lock +0 -155
- data/lib/temporal_tables/join_extensions.rb +0 -20
- data/spec/extensions/combustion.rb +0 -9
- data/spec/internal/config/routes.rb +0 -3
@@ -0,0 +1,173 @@
|
|
1
|
+
PATH
|
2
|
+
remote: ..
|
3
|
+
specs:
|
4
|
+
temporal_tables (1.0.1)
|
5
|
+
rails (>= 6.0, < 7.1)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
actioncable (7.0.0)
|
11
|
+
actionpack (= 7.0.0)
|
12
|
+
activesupport (= 7.0.0)
|
13
|
+
nio4r (~> 2.0)
|
14
|
+
websocket-driver (>= 0.6.1)
|
15
|
+
actionmailbox (7.0.0)
|
16
|
+
actionpack (= 7.0.0)
|
17
|
+
activejob (= 7.0.0)
|
18
|
+
activerecord (= 7.0.0)
|
19
|
+
activestorage (= 7.0.0)
|
20
|
+
activesupport (= 7.0.0)
|
21
|
+
mail (>= 2.7.1)
|
22
|
+
actionmailer (7.0.0)
|
23
|
+
actionpack (= 7.0.0)
|
24
|
+
actionview (= 7.0.0)
|
25
|
+
activejob (= 7.0.0)
|
26
|
+
activesupport (= 7.0.0)
|
27
|
+
mail (~> 2.5, >= 2.5.4)
|
28
|
+
rails-dom-testing (~> 2.0)
|
29
|
+
actionpack (7.0.0)
|
30
|
+
actionview (= 7.0.0)
|
31
|
+
activesupport (= 7.0.0)
|
32
|
+
rack (~> 2.0, >= 2.2.0)
|
33
|
+
rack-test (>= 0.6.3)
|
34
|
+
rails-dom-testing (~> 2.0)
|
35
|
+
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
36
|
+
actiontext (7.0.0)
|
37
|
+
actionpack (= 7.0.0)
|
38
|
+
activerecord (= 7.0.0)
|
39
|
+
activestorage (= 7.0.0)
|
40
|
+
activesupport (= 7.0.0)
|
41
|
+
globalid (>= 0.6.0)
|
42
|
+
nokogiri (>= 1.8.5)
|
43
|
+
actionview (7.0.0)
|
44
|
+
activesupport (= 7.0.0)
|
45
|
+
builder (~> 3.1)
|
46
|
+
erubi (~> 1.4)
|
47
|
+
rails-dom-testing (~> 2.0)
|
48
|
+
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
49
|
+
activejob (7.0.0)
|
50
|
+
activesupport (= 7.0.0)
|
51
|
+
globalid (>= 0.3.6)
|
52
|
+
activemodel (7.0.0)
|
53
|
+
activesupport (= 7.0.0)
|
54
|
+
activerecord (7.0.0)
|
55
|
+
activemodel (= 7.0.0)
|
56
|
+
activesupport (= 7.0.0)
|
57
|
+
activestorage (7.0.0)
|
58
|
+
actionpack (= 7.0.0)
|
59
|
+
activejob (= 7.0.0)
|
60
|
+
activerecord (= 7.0.0)
|
61
|
+
activesupport (= 7.0.0)
|
62
|
+
marcel (~> 1.0)
|
63
|
+
mini_mime (>= 1.1.0)
|
64
|
+
activesupport (7.0.0)
|
65
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
66
|
+
i18n (>= 1.6, < 2)
|
67
|
+
minitest (>= 5.1)
|
68
|
+
tzinfo (~> 2.0)
|
69
|
+
builder (3.2.4)
|
70
|
+
byebug (11.1.3)
|
71
|
+
combustion (1.3.5)
|
72
|
+
activesupport (>= 3.0.0)
|
73
|
+
railties (>= 3.0.0)
|
74
|
+
thor (>= 0.14.6)
|
75
|
+
concurrent-ruby (1.1.9)
|
76
|
+
crass (1.0.6)
|
77
|
+
database_cleaner (2.0.1)
|
78
|
+
database_cleaner-active_record (~> 2.0.0)
|
79
|
+
database_cleaner-active_record (2.0.1)
|
80
|
+
activerecord (>= 5.a)
|
81
|
+
database_cleaner-core (~> 2.0.0)
|
82
|
+
database_cleaner-core (2.0.1)
|
83
|
+
diff-lcs (1.5.0)
|
84
|
+
erubi (1.10.0)
|
85
|
+
gemika (0.6.1)
|
86
|
+
globalid (1.0.0)
|
87
|
+
activesupport (>= 5.0)
|
88
|
+
i18n (1.8.11)
|
89
|
+
concurrent-ruby (~> 1.0)
|
90
|
+
loofah (2.13.0)
|
91
|
+
crass (~> 1.0.2)
|
92
|
+
nokogiri (>= 1.5.9)
|
93
|
+
mail (2.7.1)
|
94
|
+
mini_mime (>= 0.1.1)
|
95
|
+
marcel (1.0.2)
|
96
|
+
method_source (1.0.0)
|
97
|
+
mini_mime (1.1.2)
|
98
|
+
minitest (5.15.0)
|
99
|
+
mysql2 (0.5.3)
|
100
|
+
nio4r (2.5.8)
|
101
|
+
nokogiri (1.12.5-arm64-darwin)
|
102
|
+
racc (~> 1.4)
|
103
|
+
nokogiri (1.12.5-x86_64-darwin)
|
104
|
+
racc (~> 1.4)
|
105
|
+
racc (1.6.0)
|
106
|
+
rack (2.2.3)
|
107
|
+
rack-test (1.1.0)
|
108
|
+
rack (>= 1.0, < 3)
|
109
|
+
rails (7.0.0)
|
110
|
+
actioncable (= 7.0.0)
|
111
|
+
actionmailbox (= 7.0.0)
|
112
|
+
actionmailer (= 7.0.0)
|
113
|
+
actionpack (= 7.0.0)
|
114
|
+
actiontext (= 7.0.0)
|
115
|
+
actionview (= 7.0.0)
|
116
|
+
activejob (= 7.0.0)
|
117
|
+
activemodel (= 7.0.0)
|
118
|
+
activerecord (= 7.0.0)
|
119
|
+
activestorage (= 7.0.0)
|
120
|
+
activesupport (= 7.0.0)
|
121
|
+
bundler (>= 1.15.0)
|
122
|
+
railties (= 7.0.0)
|
123
|
+
rails-dom-testing (2.0.3)
|
124
|
+
activesupport (>= 4.2.0)
|
125
|
+
nokogiri (>= 1.6)
|
126
|
+
rails-html-sanitizer (1.4.2)
|
127
|
+
loofah (~> 2.3)
|
128
|
+
railties (7.0.0)
|
129
|
+
actionpack (= 7.0.0)
|
130
|
+
activesupport (= 7.0.0)
|
131
|
+
method_source
|
132
|
+
rake (>= 12.2)
|
133
|
+
thor (~> 1.0)
|
134
|
+
zeitwerk (~> 2.5)
|
135
|
+
rake (13.0.6)
|
136
|
+
rspec (3.10.0)
|
137
|
+
rspec-core (~> 3.10.0)
|
138
|
+
rspec-expectations (~> 3.10.0)
|
139
|
+
rspec-mocks (~> 3.10.0)
|
140
|
+
rspec-core (3.10.1)
|
141
|
+
rspec-support (~> 3.10.0)
|
142
|
+
rspec-expectations (3.10.1)
|
143
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
144
|
+
rspec-support (~> 3.10.0)
|
145
|
+
rspec-mocks (3.10.2)
|
146
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
147
|
+
rspec-support (~> 3.10.0)
|
148
|
+
rspec-support (3.10.3)
|
149
|
+
thor (1.1.0)
|
150
|
+
tzinfo (2.0.4)
|
151
|
+
concurrent-ruby (~> 1.0)
|
152
|
+
websocket-driver (0.7.5)
|
153
|
+
websocket-extensions (>= 0.1.0)
|
154
|
+
websocket-extensions (0.1.5)
|
155
|
+
zeitwerk (2.5.3)
|
156
|
+
|
157
|
+
PLATFORMS
|
158
|
+
arm64-darwin-20
|
159
|
+
x86_64-darwin-19
|
160
|
+
|
161
|
+
DEPENDENCIES
|
162
|
+
byebug
|
163
|
+
combustion
|
164
|
+
database_cleaner
|
165
|
+
gemika
|
166
|
+
mysql2
|
167
|
+
rails (~> 7.0.0)
|
168
|
+
rake
|
169
|
+
rspec (~> 3.4)
|
170
|
+
temporal_tables!
|
171
|
+
|
172
|
+
BUNDLED WITH
|
173
|
+
2.2.3
|
@@ -0,0 +1,173 @@
|
|
1
|
+
PATH
|
2
|
+
remote: ..
|
3
|
+
specs:
|
4
|
+
temporal_tables (1.0.1)
|
5
|
+
rails (>= 6.0, < 7.1)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
actioncable (7.0.0)
|
11
|
+
actionpack (= 7.0.0)
|
12
|
+
activesupport (= 7.0.0)
|
13
|
+
nio4r (~> 2.0)
|
14
|
+
websocket-driver (>= 0.6.1)
|
15
|
+
actionmailbox (7.0.0)
|
16
|
+
actionpack (= 7.0.0)
|
17
|
+
activejob (= 7.0.0)
|
18
|
+
activerecord (= 7.0.0)
|
19
|
+
activestorage (= 7.0.0)
|
20
|
+
activesupport (= 7.0.0)
|
21
|
+
mail (>= 2.7.1)
|
22
|
+
actionmailer (7.0.0)
|
23
|
+
actionpack (= 7.0.0)
|
24
|
+
actionview (= 7.0.0)
|
25
|
+
activejob (= 7.0.0)
|
26
|
+
activesupport (= 7.0.0)
|
27
|
+
mail (~> 2.5, >= 2.5.4)
|
28
|
+
rails-dom-testing (~> 2.0)
|
29
|
+
actionpack (7.0.0)
|
30
|
+
actionview (= 7.0.0)
|
31
|
+
activesupport (= 7.0.0)
|
32
|
+
rack (~> 2.0, >= 2.2.0)
|
33
|
+
rack-test (>= 0.6.3)
|
34
|
+
rails-dom-testing (~> 2.0)
|
35
|
+
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
36
|
+
actiontext (7.0.0)
|
37
|
+
actionpack (= 7.0.0)
|
38
|
+
activerecord (= 7.0.0)
|
39
|
+
activestorage (= 7.0.0)
|
40
|
+
activesupport (= 7.0.0)
|
41
|
+
globalid (>= 0.6.0)
|
42
|
+
nokogiri (>= 1.8.5)
|
43
|
+
actionview (7.0.0)
|
44
|
+
activesupport (= 7.0.0)
|
45
|
+
builder (~> 3.1)
|
46
|
+
erubi (~> 1.4)
|
47
|
+
rails-dom-testing (~> 2.0)
|
48
|
+
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
49
|
+
activejob (7.0.0)
|
50
|
+
activesupport (= 7.0.0)
|
51
|
+
globalid (>= 0.3.6)
|
52
|
+
activemodel (7.0.0)
|
53
|
+
activesupport (= 7.0.0)
|
54
|
+
activerecord (7.0.0)
|
55
|
+
activemodel (= 7.0.0)
|
56
|
+
activesupport (= 7.0.0)
|
57
|
+
activestorage (7.0.0)
|
58
|
+
actionpack (= 7.0.0)
|
59
|
+
activejob (= 7.0.0)
|
60
|
+
activerecord (= 7.0.0)
|
61
|
+
activesupport (= 7.0.0)
|
62
|
+
marcel (~> 1.0)
|
63
|
+
mini_mime (>= 1.1.0)
|
64
|
+
activesupport (7.0.0)
|
65
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
66
|
+
i18n (>= 1.6, < 2)
|
67
|
+
minitest (>= 5.1)
|
68
|
+
tzinfo (~> 2.0)
|
69
|
+
builder (3.2.4)
|
70
|
+
byebug (11.1.3)
|
71
|
+
combustion (1.3.5)
|
72
|
+
activesupport (>= 3.0.0)
|
73
|
+
railties (>= 3.0.0)
|
74
|
+
thor (>= 0.14.6)
|
75
|
+
concurrent-ruby (1.1.9)
|
76
|
+
crass (1.0.6)
|
77
|
+
database_cleaner (2.0.1)
|
78
|
+
database_cleaner-active_record (~> 2.0.0)
|
79
|
+
database_cleaner-active_record (2.0.1)
|
80
|
+
activerecord (>= 5.a)
|
81
|
+
database_cleaner-core (~> 2.0.0)
|
82
|
+
database_cleaner-core (2.0.1)
|
83
|
+
diff-lcs (1.5.0)
|
84
|
+
erubi (1.10.0)
|
85
|
+
gemika (0.6.1)
|
86
|
+
globalid (1.0.0)
|
87
|
+
activesupport (>= 5.0)
|
88
|
+
i18n (1.8.11)
|
89
|
+
concurrent-ruby (~> 1.0)
|
90
|
+
loofah (2.13.0)
|
91
|
+
crass (~> 1.0.2)
|
92
|
+
nokogiri (>= 1.5.9)
|
93
|
+
mail (2.7.1)
|
94
|
+
mini_mime (>= 0.1.1)
|
95
|
+
marcel (1.0.2)
|
96
|
+
method_source (1.0.0)
|
97
|
+
mini_mime (1.1.2)
|
98
|
+
minitest (5.15.0)
|
99
|
+
nio4r (2.5.8)
|
100
|
+
nokogiri (1.12.5-arm64-darwin)
|
101
|
+
racc (~> 1.4)
|
102
|
+
nokogiri (1.12.5-x86_64-darwin)
|
103
|
+
racc (~> 1.4)
|
104
|
+
pg (1.2.3)
|
105
|
+
racc (1.6.0)
|
106
|
+
rack (2.2.3)
|
107
|
+
rack-test (1.1.0)
|
108
|
+
rack (>= 1.0, < 3)
|
109
|
+
rails (7.0.0)
|
110
|
+
actioncable (= 7.0.0)
|
111
|
+
actionmailbox (= 7.0.0)
|
112
|
+
actionmailer (= 7.0.0)
|
113
|
+
actionpack (= 7.0.0)
|
114
|
+
actiontext (= 7.0.0)
|
115
|
+
actionview (= 7.0.0)
|
116
|
+
activejob (= 7.0.0)
|
117
|
+
activemodel (= 7.0.0)
|
118
|
+
activerecord (= 7.0.0)
|
119
|
+
activestorage (= 7.0.0)
|
120
|
+
activesupport (= 7.0.0)
|
121
|
+
bundler (>= 1.15.0)
|
122
|
+
railties (= 7.0.0)
|
123
|
+
rails-dom-testing (2.0.3)
|
124
|
+
activesupport (>= 4.2.0)
|
125
|
+
nokogiri (>= 1.6)
|
126
|
+
rails-html-sanitizer (1.4.2)
|
127
|
+
loofah (~> 2.3)
|
128
|
+
railties (7.0.0)
|
129
|
+
actionpack (= 7.0.0)
|
130
|
+
activesupport (= 7.0.0)
|
131
|
+
method_source
|
132
|
+
rake (>= 12.2)
|
133
|
+
thor (~> 1.0)
|
134
|
+
zeitwerk (~> 2.5)
|
135
|
+
rake (13.0.6)
|
136
|
+
rspec (3.10.0)
|
137
|
+
rspec-core (~> 3.10.0)
|
138
|
+
rspec-expectations (~> 3.10.0)
|
139
|
+
rspec-mocks (~> 3.10.0)
|
140
|
+
rspec-core (3.10.1)
|
141
|
+
rspec-support (~> 3.10.0)
|
142
|
+
rspec-expectations (3.10.1)
|
143
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
144
|
+
rspec-support (~> 3.10.0)
|
145
|
+
rspec-mocks (3.10.2)
|
146
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
147
|
+
rspec-support (~> 3.10.0)
|
148
|
+
rspec-support (3.10.3)
|
149
|
+
thor (1.1.0)
|
150
|
+
tzinfo (2.0.4)
|
151
|
+
concurrent-ruby (~> 1.0)
|
152
|
+
websocket-driver (0.7.5)
|
153
|
+
websocket-extensions (>= 0.1.0)
|
154
|
+
websocket-extensions (0.1.5)
|
155
|
+
zeitwerk (2.5.3)
|
156
|
+
|
157
|
+
PLATFORMS
|
158
|
+
arm64-darwin-20
|
159
|
+
x86_64-darwin-19
|
160
|
+
|
161
|
+
DEPENDENCIES
|
162
|
+
byebug
|
163
|
+
combustion
|
164
|
+
database_cleaner
|
165
|
+
gemika
|
166
|
+
pg (>= 0.18, < 2.0)
|
167
|
+
rails (~> 7.0.0)
|
168
|
+
rake
|
169
|
+
rspec (~> 3.4)
|
170
|
+
temporal_tables!
|
171
|
+
|
172
|
+
BUNDLED WITH
|
173
|
+
2.2.3
|
@@ -1,19 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module TemporalTables
|
2
|
-
# This is required for eager_load to work
|
4
|
+
# This is required for eager_load to work
|
3
5
|
module ArelTable
|
4
6
|
def create_join(to, constraint = nil, klass = Arel::Nodes::InnerJoin)
|
5
7
|
join = super
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
8
|
+
at_value = Thread.current[:at_time]
|
9
|
+
if at_value
|
10
|
+
join =
|
11
|
+
join
|
12
|
+
.and(to[:eff_to].gteq(at_value))
|
13
|
+
.and(to[:eff_from].lteq(at_value))
|
10
14
|
end
|
11
15
|
join
|
12
16
|
end
|
13
17
|
end
|
14
18
|
end
|
15
19
|
|
16
|
-
|
17
|
-
when 6
|
18
|
-
Arel::Table.prepend TemporalTables::ArelTable
|
19
|
-
end
|
20
|
+
Arel::Table.prepend TemporalTables::ArelTable
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module TemporalTables
|
2
4
|
module ConnectionAdapters
|
3
5
|
module AbstractMysqlAdapter
|
@@ -7,7 +9,7 @@ module TemporalTables
|
|
7
9
|
execute "drop trigger #{table_name}_ad"
|
8
10
|
end
|
9
11
|
|
10
|
-
def create_temporal_triggers(table_name)
|
12
|
+
def create_temporal_triggers(table_name) # rubocop:disable Metrics/MethodLength
|
11
13
|
column_names = columns(table_name).map(&:name)
|
12
14
|
|
13
15
|
execute %{
|
@@ -17,7 +19,7 @@ module TemporalTables
|
|
17
19
|
set @current_time = utc_timestamp(6);
|
18
20
|
|
19
21
|
insert into #{temporal_name(table_name)} (#{column_names.join(', ')}, eff_from)
|
20
|
-
values (#{column_names.collect {|c| "new.#{c}"}.join(', ')}, @current_time);
|
22
|
+
values (#{column_names.collect { |c| "new.#{c}" }.join(', ')}, @current_time);
|
21
23
|
|
22
24
|
end
|
23
25
|
}
|
@@ -33,7 +35,7 @@ module TemporalTables
|
|
33
35
|
and eff_to = '9999-12-31';
|
34
36
|
|
35
37
|
insert into #{temporal_name(table_name)} (#{column_names.join(', ')}, eff_from)
|
36
|
-
values (#{column_names.collect {|c| "new.#{c}"}.join(', ')}, @current_time);
|
38
|
+
values (#{column_names.collect { |c| "new.#{c}" }.join(', ')}, @current_time);
|
37
39
|
|
38
40
|
end
|
39
41
|
}
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module TemporalTables
|
2
4
|
module ConnectionAdapters
|
3
5
|
module PostgreSQLAdapter
|
@@ -7,7 +9,7 @@ module TemporalTables
|
|
7
9
|
execute "drop trigger #{table_name}_ad on #{table_name}"
|
8
10
|
end
|
9
11
|
|
10
|
-
def create_temporal_triggers(table_name)
|
12
|
+
def create_temporal_triggers(table_name) # rubocop:disable Metrics/MethodLength
|
11
13
|
column_names = columns(table_name).map(&:name)
|
12
14
|
|
13
15
|
execute %{
|
@@ -18,7 +20,7 @@ module TemporalTables
|
|
18
20
|
cur_time := localtimestamp;
|
19
21
|
|
20
22
|
insert into #{temporal_name(table_name)} (#{column_list(column_names)}, eff_from)
|
21
|
-
values (#{column_names.collect {|c| "new.#{c}"}.join(', ')}, cur_time);
|
23
|
+
values (#{column_names.collect { |c| "new.#{c}" }.join(', ')}, cur_time);
|
22
24
|
|
23
25
|
return null;
|
24
26
|
end
|
@@ -41,7 +43,7 @@ module TemporalTables
|
|
41
43
|
and eff_to = '9999-12-31';
|
42
44
|
|
43
45
|
insert into #{temporal_name(table_name)} (#{column_list(column_names)}, eff_from)
|
44
|
-
values (#{column_names.collect {|c| "new.#{c}"}.join(', ')}, cur_time);
|
46
|
+
values (#{column_names.collect { |c| "new.#{c}" }.join(', ')}, cur_time);
|
45
47
|
|
46
48
|
return null;
|
47
49
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module TemporalTables
|
2
4
|
# This hooks in a "history" method to ActiveRecord::Base which will
|
3
5
|
# return the class's History class. The history class extends the original
|
@@ -8,14 +10,15 @@ module TemporalTables
|
|
8
10
|
# end
|
9
11
|
#
|
10
12
|
# Person #=> Person(id: integer, name: string)
|
11
|
-
# Person.history #=> PersonHistory(history_id: integer, id: integer,
|
13
|
+
# Person.history #=> PersonHistory(history_id: integer, id: integer,
|
14
|
+
# name: string, eff_from: datetime, eff_to: datetime)
|
12
15
|
module HistoryHook
|
13
|
-
def self.included(base)
|
16
|
+
def self.included(base) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
14
17
|
base.class_eval do
|
15
18
|
# Return this class's history class.
|
16
19
|
# If it doesn't exist yet, create and initialize it, as well
|
17
20
|
# as all dependent classes (through associations).
|
18
|
-
def self.history
|
21
|
+
def self.history # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
19
22
|
raise "Can't view history of history" if name =~ /History$/
|
20
23
|
|
21
24
|
history_class = "#{name}History"
|
@@ -25,7 +28,7 @@ module TemporalTables
|
|
25
28
|
new_class = Class.new(self) do
|
26
29
|
include TemporalTables::TemporalClass
|
27
30
|
end
|
28
|
-
segments = history_class.split(
|
31
|
+
segments = history_class.split('::')
|
29
32
|
object_class = segments[0...-1].inject(Object) { |o, s| o.const_get(s) }
|
30
33
|
object_class.const_set segments.last, new_class
|
31
34
|
|
@@ -47,4 +50,4 @@ module TemporalTables
|
|
47
50
|
end
|
48
51
|
end
|
49
52
|
|
50
|
-
ActiveRecord::Base.
|
53
|
+
ActiveRecord::Base.include TemporalTables::HistoryHook
|
@@ -1,21 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module TemporalTables
|
2
|
-
# This is required for eager_load to work in
|
4
|
+
# This is required for eager_load to work in 6.1
|
3
5
|
module AbstractReflectionExtensions
|
4
|
-
def
|
6
|
+
def join_scope(table, foreign_table, foreign_klass)
|
5
7
|
constraint = super
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
constraint
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
8
|
+
at_value = Thread.current[:at_time]
|
9
|
+
|
10
|
+
return constraint unless at_value
|
13
11
|
|
14
|
-
|
15
|
-
|
16
|
-
case Rails::VERSION::MINOR
|
17
|
-
when 2
|
18
|
-
ActiveRecord::Reflection::AbstractReflection.prepend TemporalTables::AbstractReflectionExtensions
|
12
|
+
constraint.where(klass.build_temporal_constraint(at_value))
|
13
|
+
end
|
19
14
|
end
|
20
15
|
end
|
21
16
|
|
17
|
+
prepend_reflection = ActiveRecord.version > ::Gem::Version.new('6.1.0')
|
18
|
+
ActiveRecord::Reflection::AbstractReflection.prepend TemporalTables::AbstractReflectionExtensions if prepend_reflection
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module TemporalTables
|
2
4
|
# Stores the time from the "at" field into each of the resulting objects
|
3
5
|
# so that it can be carried forward in subsequent queries.
|
@@ -9,21 +11,11 @@ module TemporalTables
|
|
9
11
|
end
|
10
12
|
|
11
13
|
def at_value
|
12
|
-
|
13
|
-
when 0
|
14
|
-
@values.fetch(:at, nil) || Thread.current[:at_time]
|
15
|
-
else
|
16
|
-
get_value(:at) || Thread.current[:at_time]
|
17
|
-
end
|
14
|
+
@values.fetch(:at, nil) || Thread.current[:at_time]
|
18
15
|
end
|
19
16
|
|
20
17
|
def at_value=(value)
|
21
|
-
|
22
|
-
when 0
|
23
|
-
@values[:at] = value
|
24
|
-
else
|
25
|
-
set_value(:at, value)
|
26
|
-
end
|
18
|
+
@values[:at] = value
|
27
19
|
end
|
28
20
|
|
29
21
|
def at(*args)
|
@@ -32,13 +24,11 @@ module TemporalTables
|
|
32
24
|
|
33
25
|
def at!(value)
|
34
26
|
self.at_value = value
|
35
|
-
|
27
|
+
where!(klass.build_temporal_constraint(value))
|
36
28
|
end
|
37
29
|
|
38
30
|
def to_sql(*args)
|
39
|
-
threadify_at
|
40
|
-
super *args
|
41
|
-
end
|
31
|
+
threadify_at { super(*args) }
|
42
32
|
end
|
43
33
|
|
44
34
|
def threadify_at
|
@@ -53,9 +43,7 @@ module TemporalTables
|
|
53
43
|
end
|
54
44
|
|
55
45
|
def limited_ids_for(*args)
|
56
|
-
threadify_at
|
57
|
-
super *args
|
58
|
-
end
|
46
|
+
threadify_at { super(*args) }
|
59
47
|
end
|
60
48
|
|
61
49
|
def exec_queries
|
@@ -63,17 +51,16 @@ module TemporalTables
|
|
63
51
|
# MyClass.includes(:associations)
|
64
52
|
# happens within this exec_queries call. That's why we needed to
|
65
53
|
# store the at_time in the thread above.
|
66
|
-
threadify_at
|
67
|
-
super
|
68
|
-
end
|
54
|
+
records = threadify_at { super }
|
69
55
|
|
70
56
|
if historical?
|
71
57
|
# Store the at value on each record returned
|
72
|
-
|
58
|
+
records.each do |r|
|
73
59
|
r.at_value = at_value
|
74
60
|
end
|
75
61
|
end
|
76
|
-
@records
|
62
|
+
@records = records
|
63
|
+
records
|
77
64
|
end
|
78
65
|
|
79
66
|
def historical?
|