historiographer 4.0.0 → 4.1.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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +115 -39
  3. data/{Gemfile → Users/brettshollenberger/programming/historiographer/Gemfile} +0 -1
  4. data/Users/brettshollenberger/programming/historiographer/Gemfile.lock +341 -0
  5. data/Users/brettshollenberger/programming/historiographer/Guardfile +4 -0
  6. data/Users/brettshollenberger/programming/historiographer/LICENSE.txt +20 -0
  7. data/Users/brettshollenberger/programming/historiographer/README.md +298 -0
  8. data/Users/brettshollenberger/programming/historiographer/historiographer-4.1.0.gem +0 -0
  9. data/{historiographer.gemspec → Users/brettshollenberger/programming/historiographer/historiographer.gemspec} +2 -43
  10. data/Users/brettshollenberger/programming/historiographer/lib/historiographer/configuration.rb +36 -0
  11. data/{lib → Users/brettshollenberger/programming/historiographer/lib}/historiographer/history.rb +9 -2
  12. data/{lib → Users/brettshollenberger/programming/historiographer/lib}/historiographer/history_migration.rb +9 -6
  13. data/{lib → Users/brettshollenberger/programming/historiographer/lib}/historiographer/relation.rb +1 -1
  14. data/Users/brettshollenberger/programming/historiographer/lib/historiographer/version.rb +3 -0
  15. data/{lib → Users/brettshollenberger/programming/historiographer/lib}/historiographer.rb +176 -11
  16. data/{spec → Users/brettshollenberger/programming/historiographer/spec}/db/database.yml +5 -3
  17. data/Users/brettshollenberger/programming/historiographer/spec/db/migrate/20241109182017_create_comments.rb +13 -0
  18. data/Users/brettshollenberger/programming/historiographer/spec/db/migrate/20241109182020_create_comment_histories.rb +9 -0
  19. data/{spec → Users/brettshollenberger/programming/historiographer/spec}/db/schema.rb +80 -41
  20. data/Users/brettshollenberger/programming/historiographer/spec/examples.txt +40 -0
  21. data/{spec → Users/brettshollenberger/programming/historiographer/spec}/historiographer_spec.rb +265 -40
  22. data/{spec → Users/brettshollenberger/programming/historiographer/spec}/spec_helper.rb +8 -4
  23. metadata +41 -39
  24. data/.document +0 -5
  25. data/.rspec +0 -1
  26. data/.ruby-version +0 -1
  27. data/.standalone_migrations +0 -6
  28. data/Gemfile.lock +0 -289
  29. data/Guardfile +0 -70
  30. data/VERSION +0 -1
  31. data/spec/examples.txt +0 -32
  32. /data/{Rakefile → Users/brettshollenberger/programming/historiographer/Rakefile} +0 -0
  33. /data/{init.rb → Users/brettshollenberger/programming/historiographer/init.rb} +0 -0
  34. /data/{lib → Users/brettshollenberger/programming/historiographer/lib}/historiographer/history_migration_mysql.rb +0 -0
  35. /data/{lib → Users/brettshollenberger/programming/historiographer/lib}/historiographer/mysql_migration.rb +0 -0
  36. /data/{lib → Users/brettshollenberger/programming/historiographer/lib}/historiographer/postgres_migration.rb +0 -0
  37. /data/{lib → Users/brettshollenberger/programming/historiographer/lib}/historiographer/safe.rb +0 -0
  38. /data/{lib → Users/brettshollenberger/programming/historiographer/lib}/historiographer/silent.rb +0 -0
  39. /data/{spec → Users/brettshollenberger/programming/historiographer/spec}/db/migrate/20161121212228_create_posts.rb +0 -0
  40. /data/{spec → Users/brettshollenberger/programming/historiographer/spec}/db/migrate/20161121212229_create_post_histories.rb +0 -0
  41. /data/{spec → Users/brettshollenberger/programming/historiographer/spec}/db/migrate/20161121212230_create_authors.rb +0 -0
  42. /data/{spec → Users/brettshollenberger/programming/historiographer/spec}/db/migrate/20161121212231_create_author_histories.rb +0 -0
  43. /data/{spec → Users/brettshollenberger/programming/historiographer/spec}/db/migrate/20161121212232_create_users.rb +0 -0
  44. /data/{spec → Users/brettshollenberger/programming/historiographer/spec}/db/migrate/20171011194624_create_safe_posts.rb +0 -0
  45. /data/{spec → Users/brettshollenberger/programming/historiographer/spec}/db/migrate/20171011194715_create_safe_post_histories.rb +0 -0
  46. /data/{spec → Users/brettshollenberger/programming/historiographer/spec}/db/migrate/20191024142304_create_thing_with_compound_index.rb +0 -0
  47. /data/{spec → Users/brettshollenberger/programming/historiographer/spec}/db/migrate/20191024142352_create_thing_with_compound_index_history.rb +0 -0
  48. /data/{spec → Users/brettshollenberger/programming/historiographer/spec}/db/migrate/20191024203106_create_thing_without_history.rb +0 -0
  49. /data/{spec → Users/brettshollenberger/programming/historiographer/spec}/db/migrate/20221018204220_create_silent_posts.rb +0 -0
  50. /data/{spec → Users/brettshollenberger/programming/historiographer/spec}/db/migrate/20221018204255_create_silent_post_histories.rb +0 -0
  51. /data/{spec → Users/brettshollenberger/programming/historiographer/spec}/factories/post.rb +0 -0
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'active_support/all'
4
+ require 'securerandom'
4
5
  require_relative './historiographer/history'
5
6
  require_relative './historiographer/postgres_migration'
6
7
  require_relative './historiographer/safe'
@@ -83,12 +84,21 @@ module Historiographer
83
84
  after_save :record_history, if: :should_record_history?
84
85
  validate :validate_history_user_id_present, if: :should_validate_history_user_id_present?
85
86
 
87
+ # Add scope to fetch latest histories
88
+ scope :latest_snapshot, -> {
89
+ history_class.latest_snapshot
90
+ }
91
+
92
+ def should_alert_history_user_id_present?
93
+ !snapshot_mode? && !is_history_class? && Thread.current[:skip_history_user_id_validation] != true
94
+ end
95
+
86
96
  def should_validate_history_user_id_present?
87
- true
97
+ !snapshot_mode? && !is_history_class? && Thread.current[:skip_history_user_id_validation] != true
88
98
  end
89
99
 
90
100
  def validate_history_user_id_present
91
- if @no_history.nil? && (!history_user_id.present? || !history_user_id.is_a?(Integer))
101
+ if should_validate_history_user_id_present? && (@no_history.nil? && (!history_user_id.present? || !history_user_id.is_a?(Integer)))
92
102
  errors.add(:history_user_id, 'must be an integer')
93
103
  end
94
104
  end
@@ -139,9 +149,9 @@ module Historiographer
139
149
  def historiographer_changes?
140
150
  case Rails.version.to_f
141
151
  when 0..5 then changed? && valid?
142
- when 5.1..7 then saved_changes?
143
- else
144
152
  raise 'Unsupported Rails version'
153
+ when 5.1..8 then saved_changes?
154
+ else
145
155
  end
146
156
  end
147
157
 
@@ -151,17 +161,36 @@ module Historiographer
151
161
  # then record history after successful save.
152
162
  #
153
163
  def should_record_history?
164
+ return false if snapshot_mode?
165
+ return false if is_history_class?
166
+
154
167
  historiographer_changes? && !@no_history
155
168
  end
156
169
 
157
- attr_accessor :history_user_id
170
+ def history_user_id=(value)
171
+ if is_history_class?
172
+ write_attribute(:history_user_id, value)
173
+ else
174
+ @history_user_id = value
175
+ end
176
+ end
177
+
178
+ def history_user_id
179
+ if is_history_class?
180
+ read_attribute(:history_user_id)
181
+ else
182
+ @history_user_id
183
+ end
184
+ end
158
185
 
159
186
  class_name = "#{base.name}History"
160
187
 
161
188
  begin
162
189
  class_name.constantize
163
190
  rescue StandardError
164
- history_class_initializer = Class.new(ActiveRecord::Base) do
191
+ history_class_initializer = Class.new(base) do
192
+ self.table_name = "#{base.table_name}_histories"
193
+ self.inheritance_column = nil
165
194
  end
166
195
 
167
196
  Object.const_set(class_name, history_class_initializer)
@@ -169,6 +198,70 @@ module Historiographer
169
198
 
170
199
  klass = class_name.constantize
171
200
 
201
+ # Hook into the association building process
202
+ base.singleton_class.prepend(Module.new do
203
+ def belongs_to(name, scope = nil, **options, &extension)
204
+ super
205
+ define_history_association(name, :belongs_to, options)
206
+ end
207
+
208
+ def has_one(name, scope = nil, **options, &extension)
209
+ super
210
+ define_history_association(name, :has_one, options)
211
+ end
212
+
213
+ def has_many(name, scope = nil, **options, &extension)
214
+ super
215
+ define_history_association(name, :has_many, options)
216
+ end
217
+
218
+ def has_and_belongs_to_many(name, scope = nil, **options, &extension)
219
+ super
220
+ define_history_association(name, :has_and_belongs_to_many, options)
221
+ end
222
+
223
+ private
224
+
225
+ def define_history_association(name, type, options)
226
+ return if is_history_class?
227
+ return if @defining_association
228
+ return if %i[histories current_history].include?(name)
229
+ @defining_association = true
230
+
231
+ history_class = "#{self.name}History".constantize
232
+ history_class_name = "#{name.to_s.singularize.camelize}History"
233
+
234
+ # Get the original association's foreign key
235
+ original_reflection = self.reflect_on_association(name)
236
+ foreign_key = original_reflection.foreign_key
237
+
238
+ if type == :has_many || type == :has_and_belongs_to_many
239
+ history_class.send(
240
+ type,
241
+ name,
242
+ -> (owner) { where("#{name.to_s.singularize}_histories.snapshot_id = ?", owner.snapshot_id) },
243
+ **options.merge(
244
+ class_name: history_class_name,
245
+ foreign_key: foreign_key,
246
+ primary_key: foreign_key
247
+ )
248
+ )
249
+ else
250
+ history_class.send(
251
+ type,
252
+ name,
253
+ -> (owner) { where("#{name}_histories.snapshot_id = ?", owner.snapshot_id) },
254
+ **options.merge(
255
+ class_name: history_class_name,
256
+ foreign_key: foreign_key,
257
+ primary_key: foreign_key
258
+ )
259
+ )
260
+ end
261
+ @defining_association = false
262
+ end
263
+ end)
264
+
172
265
  if base.respond_to?(:histories)
173
266
  raise "#{base} already has histories. Talk to Brett if this is a legit use case."
174
267
  else
@@ -219,6 +312,46 @@ module Historiographer
219
312
  @no_history = false
220
313
  end
221
314
 
315
+
316
+ def snapshot(tree = {}, snapshot_id = nil)
317
+ return if is_history_class?
318
+
319
+ without_history_user_id do
320
+ # Use SecureRandom.uuid instead of timestamp for snapshot_id
321
+ snapshot_id ||= SecureRandom.uuid
322
+ history_class = self.class.history_class
323
+ primary_key = self.class.primary_key
324
+ foreign_key = history_class.history_foreign_key
325
+ attrs = attributes.clone
326
+ existing_snapshot = history_class.where(foreign_key => attrs[primary_key], snapshot_id: snapshot_id)
327
+ return if existing_snapshot.present?
328
+
329
+ null_snapshot = history_class.where(foreign_key => attrs[primary_key], snapshot_id: nil)
330
+ if null_snapshot.present?
331
+ null_snapshot.update(snapshot_id: snapshot_id)
332
+ else
333
+ record_history(snapshot_id: snapshot_id)
334
+ end
335
+
336
+ # Recursively snapshot associations, avoiding infinite loops
337
+ self.class.reflect_on_all_associations.each do |association|
338
+ associated_records = send(association.name).reload
339
+ Array(associated_records).each do |record|
340
+ model_name = record.class.name
341
+ record_id = record.id
342
+
343
+ tree[model_name] ||= {}
344
+ next if tree[model_name][record_id]
345
+
346
+ new_tree = tree.deep_dup
347
+ new_tree[model_name][record_id] = true
348
+
349
+ record.snapshot(new_tree, snapshot_id) if record.respond_to?(:snapshot)
350
+ end
351
+ end
352
+ end
353
+ end
354
+
222
355
  private
223
356
 
224
357
  def history_user_absent_action
@@ -231,8 +364,8 @@ module Historiographer
231
364
  #
232
365
  # Find the most recent history, and update its history_ended_at timestamp
233
366
  #
234
- def record_history
235
- history_user_absent_action if history_user_id.nil?
367
+ def record_history(snapshot_id: nil)
368
+ history_user_absent_action if history_user_id.nil? && should_alert_history_user_id_present?
236
369
 
237
370
  attrs = attributes.clone
238
371
  history_class = self.class.history_class
@@ -240,30 +373,62 @@ module Historiographer
240
373
 
241
374
  now = UTC.now
242
375
  attrs.merge!(foreign_key => attrs['id'], history_started_at: now, history_user_id: history_user_id)
376
+ attrs.merge!(snapshot_id: snapshot_id) if snapshot_id.present?
243
377
 
244
378
  attrs = attrs.except('id')
245
379
 
246
380
  current_history = histories.where(history_ended_at: nil).order('id desc').limit(1).last
247
381
 
248
382
  if foreign_key.present? && history_class.present?
249
- history_class.create!(attrs)
250
- current_history.update!(history_ended_at: now) if current_history.present?
383
+ history_class.create!(attrs).tap do |history|
384
+ current_history.update!(history_ended_at: now) if current_history.present?
385
+ end
251
386
  else
252
387
  raise 'Need foreign key and history class to save history!'
253
388
  end
254
389
  end
390
+
391
+ def without_history_user_id
392
+ Thread.current[:skip_history_user_id_validation] = true
393
+ yield
394
+ ensure
395
+ Thread.current[:skip_history_user_id_validation] = false
396
+ end
255
397
  end
256
398
 
257
399
  class_methods do
400
+ def is_history_class?
401
+ name.match?(/History$/)
402
+ end
258
403
  #
259
404
  # E.g. SponsoredProductCampaign => SponsoredProductCampaignHistory
260
405
  #
261
406
  def history_class
262
- "#{name}History".constantize
407
+ if is_history_class?
408
+ nil
409
+ else
410
+ "#{name}History".constantize
411
+ end
263
412
  end
264
413
 
265
414
  def relation
266
415
  super.tap { |r| r.extend Historiographer::Relation }
267
416
  end
417
+
418
+ def historiographer_mode(mode)
419
+ @historiographer_mode = mode
420
+ end
421
+
422
+ def get_historiographer_mode
423
+ @historiographer_mode || Historiographer::Configuration.mode
424
+ end
425
+ end
426
+
427
+ def is_history_class?
428
+ self.class.is_history_class?
429
+ end
430
+
431
+ def snapshot_mode?
432
+ (self.class.get_historiographer_mode.to_sym == :snapshot_only)
268
433
  end
269
434
  end
@@ -1,12 +1,14 @@
1
1
  development:
2
2
  adapter: postgresql
3
- prepared_statements: false
4
- url: "postgres://localhost/historiographer_development"
3
+ encoding: unicode
4
+ database: historiographer_development
5
+ pool: 5
5
6
 
6
7
  test:
7
8
  adapter: postgresql
9
+ encoding: unicode
8
10
  database: historiographer_test
9
- url: "postgres://localhost/historiographer_test"
11
+ pool: 5
10
12
 
11
13
  # mysql_default: &mysql_default
12
14
  # adapter: mysql2
@@ -0,0 +1,13 @@
1
+ class CreateComments < ActiveRecord::Migration[7.1]
2
+ def change
3
+ create_table :comments do |t|
4
+ t.bigint :post_id
5
+ t.bigint :author_id
6
+ t.text :body
7
+ t.timestamps
8
+
9
+ t.index :post_id
10
+ t.index :author_id
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,9 @@
1
+ require 'historiographer/postgres_migration'
2
+
3
+ class CreateCommentHistories < ActiveRecord::Migration[7.1]
4
+ def change
5
+ create_table :comment_histories do |t|
6
+ t.histories
7
+ end
8
+ end
9
+ end
@@ -10,8 +10,7 @@
10
10
  #
11
11
  # It's strongly recommended that you check this file into your version control system.
12
12
 
13
- ActiveRecord::Schema.define(version: 2022_10_18_204255) do
14
-
13
+ ActiveRecord::Schema[7.1].define(version: 2024_11_09_182020) do
15
14
  # These are extensions that must be enabled in order to support this database
16
15
  enable_extension "plpgsql"
17
16
 
@@ -19,26 +18,58 @@ ActiveRecord::Schema.define(version: 2022_10_18_204255) do
19
18
  t.integer "author_id", null: false
20
19
  t.string "full_name", null: false
21
20
  t.text "bio"
22
- t.datetime "deleted_at"
23
- t.datetime "created_at", null: false
24
- t.datetime "updated_at", null: false
25
- t.datetime "history_started_at", null: false
26
- t.datetime "history_ended_at"
21
+ t.datetime "deleted_at", precision: nil
22
+ t.datetime "created_at", precision: nil, null: false
23
+ t.datetime "updated_at", precision: nil, null: false
24
+ t.datetime "history_started_at", precision: nil, null: false
25
+ t.datetime "history_ended_at", precision: nil
27
26
  t.integer "history_user_id"
27
+ t.string "snapshot_id"
28
28
  t.index ["author_id"], name: "index_author_histories_on_author_id"
29
29
  t.index ["deleted_at"], name: "index_author_histories_on_deleted_at"
30
30
  t.index ["history_ended_at"], name: "index_author_histories_on_history_ended_at"
31
31
  t.index ["history_started_at"], name: "index_author_histories_on_history_started_at"
32
32
  t.index ["history_user_id"], name: "index_author_histories_on_history_user_id"
33
+ t.index ["snapshot_id"], name: "index_author_histories_on_snapshot_id"
33
34
  end
34
35
 
35
36
  create_table "authors", force: :cascade do |t|
36
37
  t.string "full_name", null: false
37
38
  t.text "bio"
38
- t.datetime "deleted_at"
39
+ t.datetime "deleted_at", precision: nil
40
+ t.datetime "created_at", precision: nil, null: false
41
+ t.datetime "updated_at", precision: nil, null: false
42
+ t.index ["deleted_at"], name: "index_authors_on_deleted_at"
43
+ end
44
+
45
+ create_table "comment_histories", force: :cascade do |t|
46
+ t.integer "comment_id", null: false
47
+ t.integer "post_id"
48
+ t.integer "author_id"
49
+ t.text "body"
39
50
  t.datetime "created_at", null: false
40
51
  t.datetime "updated_at", null: false
41
- t.index ["deleted_at"], name: "index_authors_on_deleted_at"
52
+ t.datetime "history_started_at", null: false
53
+ t.datetime "history_ended_at"
54
+ t.integer "history_user_id"
55
+ t.string "snapshot_id"
56
+ t.index ["author_id"], name: "index_comment_histories_on_author_id"
57
+ t.index ["comment_id"], name: "index_comment_histories_on_comment_id"
58
+ t.index ["history_ended_at"], name: "index_comment_histories_on_history_ended_at"
59
+ t.index ["history_started_at"], name: "index_comment_histories_on_history_started_at"
60
+ t.index ["history_user_id"], name: "index_comment_histories_on_history_user_id"
61
+ t.index ["post_id"], name: "index_comment_histories_on_post_id"
62
+ t.index ["snapshot_id"], name: "index_comment_histories_on_snapshot_id"
63
+ end
64
+
65
+ create_table "comments", force: :cascade do |t|
66
+ t.bigint "post_id"
67
+ t.bigint "author_id"
68
+ t.text "body"
69
+ t.datetime "created_at", null: false
70
+ t.datetime "updated_at", null: false
71
+ t.index ["author_id"], name: "index_comments_on_author_id"
72
+ t.index ["post_id"], name: "index_comments_on_post_id"
42
73
  end
43
74
 
44
75
  create_table "post_histories", force: :cascade do |t|
@@ -47,13 +78,14 @@ ActiveRecord::Schema.define(version: 2022_10_18_204255) do
47
78
  t.text "body", null: false
48
79
  t.integer "author_id", null: false
49
80
  t.boolean "enabled", default: false
50
- t.datetime "live_at"
51
- t.datetime "deleted_at"
52
- t.datetime "created_at", null: false
53
- t.datetime "updated_at", null: false
54
- t.datetime "history_started_at", null: false
55
- t.datetime "history_ended_at"
81
+ t.datetime "live_at", precision: nil
82
+ t.datetime "deleted_at", precision: nil
83
+ t.datetime "created_at", precision: nil, null: false
84
+ t.datetime "updated_at", precision: nil, null: false
85
+ t.datetime "history_started_at", precision: nil, null: false
86
+ t.datetime "history_ended_at", precision: nil
56
87
  t.integer "history_user_id"
88
+ t.string "snapshot_id"
57
89
  t.index ["author_id"], name: "index_post_histories_on_author_id"
58
90
  t.index ["deleted_at"], name: "index_post_histories_on_deleted_at"
59
91
  t.index ["enabled"], name: "index_post_histories_on_enabled"
@@ -62,6 +94,7 @@ ActiveRecord::Schema.define(version: 2022_10_18_204255) do
62
94
  t.index ["history_user_id"], name: "index_post_histories_on_history_user_id"
63
95
  t.index ["live_at"], name: "index_post_histories_on_live_at"
64
96
  t.index ["post_id"], name: "index_post_histories_on_post_id"
97
+ t.index ["snapshot_id"], name: "index_post_histories_on_snapshot_id"
65
98
  end
66
99
 
67
100
  create_table "posts", force: :cascade do |t|
@@ -69,10 +102,10 @@ ActiveRecord::Schema.define(version: 2022_10_18_204255) do
69
102
  t.text "body", null: false
70
103
  t.integer "author_id", null: false
71
104
  t.boolean "enabled", default: false
72
- t.datetime "live_at"
73
- t.datetime "deleted_at"
74
- t.datetime "created_at", null: false
75
- t.datetime "updated_at", null: false
105
+ t.datetime "live_at", precision: nil
106
+ t.datetime "deleted_at", precision: nil
107
+ t.datetime "created_at", precision: nil, null: false
108
+ t.datetime "updated_at", precision: nil, null: false
76
109
  t.index ["author_id"], name: "index_posts_on_author_id"
77
110
  t.index ["deleted_at"], name: "index_posts_on_deleted_at"
78
111
  t.index ["enabled"], name: "index_posts_on_enabled"
@@ -85,13 +118,14 @@ ActiveRecord::Schema.define(version: 2022_10_18_204255) do
85
118
  t.text "body", null: false
86
119
  t.integer "author_id", null: false
87
120
  t.boolean "enabled", default: false
88
- t.datetime "live_at"
89
- t.datetime "deleted_at"
90
- t.datetime "created_at", null: false
91
- t.datetime "updated_at", null: false
92
- t.datetime "history_started_at", null: false
93
- t.datetime "history_ended_at"
121
+ t.datetime "live_at", precision: nil
122
+ t.datetime "deleted_at", precision: nil
123
+ t.datetime "created_at", precision: nil, null: false
124
+ t.datetime "updated_at", precision: nil, null: false
125
+ t.datetime "history_started_at", precision: nil, null: false
126
+ t.datetime "history_ended_at", precision: nil
94
127
  t.integer "history_user_id"
128
+ t.string "snapshot_id"
95
129
  t.index ["author_id"], name: "index_safe_post_histories_on_author_id"
96
130
  t.index ["deleted_at"], name: "index_safe_post_histories_on_deleted_at"
97
131
  t.index ["enabled"], name: "index_safe_post_histories_on_enabled"
@@ -100,6 +134,7 @@ ActiveRecord::Schema.define(version: 2022_10_18_204255) do
100
134
  t.index ["history_user_id"], name: "index_safe_post_histories_on_history_user_id"
101
135
  t.index ["live_at"], name: "index_safe_post_histories_on_live_at"
102
136
  t.index ["safe_post_id"], name: "index_safe_post_histories_on_safe_post_id"
137
+ t.index ["snapshot_id"], name: "index_safe_post_histories_on_snapshot_id"
103
138
  end
104
139
 
105
140
  create_table "safe_posts", force: :cascade do |t|
@@ -107,10 +142,10 @@ ActiveRecord::Schema.define(version: 2022_10_18_204255) do
107
142
  t.text "body", null: false
108
143
  t.integer "author_id", null: false
109
144
  t.boolean "enabled", default: false
110
- t.datetime "live_at"
111
- t.datetime "deleted_at"
112
- t.datetime "created_at", null: false
113
- t.datetime "updated_at", null: false
145
+ t.datetime "live_at", precision: nil
146
+ t.datetime "deleted_at", precision: nil
147
+ t.datetime "created_at", precision: nil, null: false
148
+ t.datetime "updated_at", precision: nil, null: false
114
149
  t.index ["author_id"], name: "index_safe_posts_on_author_id"
115
150
  t.index ["deleted_at"], name: "index_safe_posts_on_deleted_at"
116
151
  t.index ["enabled"], name: "index_safe_posts_on_enabled"
@@ -123,13 +158,14 @@ ActiveRecord::Schema.define(version: 2022_10_18_204255) do
123
158
  t.text "body", null: false
124
159
  t.integer "author_id", null: false
125
160
  t.boolean "enabled", default: false
126
- t.datetime "live_at"
127
- t.datetime "deleted_at"
128
- t.datetime "created_at", null: false
129
- t.datetime "updated_at", null: false
130
- t.datetime "history_started_at", null: false
131
- t.datetime "history_ended_at"
161
+ t.datetime "live_at", precision: nil
162
+ t.datetime "deleted_at", precision: nil
163
+ t.datetime "created_at", precision: nil, null: false
164
+ t.datetime "updated_at", precision: nil, null: false
165
+ t.datetime "history_started_at", precision: nil, null: false
166
+ t.datetime "history_ended_at", precision: nil
132
167
  t.integer "history_user_id"
168
+ t.string "snapshot_id"
133
169
  t.index ["author_id"], name: "index_silent_post_histories_on_author_id"
134
170
  t.index ["deleted_at"], name: "index_silent_post_histories_on_deleted_at"
135
171
  t.index ["enabled"], name: "index_silent_post_histories_on_enabled"
@@ -138,6 +174,7 @@ ActiveRecord::Schema.define(version: 2022_10_18_204255) do
138
174
  t.index ["history_user_id"], name: "index_silent_post_histories_on_history_user_id"
139
175
  t.index ["live_at"], name: "index_silent_post_histories_on_live_at"
140
176
  t.index ["silent_post_id"], name: "index_silent_post_histories_on_silent_post_id"
177
+ t.index ["snapshot_id"], name: "index_silent_post_histories_on_snapshot_id"
141
178
  end
142
179
 
143
180
  create_table "silent_posts", force: :cascade do |t|
@@ -145,10 +182,10 @@ ActiveRecord::Schema.define(version: 2022_10_18_204255) do
145
182
  t.text "body", null: false
146
183
  t.integer "author_id", null: false
147
184
  t.boolean "enabled", default: false
148
- t.datetime "live_at"
149
- t.datetime "deleted_at"
150
- t.datetime "created_at", null: false
151
- t.datetime "updated_at", null: false
185
+ t.datetime "live_at", precision: nil
186
+ t.datetime "deleted_at", precision: nil
187
+ t.datetime "created_at", precision: nil, null: false
188
+ t.datetime "updated_at", precision: nil, null: false
152
189
  t.index ["author_id"], name: "index_silent_posts_on_author_id"
153
190
  t.index ["deleted_at"], name: "index_silent_posts_on_deleted_at"
154
191
  t.index ["enabled"], name: "index_silent_posts_on_enabled"
@@ -159,13 +196,15 @@ ActiveRecord::Schema.define(version: 2022_10_18_204255) do
159
196
  t.integer "thing_with_compound_index_id", null: false
160
197
  t.string "key"
161
198
  t.string "value"
162
- t.datetime "history_started_at", null: false
163
- t.datetime "history_ended_at"
199
+ t.datetime "history_started_at", precision: nil, null: false
200
+ t.datetime "history_ended_at", precision: nil
164
201
  t.integer "history_user_id"
202
+ t.string "snapshot_id"
165
203
  t.index ["history_ended_at"], name: "index_thing_with_compound_index_histories_on_history_ended_at"
166
204
  t.index ["history_started_at"], name: "index_thing_with_compound_index_histories_on_history_started_at"
167
205
  t.index ["history_user_id"], name: "index_thing_with_compound_index_histories_on_history_user_id"
168
206
  t.index ["key", "value"], name: "idx_history_k_v"
207
+ t.index ["snapshot_id"], name: "index_thing_with_compound_index_histories_on_snapshot_id"
169
208
  t.index ["thing_with_compound_index_id"], name: "idx_k_v_histories"
170
209
  end
171
210
 
@@ -0,0 +1,40 @@
1
+ example_id | status | run_time |
2
+ ----------------------------------------- | ------ | --------------- |
3
+ ./spec/historiographer_spec.rb[1:1:1] | passed | 0.03206 seconds |
4
+ ./spec/historiographer_spec.rb[1:1:2] | passed | 0.03548 seconds |
5
+ ./spec/historiographer_spec.rb[1:1:3] | passed | 0.0394 seconds |
6
+ ./spec/historiographer_spec.rb[1:2:1] | passed | 0.04024 seconds |
7
+ ./spec/historiographer_spec.rb[1:2:2] | passed | 0.03537 seconds |
8
+ ./spec/historiographer_spec.rb[1:2:3:1:1] | passed | 0.05859 seconds |
9
+ ./spec/historiographer_spec.rb[1:2:3:1:2] | passed | 0.04457 seconds |
10
+ ./spec/historiographer_spec.rb[1:2:3:2:1] | passed | 0.04026 seconds |
11
+ ./spec/historiographer_spec.rb[1:2:3:2:2] | passed | 0.04242 seconds |
12
+ ./spec/historiographer_spec.rb[1:2:3:2:3] | passed | 0.03368 seconds |
13
+ ./spec/historiographer_spec.rb[1:2:3:3:1] | passed | 0.05167 seconds |
14
+ ./spec/historiographer_spec.rb[1:2:3:3:2] | passed | 0.04029 seconds |
15
+ ./spec/historiographer_spec.rb[1:2:4:1] | passed | 0.04736 seconds |
16
+ ./spec/historiographer_spec.rb[1:2:4:2] | passed | 0.03779 seconds |
17
+ ./spec/historiographer_spec.rb[1:2:4:3] | passed | 0.03484 seconds |
18
+ ./spec/historiographer_spec.rb[1:2:5:1] | passed | 0.04458 seconds |
19
+ ./spec/historiographer_spec.rb[1:2:5:2] | passed | 0.03644 seconds |
20
+ ./spec/historiographer_spec.rb[1:2:5:3] | passed | 0.03426 seconds |
21
+ ./spec/historiographer_spec.rb[1:2:6] | passed | 0.03251 seconds |
22
+ ./spec/historiographer_spec.rb[1:2:7] | passed | 0.04135 seconds |
23
+ ./spec/historiographer_spec.rb[1:2:8] | passed | 0.03819 seconds |
24
+ ./spec/historiographer_spec.rb[1:3:1] | passed | 0.03542 seconds |
25
+ ./spec/historiographer_spec.rb[1:4:1] | passed | 0.03833 seconds |
26
+ ./spec/historiographer_spec.rb[1:5:1] | passed | 0.03372 seconds |
27
+ ./spec/historiographer_spec.rb[1:5:2] | passed | 0.05387 seconds |
28
+ ./spec/historiographer_spec.rb[1:6:1] | passed | 0.0377 seconds |
29
+ ./spec/historiographer_spec.rb[1:6:2] | passed | 0.03973 seconds |
30
+ ./spec/historiographer_spec.rb[1:7:1] | passed | 0.03895 seconds |
31
+ ./spec/historiographer_spec.rb[1:8:1] | passed | 0.03733 seconds |
32
+ ./spec/historiographer_spec.rb[1:9:1] | passed | 0.0322 seconds |
33
+ ./spec/historiographer_spec.rb[1:10:1] | passed | 0.03434 seconds |
34
+ ./spec/historiographer_spec.rb[1:10:2] | passed | 0.0363 seconds |
35
+ ./spec/historiographer_spec.rb[1:10:3] | passed | 0.03492 seconds |
36
+ ./spec/historiographer_spec.rb[1:10:4] | passed | 0.03702 seconds |
37
+ ./spec/historiographer_spec.rb[1:11:1] | passed | 0.05087 seconds |
38
+ ./spec/historiographer_spec.rb[1:11:2] | passed | 0.06332 seconds |
39
+ ./spec/historiographer_spec.rb[1:11:3] | passed | 0.06558 seconds |
40
+ ./spec/historiographer_spec.rb[1:12:1] | passed | 0.15112 seconds |