historiographer 4.1.14 → 4.3.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 (65) hide show
  1. checksums.yaml +4 -4
  2. data/.document +5 -0
  3. data/.rspec +1 -0
  4. data/.ruby-version +1 -0
  5. data/.standalone_migrations +6 -0
  6. data/Gemfile +33 -0
  7. data/Gemfile.lock +341 -0
  8. data/Guardfile +4 -0
  9. data/README.md +0 -168
  10. data/Rakefile +54 -0
  11. data/VERSION +1 -0
  12. data/historiographer-4.1.12.gem +0 -0
  13. data/historiographer-4.1.13.gem +0 -0
  14. data/historiographer-4.1.14.gem +0 -0
  15. data/historiographer.gemspec +136 -0
  16. data/init.rb +18 -0
  17. data/instructions/implementation.md +282 -0
  18. data/instructions/todo.md +96 -0
  19. data/lib/historiographer/history.rb +1 -20
  20. data/lib/historiographer/version.rb +1 -1
  21. data/lib/historiographer.rb +27 -14
  22. data/spec/db/database.yml +27 -0
  23. data/spec/db/migrate/20161121212228_create_posts.rb +19 -0
  24. data/spec/db/migrate/20161121212229_create_post_histories.rb +10 -0
  25. data/spec/db/migrate/20161121212230_create_authors.rb +13 -0
  26. data/spec/db/migrate/20161121212231_create_author_histories.rb +10 -0
  27. data/spec/db/migrate/20161121212232_create_users.rb +9 -0
  28. data/spec/db/migrate/20171011194624_create_safe_posts.rb +19 -0
  29. data/spec/db/migrate/20171011194715_create_safe_post_histories.rb +9 -0
  30. data/spec/db/migrate/20191024142304_create_thing_with_compound_index.rb +10 -0
  31. data/spec/db/migrate/20191024142352_create_thing_with_compound_index_history.rb +11 -0
  32. data/spec/db/migrate/20191024203106_create_thing_without_history.rb +7 -0
  33. data/spec/db/migrate/20221018204220_create_silent_posts.rb +21 -0
  34. data/spec/db/migrate/20221018204255_create_silent_post_histories.rb +9 -0
  35. data/spec/db/migrate/20241109182017_create_comments.rb +13 -0
  36. data/spec/db/migrate/20241109182020_create_comment_histories.rb +9 -0
  37. data/spec/db/migrate/20241119000000_create_datasets.rb +17 -0
  38. data/spec/db/migrate/2025082100000_create_projects.rb +14 -0
  39. data/spec/db/migrate/2025082100001_create_project_files.rb +18 -0
  40. data/spec/db/schema.rb +352 -0
  41. data/spec/factories/post.rb +7 -0
  42. data/spec/historiographer_spec.rb +920 -0
  43. data/spec/models/application_record.rb +3 -0
  44. data/spec/models/author.rb +5 -0
  45. data/spec/models/author_history.rb +4 -0
  46. data/spec/models/comment.rb +5 -0
  47. data/spec/models/comment_history.rb +5 -0
  48. data/spec/models/easy_ml/column.rb +6 -0
  49. data/spec/models/easy_ml/column_history.rb +6 -0
  50. data/spec/models/post.rb +45 -0
  51. data/spec/models/post_history.rb +8 -0
  52. data/spec/models/project.rb +4 -0
  53. data/spec/models/project_file.rb +5 -0
  54. data/spec/models/project_file_history.rb +4 -0
  55. data/spec/models/project_history.rb +4 -0
  56. data/spec/models/safe_post.rb +5 -0
  57. data/spec/models/safe_post_history.rb +5 -0
  58. data/spec/models/silent_post.rb +3 -0
  59. data/spec/models/silent_post_history.rb +4 -0
  60. data/spec/models/thing_with_compound_index.rb +3 -0
  61. data/spec/models/thing_with_compound_index_history.rb +4 -0
  62. data/spec/models/thing_without_history.rb +2 -0
  63. data/spec/models/user.rb +2 -0
  64. data/spec/spec_helper.rb +105 -0
  65. metadata +62 -31
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9eae77a7f8f3cfb9251c7bb4a22a965365648773ef43982a75be730639400caa
4
- data.tar.gz: 75c2492ef39fd1d64595227c0ed7b36bc01347b79c4ee7b883bddcac60039a6f
3
+ metadata.gz: df0f832698c8177c8785d913caa4c26e2374e10ea813896190481b091a3176a6
4
+ data.tar.gz: 3bcf25861fed71c432c47e97489b2ffae7a42d70960e6d321ce8b4b24c8a5c89
5
5
  SHA512:
6
- metadata.gz: 36e424a231f6444607b1e9b463cac9720e50640ac0665d173e1bc32c2184f89793c4ed8039555b3a63826b9aac2c0b28455c9cfc734ab447026e4c2507f891fb
7
- data.tar.gz: 5570bcd7285e1674b7aab271d9b64e79aff1e01cc94b9c58799d02a1fb4c2090bf0384aa3e0d8be2a5691c4bab0dcdeb3e4955691a44f05fbb3277ca026982d1
6
+ metadata.gz: df1430488c6120b9126aff4a526fb2aba8f84a6aad8690592b977a45b5031674ee3722818c8679881c96cd950b50a81089d4a363948cddcf65e253051792a524
7
+ data.tar.gz: 4bb03df9ecd8998fb1866bc2d5ada28b509d1122787e6ef7b47375d0a3dc18bd8bd14f8e846d1b6e5702c9a2f5a53366680d6855126c742c48526d9048d211d4
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.0.2
@@ -0,0 +1,6 @@
1
+ db:
2
+ seeds: spec/db/seeds.rb
3
+ migrate: spec/db/migrate
4
+ schema: spec/db/schema.rb
5
+ config:
6
+ database: spec/db/database.yml
data/Gemfile ADDED
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+ ruby '3.0.2'
5
+
6
+ gem 'activerecord', '>= 6'
7
+ gem 'activerecord-import'
8
+ gem 'activesupport'
9
+ gem 'rails', '>= 6'
10
+ gem 'rollbar'
11
+
12
+ group :development, :test do
13
+ gem 'mysql2', '0.5'
14
+ gem 'paranoia'
15
+ gem 'pg'
16
+ gem 'pry'
17
+ gem 'standalone_migrations'
18
+ gem 'timecop'
19
+ end
20
+
21
+ group :development do
22
+ gem 'jeweler', git: 'https://github.com/technicalpickles/jeweler', branch: 'master'
23
+ gem 'rdoc', '~> 3.12'
24
+ gem 'simplecov', '>= 0'
25
+ end
26
+
27
+ group :test do
28
+ gem 'database_cleaner'
29
+ gem 'factory_bot_rails'
30
+ gem 'guard'
31
+ gem 'guard-rspec'
32
+ gem 'rspec'
33
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,341 @@
1
+ GIT
2
+ remote: https://github.com/technicalpickles/jeweler
3
+ revision: 2ab86309fc2494ba2a4e9c86c514742cd4f681c2
4
+ branch: master
5
+ specs:
6
+ jeweler (2.3.9)
7
+ builder
8
+ bundler
9
+ git (>= 1.2.5)
10
+ github_api (~> 0.16.0)
11
+ highline (>= 1.6.15)
12
+ nokogiri (>= 1.5.10)
13
+ psych
14
+ rake
15
+ rdoc
16
+ semver2
17
+
18
+ GEM
19
+ remote: https://rubygems.org/
20
+ specs:
21
+ actioncable (7.1.5)
22
+ actionpack (= 7.1.5)
23
+ activesupport (= 7.1.5)
24
+ nio4r (~> 2.0)
25
+ websocket-driver (>= 0.6.1)
26
+ zeitwerk (~> 2.6)
27
+ actionmailbox (7.1.5)
28
+ actionpack (= 7.1.5)
29
+ activejob (= 7.1.5)
30
+ activerecord (= 7.1.5)
31
+ activestorage (= 7.1.5)
32
+ activesupport (= 7.1.5)
33
+ mail (>= 2.7.1)
34
+ net-imap
35
+ net-pop
36
+ net-smtp
37
+ actionmailer (7.1.5)
38
+ actionpack (= 7.1.5)
39
+ actionview (= 7.1.5)
40
+ activejob (= 7.1.5)
41
+ activesupport (= 7.1.5)
42
+ mail (~> 2.5, >= 2.5.4)
43
+ net-imap
44
+ net-pop
45
+ net-smtp
46
+ rails-dom-testing (~> 2.2)
47
+ actionpack (7.1.5)
48
+ actionview (= 7.1.5)
49
+ activesupport (= 7.1.5)
50
+ nokogiri (>= 1.8.5)
51
+ racc
52
+ rack (>= 2.2.4)
53
+ rack-session (>= 1.0.1)
54
+ rack-test (>= 0.6.3)
55
+ rails-dom-testing (~> 2.2)
56
+ rails-html-sanitizer (~> 1.6)
57
+ actiontext (7.1.5)
58
+ actionpack (= 7.1.5)
59
+ activerecord (= 7.1.5)
60
+ activestorage (= 7.1.5)
61
+ activesupport (= 7.1.5)
62
+ globalid (>= 0.6.0)
63
+ nokogiri (>= 1.8.5)
64
+ actionview (7.1.5)
65
+ activesupport (= 7.1.5)
66
+ builder (~> 3.1)
67
+ erubi (~> 1.11)
68
+ rails-dom-testing (~> 2.2)
69
+ rails-html-sanitizer (~> 1.6)
70
+ activejob (7.1.5)
71
+ activesupport (= 7.1.5)
72
+ globalid (>= 0.3.6)
73
+ activemodel (7.1.5)
74
+ activesupport (= 7.1.5)
75
+ activerecord (7.1.5)
76
+ activemodel (= 7.1.5)
77
+ activesupport (= 7.1.5)
78
+ timeout (>= 0.4.0)
79
+ activerecord-import (1.8.1)
80
+ activerecord (>= 4.2)
81
+ activestorage (7.1.5)
82
+ actionpack (= 7.1.5)
83
+ activejob (= 7.1.5)
84
+ activerecord (= 7.1.5)
85
+ activesupport (= 7.1.5)
86
+ marcel (~> 1.0)
87
+ activesupport (7.1.5)
88
+ base64
89
+ benchmark (>= 0.3)
90
+ bigdecimal
91
+ concurrent-ruby (~> 1.0, >= 1.0.2)
92
+ connection_pool (>= 2.2.5)
93
+ drb
94
+ i18n (>= 1.6, < 2)
95
+ logger (>= 1.4.2)
96
+ minitest (>= 5.1)
97
+ mutex_m
98
+ securerandom (>= 0.3)
99
+ tzinfo (~> 2.0)
100
+ addressable (2.4.0)
101
+ base64 (0.2.0)
102
+ benchmark (0.4.0)
103
+ bigdecimal (3.1.8)
104
+ builder (3.3.0)
105
+ coderay (1.1.3)
106
+ concurrent-ruby (1.3.4)
107
+ connection_pool (2.4.1)
108
+ crass (1.0.6)
109
+ database_cleaner (2.1.0)
110
+ database_cleaner-active_record (>= 2, < 3)
111
+ database_cleaner-active_record (2.2.0)
112
+ activerecord (>= 5.a)
113
+ database_cleaner-core (~> 2.0.0)
114
+ database_cleaner-core (2.0.1)
115
+ date (3.4.0)
116
+ descendants_tracker (0.0.4)
117
+ thread_safe (~> 0.3, >= 0.3.1)
118
+ diff-lcs (1.5.1)
119
+ docile (1.4.1)
120
+ drb (2.2.1)
121
+ erubi (1.13.0)
122
+ factory_bot (6.5.0)
123
+ activesupport (>= 5.0.0)
124
+ factory_bot_rails (6.4.4)
125
+ factory_bot (~> 6.5)
126
+ railties (>= 5.0.0)
127
+ faraday (0.9.2)
128
+ multipart-post (>= 1.2, < 3)
129
+ ffi (1.17.0-arm64-darwin)
130
+ ffi (1.17.0-x86_64-darwin)
131
+ formatador (1.1.0)
132
+ git (1.11.0)
133
+ rchardet (~> 1.8)
134
+ github_api (0.16.0)
135
+ addressable (~> 2.4.0)
136
+ descendants_tracker (~> 0.0.4)
137
+ faraday (~> 0.8, < 0.10)
138
+ hashie (>= 3.4)
139
+ mime-types (>= 1.16, < 3.0)
140
+ oauth2 (~> 1.0)
141
+ globalid (1.2.1)
142
+ activesupport (>= 6.1)
143
+ guard (2.19.0)
144
+ formatador (>= 0.2.4)
145
+ listen (>= 2.7, < 4.0)
146
+ lumberjack (>= 1.0.12, < 2.0)
147
+ nenv (~> 0.1)
148
+ notiffany (~> 0.0)
149
+ pry (>= 0.13.0)
150
+ shellany (~> 0.0)
151
+ thor (>= 0.18.1)
152
+ guard-compat (1.2.1)
153
+ guard-rspec (4.7.3)
154
+ guard (~> 2.1)
155
+ guard-compat (~> 1.1)
156
+ rspec (>= 2.99.0, < 4.0)
157
+ hashie (5.0.0)
158
+ highline (3.1.1)
159
+ reline
160
+ i18n (1.14.6)
161
+ concurrent-ruby (~> 1.0)
162
+ io-console (0.7.2)
163
+ irb (1.12.0)
164
+ rdoc
165
+ reline (>= 0.4.2)
166
+ json (1.8.6)
167
+ jwt (2.9.3)
168
+ base64
169
+ listen (3.9.0)
170
+ rb-fsevent (~> 0.10, >= 0.10.3)
171
+ rb-inotify (~> 0.9, >= 0.9.10)
172
+ logger (1.6.1)
173
+ loofah (2.23.1)
174
+ crass (~> 1.0.2)
175
+ nokogiri (>= 1.12.0)
176
+ lumberjack (1.2.10)
177
+ mail (2.8.1)
178
+ mini_mime (>= 0.1.1)
179
+ net-imap
180
+ net-pop
181
+ net-smtp
182
+ marcel (1.0.4)
183
+ method_source (1.1.0)
184
+ mime-types (2.99.3)
185
+ mini_mime (1.1.5)
186
+ minitest (5.25.1)
187
+ multi_json (1.15.0)
188
+ multi_xml (0.6.0)
189
+ multipart-post (2.4.1)
190
+ mutex_m (0.2.0)
191
+ mysql2 (0.5.0)
192
+ nenv (0.3.0)
193
+ net-imap (0.4.18)
194
+ date
195
+ net-protocol
196
+ net-pop (0.1.2)
197
+ net-protocol
198
+ net-protocol (0.2.2)
199
+ timeout
200
+ net-smtp (0.5.0)
201
+ net-protocol
202
+ nio4r (2.7.4)
203
+ nokogiri (1.16.7-arm64-darwin)
204
+ racc (~> 1.4)
205
+ nokogiri (1.16.7-x86_64-darwin)
206
+ racc (~> 1.4)
207
+ notiffany (0.1.3)
208
+ nenv (~> 0.1)
209
+ shellany (~> 0.0)
210
+ oauth2 (1.4.8)
211
+ faraday (>= 0.8, < 3.0)
212
+ jwt (>= 1.0, < 3.0)
213
+ multi_json (~> 1.3)
214
+ multi_xml (~> 0.5)
215
+ rack (>= 1.2, < 3)
216
+ paranoia (3.0.0)
217
+ activerecord (>= 6, < 8.1)
218
+ pg (1.5.9)
219
+ pry (0.14.2)
220
+ coderay (~> 1.1)
221
+ method_source (~> 1.0)
222
+ psych (5.2.0)
223
+ stringio
224
+ racc (1.8.1)
225
+ rack (2.2.10)
226
+ rack-session (1.0.2)
227
+ rack (< 3)
228
+ rack-test (2.1.0)
229
+ rack (>= 1.3)
230
+ rackup (1.0.1)
231
+ rack (< 3)
232
+ webrick
233
+ rails (7.1.5)
234
+ actioncable (= 7.1.5)
235
+ actionmailbox (= 7.1.5)
236
+ actionmailer (= 7.1.5)
237
+ actionpack (= 7.1.5)
238
+ actiontext (= 7.1.5)
239
+ actionview (= 7.1.5)
240
+ activejob (= 7.1.5)
241
+ activemodel (= 7.1.5)
242
+ activerecord (= 7.1.5)
243
+ activestorage (= 7.1.5)
244
+ activesupport (= 7.1.5)
245
+ bundler (>= 1.15.0)
246
+ railties (= 7.1.5)
247
+ rails-dom-testing (2.2.0)
248
+ activesupport (>= 5.0.0)
249
+ minitest
250
+ nokogiri (>= 1.6)
251
+ rails-html-sanitizer (1.6.0)
252
+ loofah (~> 2.21)
253
+ nokogiri (~> 1.14)
254
+ railties (7.1.5)
255
+ actionpack (= 7.1.5)
256
+ activesupport (= 7.1.5)
257
+ irb
258
+ rackup (>= 1.0.0)
259
+ rake (>= 12.2)
260
+ thor (~> 1.0, >= 1.2.2)
261
+ zeitwerk (~> 2.6)
262
+ rake (13.2.1)
263
+ rb-fsevent (0.11.2)
264
+ rb-inotify (0.11.1)
265
+ ffi (~> 1.0)
266
+ rchardet (1.8.0)
267
+ rdoc (3.12.2)
268
+ json (~> 1.4)
269
+ reline (0.5.11)
270
+ io-console (~> 0.5)
271
+ rollbar (3.6.0)
272
+ rspec (3.13.0)
273
+ rspec-core (~> 3.13.0)
274
+ rspec-expectations (~> 3.13.0)
275
+ rspec-mocks (~> 3.13.0)
276
+ rspec-core (3.13.2)
277
+ rspec-support (~> 3.13.0)
278
+ rspec-expectations (3.13.3)
279
+ diff-lcs (>= 1.2.0, < 2.0)
280
+ rspec-support (~> 3.13.0)
281
+ rspec-mocks (3.13.2)
282
+ diff-lcs (>= 1.2.0, < 2.0)
283
+ rspec-support (~> 3.13.0)
284
+ rspec-support (3.13.1)
285
+ securerandom (0.3.1)
286
+ semver2 (3.4.2)
287
+ shellany (0.0.1)
288
+ simplecov (0.22.0)
289
+ docile (~> 1.1)
290
+ simplecov-html (~> 0.11)
291
+ simplecov_json_formatter (~> 0.1)
292
+ simplecov-html (0.13.1)
293
+ simplecov_json_formatter (0.1.4)
294
+ standalone_migrations (7.2.0)
295
+ activerecord (>= 6.0.0, < 8.0)
296
+ nokogiri (~> 1.14)
297
+ railties (>= 6.0.0, < 8.0)
298
+ rake (>= 10.0)
299
+ stringio (3.1.2)
300
+ thor (1.3.2)
301
+ thread_safe (0.3.6)
302
+ timecop (0.9.10)
303
+ timeout (0.4.2)
304
+ tzinfo (2.0.6)
305
+ concurrent-ruby (~> 1.0)
306
+ webrick (1.9.0)
307
+ websocket-driver (0.7.6)
308
+ websocket-extensions (>= 0.1.0)
309
+ websocket-extensions (0.1.5)
310
+ zeitwerk (2.6.18)
311
+
312
+ PLATFORMS
313
+ arm64-darwin
314
+ x86_64-darwin
315
+
316
+ DEPENDENCIES
317
+ activerecord (>= 6)
318
+ activerecord-import
319
+ activesupport
320
+ database_cleaner
321
+ factory_bot_rails
322
+ guard
323
+ guard-rspec
324
+ jeweler!
325
+ mysql2 (= 0.5)
326
+ paranoia
327
+ pg
328
+ pry
329
+ rails (>= 6)
330
+ rdoc (~> 3.12)
331
+ rollbar
332
+ rspec
333
+ simplecov
334
+ standalone_migrations
335
+ timecop
336
+
337
+ RUBY VERSION
338
+ ruby 3.0.2p107
339
+
340
+ BUNDLED WITH
341
+ 2.5.23
data/Guardfile ADDED
@@ -0,0 +1,4 @@
1
+ guard :rspec, cmd: "bundle exec rspec" do
2
+ watch(%r{^spec/.+\.rb$}) { |_m| "spec/historiographer_spec.rb" }
3
+ watch(%r{^lib/(.+)\.rb$}) { |_m| "spec/historiographer_spec.rb" }
4
+ end
data/README.md CHANGED
@@ -130,174 +130,6 @@ This can be useful when:
130
130
  - You're versioning training data for machine learning models
131
131
  - You need to maintain immutable audit trails at specific checkpoints
132
132
 
133
- ## Single Table Inheritance (STI)
134
-
135
- Historiographer fully supports Single Table Inheritance, both with the default `type` column and with custom inheritance columns.
136
-
137
- ### Default STI with `type` column
138
-
139
- ```ruby
140
- class Post < ActiveRecord::Base
141
- include Historiographer
142
- end
143
-
144
- class PrivatePost < Post
145
- end
146
-
147
- # The history classes follow the same inheritance pattern:
148
- class PostHistory < ActiveRecord::Base
149
- include Historiographer::History
150
- end
151
-
152
- class PrivatePostHistory < PostHistory
153
- end
154
- ```
155
-
156
- History records automatically maintain the correct STI type:
157
-
158
- ```ruby
159
- private_post = PrivatePost.create(title: "Secret", history_user_id: current_user.id)
160
- private_post.snapshot
161
-
162
- # History records are the correct subclass
163
- history = PostHistory.last
164
- history.is_a?(PrivatePostHistory) #=> true
165
- history.type #=> "PrivatePostHistory"
166
- ```
167
-
168
- ### Custom Inheritance Columns
169
-
170
- You can also use a custom column for STI instead of the default `type`:
171
-
172
- ```ruby
173
- class MLModel < ActiveRecord::Base
174
- self.inheritance_column = :model_type
175
- include Historiographer
176
- end
177
-
178
- class XGBoost < MLModel
179
- self.table_name = "ml_models"
180
- end
181
-
182
- # History classes use the same custom column
183
- class MLModelHistory < MLModel
184
- self.inheritance_column = :model_type
185
- self.table_name = "ml_model_histories"
186
- end
187
-
188
- class XGBoostHistory < MLModelHistory
189
- end
190
- ```
191
-
192
- Migration for custom inheritance column:
193
-
194
- ```ruby
195
- create_table :ml_models do |t|
196
- t.string :name
197
- t.string :model_type # Custom inheritance column
198
- t.jsonb :parameters
199
- t.timestamps
200
-
201
- t.index :model_type
202
- end
203
-
204
- create_table :ml_model_histories do |t|
205
- t.histories # Includes all columns from parent table
206
- end
207
- ```
208
-
209
- The custom inheritance column works just like the default `type`:
210
-
211
- ```ruby
212
- model = XGBoost.create(name: "My Model", history_user_id: current_user.id)
213
- model.snapshot
214
-
215
- # History records maintain the correct subclass
216
- history = MLModelHistory.last
217
- history.is_a?(XGBoostHistory) #=> true
218
- history.model_type #=> "XGBoostHistory"
219
- ```
220
-
221
- ### STI and Snapshots: Perfect for Model Versioning
222
-
223
- Single Table Inheritance combined with Historiographer's snapshot feature is particularly powerful for versioning machine learning models and other complex systems that need immutable historical records. Here's why:
224
-
225
- 1. **Type-Safe History**: When you snapshot an ML model, both the model and its parameters are preserved with their exact implementation type. This ensures that when you retrieve historical versions, you get back exactly the right subclass with its specific behavior:
226
-
227
- ```ruby
228
- # Create and configure an XGBoost model
229
- model = XGBoost.create(
230
- name: "Customer Churn Predictor v1",
231
- parameters: { max_depth: 3, eta: 0.1 },
232
- history_user_id: current_user.id
233
- )
234
-
235
- # Take a snapshot before training
236
- model.snapshot
237
-
238
- # Update the model after training
239
- model.update(
240
- name: "Customer Churn Predictor v2",
241
- parameters: { max_depth: 5, eta: 0.2 },
242
- history_user_id: current_user.id
243
- )
244
-
245
- # Later, retrieve the exact pre-training version
246
- historical_model = MLModel.latest_snapshot
247
- historical_model.is_a?(XGBoostHistory) #=> true
248
- historical_model.parameters #=> { max_depth: 3, eta: 0.1 }
249
- ```
250
-
251
- 2. **Implementation Versioning**: Different model types often have different parameters, preprocessing steps, or scoring methods. STI ensures these differences are preserved in history:
252
-
253
- ```ruby
254
- class XGBoost < MLModel
255
- def predict(data)
256
- # XGBoost-specific prediction logic
257
- end
258
- end
259
-
260
- class RandomForest < MLModel
261
- def predict(data)
262
- # RandomForest-specific prediction logic
263
- end
264
- end
265
-
266
- # Your historical records maintain these implementation differences
267
- old_model = MLModel.latest_snapshot
268
- old_model.predict(data) # Uses the exact prediction logic from that point in time
269
- ```
270
-
271
- 3. **Reproducibility**: Essential for ML workflows where you need to reproduce results or audit model behavior:
272
-
273
- ```ruby
274
- # Create model and snapshot at each significant stage
275
- model = XGBoost.create(name: "Risk Scorer v1", history_user_id: current_user.id)
276
-
277
- # Snapshot after initial configuration
278
- model.snapshot(metadata: { stage: "configuration" })
279
-
280
- # Snapshot after training
281
- model.update(parameters: trained_parameters)
282
- model.snapshot(metadata: { stage: "post_training" })
283
-
284
- # Snapshot after validation
285
- model.update(parameters: validated_parameters)
286
- model.snapshot(metadata: { stage: "validated" })
287
-
288
- # Later, you can retrieve any version to reproduce results
289
- initial_version = model.histories.find_by(metadata: { stage: "configuration" })
290
- trained_version = model.histories.find_by(metadata: { stage: "post_training" })
291
- ```
292
-
293
- This combination of STI and snapshots is particularly valuable for:
294
-
295
- - Model governance and compliance
296
- - A/B testing different model types
297
- - Debugging model behavior
298
- - Reproducing historical predictions
299
- - Maintaining audit trails for regulatory requirements
300
-
301
133
  ## Namespaced Models
302
134
 
303
135
  When using namespaced models, Rails handles foreign key naming differently than with non-namespaced models. For example, if you have a model namespaced like this:
data/Rakefile ADDED
@@ -0,0 +1,54 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ require 'pry'
6
+ begin
7
+ Bundler.setup(:default, :development)
8
+ rescue Bundler::BundlerError => e
9
+ $stderr.puts e.message
10
+ $stderr.puts "Run `bundle install` to install missing gems"
11
+ exit e.status_code
12
+ end
13
+ require 'rake'
14
+ require 'jeweler'
15
+
16
+ Jeweler::Tasks.new do |gem|
17
+ # gem is a Gem::Specification... see http://guides.rubygems.org/specification-reference/ for more options
18
+ gem.name = "historiographer"
19
+ gem.homepage = "http://github.com/brettshollenberger/historiographer"
20
+ gem.license = "MIT"
21
+ gem.summary = %Q{Create histories of your ActiveRecord tables}
22
+ gem.description = %Q{Creates separate tables for each history table}
23
+ gem.email = "brett.shollenberger@gmail.com"
24
+ gem.authors = ["brettshollenberger"]
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rake/testtask'
29
+ Rake::TestTask.new(:test) do |test|
30
+ test.libs << 'lib' << 'spec'
31
+ test.pattern = 'rspec/**/*_spec.rb'
32
+ test.verbose = true
33
+ end
34
+
35
+ desc "Code coverage detail"
36
+ task :simplecov do
37
+ ENV['COVERAGE'] = "true"
38
+ Rake::Task['test'].execute
39
+ end
40
+
41
+ task :default => :test
42
+
43
+ require 'rdoc/task'
44
+ Rake::RDocTask.new do |rdoc|
45
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
46
+
47
+ rdoc.rdoc_dir = 'rdoc'
48
+ rdoc.title = "historiographer #{version}"
49
+ rdoc.rdoc_files.include('README*')
50
+ rdoc.rdoc_files.include('lib/**/*.rb')
51
+ end
52
+
53
+ require 'standalone_migrations'
54
+ StandaloneMigrations::Tasks.load_tasks
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 4.3.0
Binary file
Binary file
Binary file