historiographer 4.0.0 → 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} +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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f16398b9f6b0a3d58501a2115eabca0e0f93a938d04eeb4c21d3713f9b70079a
4
- data.tar.gz: a460ef65372e236b001225b1028837eb7ba107e8d45d958c39d003be0cd64db4
3
+ metadata.gz: 23b67927669a8cddbbf3a4097aba1c238f086324ad6e277bb728525263e12381
4
+ data.tar.gz: bf24dcdae837fc9a443810e24d1f559a87d3c8d778acb1904c308dd11017d15f
5
5
  SHA512:
6
- metadata.gz: 3b545edcfe0076f0e83f5478347a9298fce77118d7274ad39ce8304844637b7ee15980e66c02dff36321eda4e36b0defdb10b6c33cc7486fba47e780043e5f42
7
- data.tar.gz: f828cf26cc357fb0b3e2750bfcc1f62dc628c1579f1fa3356062f34314545783bb6ecb80366e4ac9d6988eae8374168afeb0d29c166daa9dbd7c860074494de4
6
+ metadata.gz: 49c8d86b477f67c016d52aae1cb721a7d33bfecc04de761f50d7c3cc42c4481eb6b3863f2b3c89f226f2321a79c92411f70e6344f6e933bde7a2245504a876a1
7
+ data.tar.gz: 667b8032e144c0bc0a61cedbbffcf51dd5a90eac68ee8dfe95920e6500da6fc9f39c6b374f419907031822fa12d858b9bf79c77a8323a57192ca3c01da680b8b
data/README.md CHANGED
@@ -8,21 +8,11 @@ Historiographer fixes this problem in a better way than existing auditing gems.
8
8
 
9
9
  The Audited gem has some serious flaws.
10
10
 
11
- 🤚Hands up if your `versions` table has gotten too big to query 🤚
11
+ 1. The `versions` table quickly grows too large to query
12
12
 
13
- 🤚Hands up if your `versions` table doesn't have the indexes you need 🤚
13
+ 2. It doesn't provide the indexes you need from your primary tables
14
14
 
15
- 🤚Hands up if you've ever iterated over `versions` records in Ruby to recreate a snapshot of what data looked like at a point in time. 🤚
16
-
17
- Why does this happen?
18
-
19
- First, `audited` only tracks a record of what changed, so there's no way to "go back in time" and see what the data looked like back when a problem occurred without replaying every single audit.
20
-
21
- Second, it tracks changes as JSON. While some data stores have JSON querying semantics, not all do, making it very hard to ask complex questions of your historical data -- that's the whole reason you're keeping it around.
22
-
23
- Third, it doesn't maintain indexes on your data. If you maintain an index on the primary table, wouldn't you also want to look up historical records using the same columns? Historical data is MUCH larger than "latest snapshot" data, so, duh, of course you do.
24
-
25
- Finally, Audited creates just one table for all audits. Historical data is big. It's not unusual for an audited gem table to get into the many millions of rows, and need to be constantly partitioned to maintain any kind of efficiency.
15
+ 3. It doesn't provdie out-of-the-box snapshots
26
16
 
27
17
  ## How does Historiographer solve these problems?
28
18
 
@@ -30,44 +20,116 @@ Historiographer introduces the concept of _history tables:_ append-only tables t
30
20
 
31
21
  If you have a `posts` table:
32
22
 
33
- | id | title |
34
- | :----------- | :----------- |
35
- | 1 | My Great Post |
36
- | 2 | My Second Post |
23
+ | id | title |
24
+ | :-- | :------------- |
25
+ | 1 | My Great Post |
26
+ | 2 | My Second Post |
37
27
 
38
28
  You'll also have a `post_histories_table`:
39
29
 
40
- | id | post_id | title | history_started_at | history_ended_at | history_user_id |
41
- | :----------- | :----------- | :----------- | :----------- | :----------- | :----------- |
42
- | 1 | 1 | My Great Post | '2019-11-08' | NULL | 1 |
43
- | 2 | 2| My Second Post | '2019-11-08' | NULL | 1 |
30
+ | id | post_id | title | history_started_at | history_ended_at | history_user_id |
31
+ | :-- | :------ | :------------- | :----------------- | :--------------- | :-------------- |
32
+ | 1 | 1 | My Great Post | '2019-11-08' | NULL | 1 |
33
+ | 2 | 2 | My Second Post | '2019-11-08' | NULL | 1 |
44
34
 
45
35
  If you change the title of the 1st post:
46
36
 
47
- ```Post.find(1).update(title: "Title With Better SEO", history_user_id: current_user.id)```
37
+ `Post.find(1).update(title: "Title With Better SEO", history_user_id: current_user.id)`
48
38
 
49
39
  You'll expect your `posts` table to be updated directly:
50
40
 
51
- | id | title |
52
- | :----------- | :----------- |
53
- | 1 | Title With Better SEO |
54
- | 2 | My Second Post |
41
+ | id | title |
42
+ | :-- | :-------------------- |
43
+ | 1 | Title With Better SEO |
44
+ | 2 | My Second Post |
55
45
 
56
46
  But also, your `histories` table will be updated:
57
47
 
58
- | id | post_id | title | history_started_at | history_ended_at | history_user_id |
59
- | :----------- | :----------- | :----------- | :----------- | :----------- | :----------- |
60
- | 1 | 1 | My Great Post | '2019-11-08' | '2019-11-09' | 1 |
61
- | 2 | 2| My Second Post | '2019-11-08' | NULL | 1 |
62
- | 1 | 1 | Title With Better SEO | '2019-11-09' | NULL | 1 |
48
+ | id | post_id | title | history_started_at | history_ended_at | history_user_id |
49
+ | :-- | :------ | :-------------------- | :----------------- | :--------------- | :-------------- |
50
+ | 1 | 1 | My Great Post | '2019-11-08' | '2019-11-09' | 1 |
51
+ | 2 | 2 | My Second Post | '2019-11-08' | NULL | 1 |
52
+ | 1 | 1 | Title With Better SEO | '2019-11-09' | NULL | 1 |
63
53
 
64
54
  A few things have happened here:
65
55
 
66
56
  1. The primary table (`posts`) is updated directly
67
57
  2. The existing history for `post_id=1` is timestamped when its `history_ended_at`, so that we can see when the post had the title "My Great Post"
68
- 3. A new history record is appended to the table containing a complete snapshot of the record, and a `NULL` `history_ended_at`. That's because this is the current history.
58
+ 3. A new history record is appended to the table containing a complete snapshot of the record, and a `NULL` `history_ended_at`. That's because this is the current history.
69
59
  4. A record of _who_ made the change is saved (`history_user_id`). You can join to your users table to see more data.
70
60
 
61
+ ## Snapshots
62
+
63
+ Snapshots are particularly useful for two key use cases:
64
+
65
+ ### 1. Time Travel & Auditing
66
+
67
+ When you need to see exactly what your data looked like at a specific point in time - not just individual records, but entire object graphs with all their associations. This is invaluable for:
68
+
69
+ - Debugging production issues ("What did the entire order look like when this happened?")
70
+ - Compliance requirements ("Show me the exact state of this patient's record on January 1st")
71
+ - Auditing complex workflows ("What was the state of this loan application when it was approved?")
72
+
73
+ ### 2. Machine Learning & Analytics
74
+
75
+ When you need immutable snapshots of data for:
76
+
77
+ - Training data versioning
78
+ - Feature engineering
79
+ - Model validation
80
+ - A/B test analysis
81
+ - Ensuring reproducibility of results
82
+
83
+ ### Taking Snapshots
84
+
85
+ You can take a snapshot of a record and all its associated records:
86
+
87
+ ```ruby
88
+ post = Post.find(1)
89
+ post.snapshot(history_user_id: current_user.id)
90
+ ```
91
+
92
+ This will:
93
+
94
+ 1. Create a history record for the post
95
+ 2. Create history records for all associated records (comments, author, etc.)
96
+ 3. Link these history records together with a shared `snapshot_id`
97
+
98
+ You can retrieve the latest snapshot using:
99
+
100
+ ```ruby
101
+ post = Post.find(1)
102
+ snapshot = post.latest_snapshot
103
+
104
+ # Access associated records from the snapshot
105
+ snapshot.comments # Returns CommentHistory records
106
+ snapshot.author # Returns AuthorHistory record
107
+ ```
108
+
109
+ Snapshots are immutable - you cannot modify history records that are part of a snapshot. This guarantees that your historical data remains unchanged, which is crucial for both auditing and machine learning applications.
110
+
111
+ ### Snapshot-Only Mode
112
+
113
+ If you want to only track snapshots and not record every individual change, you can configure Historiographer to operate in snapshot-only mode:
114
+
115
+ ```ruby
116
+ Historiographer::Configuration.mode = :snapshot_only
117
+ ```
118
+
119
+ In this mode:
120
+
121
+ - Regular updates/changes will not create history records
122
+ - Only explicit calls to `snapshot` will create history records
123
+ - Each snapshot still captures the complete state of the record and its associations
124
+
125
+ This can be useful when:
126
+
127
+ - You only care about specific points in time rather than every change
128
+ - You want to reduce the number of history records created
129
+ - You need to capture the state of complex object graphs at specific moments
130
+ - You're versioning training data for machine learning models
131
+ - You need to maintain immutable audit trails at specific checkpoints
132
+
71
133
  # Getting Started
72
134
 
73
135
  Whenever you include the `Historiographer` gem in your ActiveRecord model, it allows you to insert, update, or delete data as you normally would.
@@ -78,18 +140,33 @@ class Post < ActiveRecord::Base
78
140
  end
79
141
  ```
80
142
 
81
- By default, Historiographer will require all SQL-backed methods to provide a `history_user_id` to track who made the changes.
143
+ ### History Modes
144
+
145
+ Historiographer supports two modes of operation:
146
+
147
+ 1. **:histories mode** (default) - Records history for every change to a record
148
+ 2. **:snapshot_only mode** - Only records history when explicitly taking snapshots
149
+
150
+ You can configure the mode globally:
82
151
 
83
152
  ```ruby
84
- Post.create(title: "My Post", history_user_id: current_user.id) # => OK
85
- Post.create(title: "My Post") # => Error!
153
+ # In an initializer
154
+ Historiographer::Configuration.mode = :histories # Default mode
155
+ # or
156
+ Historiographer::Configuration.mode = :snapshot_only
86
157
  ```
87
158
 
88
- Many existing models will be better off using `Historiographer::Safe` when getting started, which will not raise an error, but will alert you of locations where your app is missing `history_user_id`.
159
+ Or per model using `historiographer_mode`:
89
160
 
90
161
  ```ruby
91
162
  class Post < ActiveRecord::Base
92
- include Historiographer::Safe
163
+ include Historiographer
164
+ historiographer_mode :snapshot_only # Only record history when .snapshot is called
165
+ end
166
+
167
+ class Comment < ActiveRecord::Base
168
+ include Historiographer
169
+ historiographer_mode :histories # Record history for every change (default)
93
170
  end
94
171
  ```
95
172
 
@@ -210,12 +287,11 @@ end
210
287
  == Mysql Install
211
288
 
212
289
  For contributors on OSX, you may have difficulty installing mysql:
213
-
290
+
214
291
  ```
215
292
  gem install mysql2 -v '0.4.10' --source 'https://rubygems.org/' -- --with-ldflags=-L/usr/local/opt/openssl/lib --with-cppflags=-I/usr/local/opt/openssl/include
216
293
  ```
217
294
 
218
-
219
295
  == Copyright
220
296
 
221
297
  Copyright (c) 2016-2020 brettshollenberger. See LICENSE.txt for
@@ -19,7 +19,6 @@ group :development, :test do
19
19
  end
20
20
 
21
21
  group :development do
22
- gem 'bundler', '~> 1.0'
23
22
  gem 'jeweler', git: 'https://github.com/technicalpickles/jeweler', branch: 'master'
24
23
  gem 'rdoc', '~> 3.12'
25
24
  gem 'simplecov', '>= 0'
@@ -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
@@ -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
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2016 Brett Shollenberger
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.