historiographer 3.1.2 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +115 -39
  3. data/{Gemfile → Users/brettshollenberger/programming/historiographer/Gemfile} +1 -2
  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} +5 -46
  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 +13 -5
  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 +183 -13
  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 +43 -41
  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 -29
  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,13 +198,82 @@ 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
175
268
  opts = { class_name: class_name }
176
269
  opts[:foreign_key] = klass.history_foreign_key if klass.respond_to?(:history_foreign_key)
177
- has_many :histories, opts
178
- has_one :current_history, -> { current }, opts
270
+ if RUBY_VERSION.to_i >= 3
271
+ has_many :histories, **opts
272
+ has_one :current_history, -> { current }, **opts
273
+ else
274
+ has_many :histories, opts
275
+ has_one :current_history, -> { current }, opts
276
+ end
179
277
  end
180
278
 
181
279
  klass.send(:include, Historiographer::History) unless klass.ancestors.include?(Historiographer::History)
@@ -214,6 +312,46 @@ module Historiographer
214
312
  @no_history = false
215
313
  end
216
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
+
217
355
  private
218
356
 
219
357
  def history_user_absent_action
@@ -226,8 +364,8 @@ module Historiographer
226
364
  #
227
365
  # Find the most recent history, and update its history_ended_at timestamp
228
366
  #
229
- def record_history
230
- 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?
231
369
 
232
370
  attrs = attributes.clone
233
371
  history_class = self.class.history_class
@@ -235,30 +373,62 @@ module Historiographer
235
373
 
236
374
  now = UTC.now
237
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?
238
377
 
239
378
  attrs = attrs.except('id')
240
379
 
241
380
  current_history = histories.where(history_ended_at: nil).order('id desc').limit(1).last
242
381
 
243
382
  if foreign_key.present? && history_class.present?
244
- history_class.create!(attrs)
245
- 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
246
386
  else
247
387
  raise 'Need foreign key and history class to save history!'
248
388
  end
249
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
250
397
  end
251
398
 
252
399
  class_methods do
400
+ def is_history_class?
401
+ name.match?(/History$/)
402
+ end
253
403
  #
254
404
  # E.g. SponsoredProductCampaign => SponsoredProductCampaignHistory
255
405
  #
256
406
  def history_class
257
- "#{name}History".constantize
407
+ if is_history_class?
408
+ nil
409
+ else
410
+ "#{name}History".constantize
411
+ end
258
412
  end
259
413
 
260
414
  def relation
261
415
  super.tap { |r| r.extend Historiographer::Relation }
262
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)
263
433
  end
264
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 |