hoardable 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -0
- data/README.md +69 -9
- data/lib/generators/hoardable/migration_generator.rb +2 -1
- data/lib/hoardable/error.rb +1 -1
- data/lib/hoardable/hoardable.rb +14 -3
- data/lib/hoardable/model.rb +27 -2
- data/lib/hoardable/source_model.rb +34 -5
- data/lib/hoardable/tableoid.rb +21 -1
- data/lib/hoardable/version.rb +1 -1
- data/lib/hoardable/version_model.rb +29 -1
- data/sig/hoardable.rbs +83 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c960d95a373942d9183464cc50b7c4213c25c7563fa9d920c81d2c325ea71705
|
4
|
+
data.tar.gz: e7e0f289e60acd720538edc15584209ed3d30e08b21758d06884a5486f198ee0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a83966223151922d24bb009ac50465723388ba91825e27cf933bb5e00370c270a0518ec828358f1109a040e2a9202cee7b37d7ea98e0387b30dc07a74f7eb851
|
7
|
+
data.tar.gz: 6bc246f6664b61c5000ffa71b24c8ddd30c409eda87e790b0ea1bd9d47f46c4e85e0b5eb89736939a75018e272cdd5ac2ce1217c7c7e9272ddc4f96cc8cc33f4
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -3,8 +3,6 @@
|
|
3
3
|
Hoardable is an ActiveRecord extension for Ruby 2.6+, Rails 6.1+, and PostgreSQL that allows for
|
4
4
|
versioning and soft-deletion of records through the use of _uni-temporal inherited tables_.
|
5
5
|
|
6
|
-
#### huh?
|
7
|
-
|
8
6
|
[Temporal tables](https://en.wikipedia.org/wiki/Temporal_database) are a database design pattern
|
9
7
|
where each row of a table contains data along with one or more time ranges. In the case of this gem,
|
10
8
|
each database row has a time range that represents the row’s valid time range - hence
|
@@ -18,8 +16,10 @@ change is reflected on its descendants.
|
|
18
16
|
With these concepts combined, `hoardable` offers a simple and effective model versioning system for
|
19
17
|
Rails. Versions of records are stored in separate, inherited tables along with their valid time
|
20
18
|
ranges and contextual data. Compared to other Rails-oriented versioning systems, this gem strives to
|
21
|
-
be more explicit and obvious on the lower RDBS level while still familiar and convenient
|
22
|
-
on Rails.
|
19
|
+
be more explicit and obvious on the lower RDBS level while still familiar and convenient to use
|
20
|
+
within Ruby on Rails.
|
21
|
+
|
22
|
+
[👉 Documentation](https://www.rubydoc.info/gems/hoardable)
|
23
23
|
|
24
24
|
## Installation
|
25
25
|
|
@@ -117,6 +117,10 @@ post.at(1.day.ago) # => #<PostVersion:0x000000010d44fa30>
|
|
117
117
|
PostVersion.at(1.day.ago).find_by(post_id: post.id) # => #<PostVersion:0x000000010d44fa30>
|
118
118
|
```
|
119
119
|
|
120
|
+
_Note:_ A `Version` is not created upon initial parent model creation. If you would like to
|
121
|
+
accurately capture the valid temporal frame of the first version, make sure your model’s table has a
|
122
|
+
`created_at` timestamp field.
|
123
|
+
|
120
124
|
By default, `hoardable` will keep copies of records you have destroyed. You can query for them as
|
121
125
|
well:
|
122
126
|
|
@@ -127,7 +131,7 @@ PostVersion.trashed
|
|
127
131
|
_Note:_ Creating an inherited table does not copy over the indexes from the parent table. If you
|
128
132
|
need to query versions often, you should add appropriate indexes to the `_versions` tables.
|
129
133
|
|
130
|
-
### Tracking
|
134
|
+
### Tracking Contextual Data
|
131
135
|
|
132
136
|
You’ll often want to track contextual data about the creation of a version. There are 3 optional
|
133
137
|
symbol keys that are provided for tracking contextual information:
|
@@ -220,19 +224,22 @@ end
|
|
220
224
|
|
221
225
|
### Configuration
|
222
226
|
|
223
|
-
There are
|
227
|
+
There are three configurable options currently:
|
224
228
|
|
225
229
|
```ruby
|
226
230
|
Hoardable.enabled # => default true
|
231
|
+
Hoardable.version_updates # => default true
|
227
232
|
Hoardable.save_trash # => default true
|
228
233
|
```
|
229
234
|
|
230
|
-
`Hoardable.enabled` controls whether versions will be
|
235
|
+
`Hoardable.enabled` controls whether versions will be ever be created.
|
236
|
+
|
237
|
+
`Hoardable.version_updates` controls whether versions get created on record updates.
|
231
238
|
|
232
239
|
`Hoardable.save_trash` controls whether to create versions upon record deletion. When this is set to
|
233
240
|
`false`, all versions of a record will be deleted when the record is destroyed.
|
234
241
|
|
235
|
-
If you would like to temporarily set a config setting, you can use `Hoardable.with
|
242
|
+
If you would like to temporarily set a config setting, you can use `Hoardable.with`:
|
236
243
|
|
237
244
|
```ruby
|
238
245
|
Hoardable.with(enabled: false) do
|
@@ -240,6 +247,18 @@ Hoardable.with(enabled: false) do
|
|
240
247
|
end
|
241
248
|
```
|
242
249
|
|
250
|
+
You can also configure these variables per `ActiveRecord` class as well using `hoardable_options`:
|
251
|
+
|
252
|
+
```ruby
|
253
|
+
class Comment < ActiveRecord::Base
|
254
|
+
include Hoardable::Model
|
255
|
+
hoardable_options version_updates: false
|
256
|
+
end
|
257
|
+
```
|
258
|
+
|
259
|
+
If either the model-level option or global option for a configuration variable is set to `false`,
|
260
|
+
that behavior will be disabled.
|
261
|
+
|
243
262
|
### Relationships
|
244
263
|
|
245
264
|
As in life, sometimes relationships can be hard. `hoardable` is still working out best practices and
|
@@ -269,15 +288,56 @@ class Post < ActiveRecord::Base
|
|
269
288
|
Comment
|
270
289
|
.version_class
|
271
290
|
.trashed
|
291
|
+
.where(post_id: id)
|
272
292
|
.with_hoardable_event_uuid(hoardable_event_uuid)
|
273
293
|
.find_each(&:untrash!)
|
274
294
|
end
|
275
295
|
end
|
276
296
|
```
|
277
297
|
|
298
|
+
## Gem Comparison
|
299
|
+
|
300
|
+
### [`paper_trail`](https://github.com/paper-trail-gem/paper_trail)
|
301
|
+
|
302
|
+
`paper_trail` is maybe the most popular and fully featured gem in this space. It works for other
|
303
|
+
database types than PostgeSQL and (by default) stores all versions of all versioned models in a
|
304
|
+
single `versions` table. It stores changes in a `text`, `json`, or `jsonb` column. In order to
|
305
|
+
efficiently query the `versions` table, a `jsonb` column should be used, which takes up a lot of
|
306
|
+
space to index. Unless you customize your configuration, all `versions` for all models types are
|
307
|
+
in the same table which is inefficient if you are only interested in querying versions of a single
|
308
|
+
model. By contrast, `hoardable` stores versions in smaller, isolated and inherited tables with the
|
309
|
+
same database columns as their parents, which are more efficient for querying as well as auditing
|
310
|
+
for truncating and dropping. The concept of a `temporal` time-frame does not exist for a single
|
311
|
+
version since there is only a `created_at` timestamp.
|
312
|
+
|
313
|
+
### [`audited`](https://github.com/collectiveidea/audited)
|
314
|
+
|
315
|
+
`audited` works in a similar manner as `paper_trail`. It stores all versions for all model types in
|
316
|
+
a single table, you must opt into using `jsonb` as the column type to store "changes", in case you
|
317
|
+
want to query them, and there is no concept of a `temporal` time-frame for a single version. It
|
318
|
+
makes opinionated decisions about contextual data requirements and stores them as top level data
|
319
|
+
types on the `audited` table.
|
320
|
+
|
321
|
+
### [`discard`](https://github.com/jhawthorn/discard)
|
322
|
+
|
323
|
+
`discard` only covers soft-deletion. The act of "soft deleting" a record is only captured through
|
324
|
+
the time-stamping of a `discarded_at` column on the records table; there is no other capturing of
|
325
|
+
the event that caused the soft deletion unless you implement it yourself. Once the "discarded"
|
326
|
+
record is restored, the previous "discarded" awareness is lost. Since "discarded" records exist in
|
327
|
+
the same table as "undiscarded" records, you must explicitly omit the discarded records from queries
|
328
|
+
across your app to keep them from leaking in.
|
329
|
+
|
330
|
+
### [`paranoia`](https://github.com/rubysherpas/paranoia)
|
331
|
+
|
332
|
+
`paranoia` also only covers soft-deletion. In their README, they recommend using `discard` instead
|
333
|
+
of `paranoia` because of the fact they override ActiveRecord’s `delete` and `destroy` methods.
|
334
|
+
`hoardable` employs callbacks to create trashed versions instead of overriding methods. Otherwise,
|
335
|
+
`paranoia` works similarly to `discard` in that it keeps deleted records in the same table and tags
|
336
|
+
them with a `deleted_at` timestamp. No other information about the soft-deletion event is stored.
|
337
|
+
|
278
338
|
## Contributing
|
279
339
|
|
280
|
-
This gem
|
340
|
+
This gem still quite new and very open to feedback.
|
281
341
|
|
282
342
|
Bug reports and pull requests are welcome on GitHub at https://github.com/waymondo/hoardable.
|
283
343
|
|
@@ -4,7 +4,8 @@ require 'rails/generators'
|
|
4
4
|
require 'rails/generators/active_record/migration/migration_generator'
|
5
5
|
|
6
6
|
module Hoardable
|
7
|
-
# Generates a migration
|
7
|
+
# Generates a migration to create an inherited uni-temporal table of a model including
|
8
|
+
# {Hoardable::Model}, for the storage of +versions+.
|
8
9
|
class MigrationGenerator < ActiveRecord::Generators::Base
|
9
10
|
source_root File.expand_path('templates', __dir__)
|
10
11
|
include Rails::Generators::Migration
|
data/lib/hoardable/error.rb
CHANGED
data/lib/hoardable/hoardable.rb
CHANGED
@@ -1,13 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# An ActiveRecord extension for keeping versions of records in temporal inherited tables
|
3
|
+
# An +ActiveRecord+ extension for keeping versions of records in uni-temporal inherited tables.
|
4
4
|
module Hoardable
|
5
|
+
# Symbols for use with setting contextual data, when creating versions. See
|
6
|
+
# {file:README.md#tracking-contextual-data README} for more.
|
5
7
|
DATA_KEYS = %i[meta whodunit note event_uuid].freeze
|
6
|
-
|
8
|
+
# Symbols for use with setting {Hoardable} configuration. See {file:README.md#configuration
|
9
|
+
# README} for more.
|
10
|
+
CONFIG_KEYS = %i[enabled version_updates save_trash].freeze
|
7
11
|
|
12
|
+
# @!visibility private
|
8
13
|
VERSION_CLASS_SUFFIX = 'Version'
|
14
|
+
|
15
|
+
# @!visibility private
|
9
16
|
VERSION_TABLE_SUFFIX = "_#{VERSION_CLASS_SUFFIX.tableize}"
|
10
|
-
|
17
|
+
|
18
|
+
# @!visibility private
|
11
19
|
DURING_QUERY = '_during @> ?::timestamp'
|
12
20
|
|
13
21
|
@context = {}
|
@@ -36,6 +44,9 @@ module Hoardable
|
|
36
44
|
end
|
37
45
|
end
|
38
46
|
|
47
|
+
# This is a general use method for setting {DATA_KEYS} or {CONFIG_KEYS} around a scoped block.
|
48
|
+
#
|
49
|
+
# @param hash [Hash] Options and contextual data to set within a block
|
39
50
|
def with(hash)
|
40
51
|
current_config = @config
|
41
52
|
current_context = @context
|
data/lib/hoardable/model.rb
CHANGED
@@ -1,11 +1,36 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Hoardable
|
4
|
-
# This concern
|
5
|
-
# the
|
4
|
+
# This concern is the main entrypoint for using {Hoardable}. When included into an +ActiveRecord+
|
5
|
+
# class, it dynamically generates the +Version+ variant of that class (with {VersionModel}) and
|
6
|
+
# includes the {Hoardable} API methods and relationships on the source model class (through
|
7
|
+
# {SourceModel}).
|
6
8
|
module Model
|
7
9
|
extend ActiveSupport::Concern
|
8
10
|
|
11
|
+
class_methods do
|
12
|
+
# @!visibility private
|
13
|
+
attr_reader :_hoardable_options
|
14
|
+
|
15
|
+
# If called with a hash, this will set the model-level +Hoardable+ configuration variables. If
|
16
|
+
# called without an argument it will return the computed +Hoardable+ configuration considering
|
17
|
+
# both model-level and global values.
|
18
|
+
#
|
19
|
+
# @param hash [Hash] The +Hoardable+ configuration for the model. Keys must be present in
|
20
|
+
# {CONFIG_KEYS}
|
21
|
+
# @return [Hash]
|
22
|
+
def hoardable_options(hash = nil)
|
23
|
+
if hash
|
24
|
+
@_hoardable_options = hash.slice(*Hoardable::CONFIG_KEYS)
|
25
|
+
else
|
26
|
+
@_hoardable_options ||= {}
|
27
|
+
Hoardable::CONFIG_KEYS.to_h do |key|
|
28
|
+
[key, Hoardable.send(key) != false && @_hoardable_options[key] != false]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
9
34
|
included do
|
10
35
|
define_model_callbacks :versioned
|
11
36
|
define_model_callbacks :reverted, only: :after
|
@@ -1,11 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Hoardable
|
4
|
-
# This concern contains the relationships, callbacks, and API methods for
|
4
|
+
# This concern contains the {Hoardable} relationships, callbacks, and API methods for an
|
5
|
+
# +ActiveRecord+. It is included by {Hoardable::Model} after the dynamic generation of the
|
6
|
+
# +Version+ class variant.
|
5
7
|
module SourceModel
|
6
8
|
extend ActiveSupport::Concern
|
7
9
|
|
8
10
|
class_methods do
|
11
|
+
# The dynamically generated +Version+ class for this model.
|
9
12
|
def version_class
|
10
13
|
"#{name}#{VERSION_CLASS_SUFFIX}".constantize
|
11
14
|
end
|
@@ -14,15 +17,22 @@ module Hoardable
|
|
14
17
|
included do
|
15
18
|
include Tableoid
|
16
19
|
|
17
|
-
around_update :insert_hoardable_version_on_update, if:
|
18
|
-
around_destroy :insert_hoardable_version_on_destroy, if: [
|
19
|
-
before_destroy :delete_hoardable_versions, if: :hoardable_callbacks_enabled, unless:
|
20
|
+
around_update :insert_hoardable_version_on_update, if: %i[hoardable_callbacks_enabled hoardable_version_updates]
|
21
|
+
around_destroy :insert_hoardable_version_on_destroy, if: %i[hoardable_callbacks_enabled hoardable_save_trash]
|
22
|
+
before_destroy :delete_hoardable_versions, if: :hoardable_callbacks_enabled, unless: :hoardable_save_trash
|
20
23
|
after_commit :unset_hoardable_version_and_event_uuid
|
21
24
|
|
25
|
+
# This will contain the +Version+ class instance for use within +versioned+, +reverted+, and
|
26
|
+
# +untrashed+ callbacks.
|
22
27
|
attr_reader :hoardable_version
|
23
28
|
|
29
|
+
# @!attribute [r] hoardable_event_uuid
|
30
|
+
# @return [String] A postgres UUID that represents the +version+’s +ActiveRecord+ database transaction
|
31
|
+
# @!attribute [r] hoardable_operation
|
32
|
+
# @return [String] The database operation that created the +version+ - either +update+ or +delete+.
|
24
33
|
delegate :hoardable_event_uuid, :hoardable_operation, to: :hoardable_version, allow_nil: true
|
25
34
|
|
35
|
+
# Returns all +versions+ in ascending order of their temporal timeframes.
|
26
36
|
has_many(
|
27
37
|
:versions, -> { order(:_during) },
|
28
38
|
dependent: nil,
|
@@ -31,16 +41,27 @@ module Hoardable
|
|
31
41
|
)
|
32
42
|
end
|
33
43
|
|
44
|
+
# Returns a boolean of whether the record is actually a trashed +version+.
|
45
|
+
#
|
46
|
+
# @return [Boolean]
|
34
47
|
def trashed?
|
35
48
|
versions.trashed.limit(1).order(_during: :desc).first&.send(:hoardable_source_attributes) == attributes
|
36
49
|
end
|
37
50
|
|
51
|
+
# Returns the +version+ at the supplied +datetime+ or +time+. It will return +self+ if there is
|
52
|
+
# none. This will raise an error if you try to find a version in the future.
|
53
|
+
#
|
54
|
+
# @param datetime [DateTime, Time]
|
38
55
|
def at(datetime)
|
39
56
|
raise(Error, 'Future state cannot be known') if datetime.future?
|
40
57
|
|
41
58
|
versions.find_by(DURING_QUERY, datetime) || self
|
42
59
|
end
|
43
60
|
|
61
|
+
# If a version is found at the supplied datetime, it will +revert!+ to it and return it. This
|
62
|
+
# will raise an error if you try to revert to a version in the future.
|
63
|
+
#
|
64
|
+
# @param datetime [DateTime, Time]
|
44
65
|
def revert_to!(datetime)
|
45
66
|
return unless (version = at(datetime))
|
46
67
|
|
@@ -50,7 +71,15 @@ module Hoardable
|
|
50
71
|
private
|
51
72
|
|
52
73
|
def hoardable_callbacks_enabled
|
53
|
-
|
74
|
+
self.class.hoardable_options[:enabled] && !self.class.name.end_with?(VERSION_CLASS_SUFFIX)
|
75
|
+
end
|
76
|
+
|
77
|
+
def hoardable_save_trash
|
78
|
+
self.class.hoardable_options[:save_trash]
|
79
|
+
end
|
80
|
+
|
81
|
+
def hoardable_version_updates
|
82
|
+
self.class.hoardable_options[:version_updates]
|
54
83
|
end
|
55
84
|
|
56
85
|
def insert_hoardable_version_on_update(&block)
|
data/lib/hoardable/tableoid.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Hoardable
|
4
|
-
# This concern provides support for PostgreSQL
|
4
|
+
# This concern provides support for PostgreSQL’s tableoid system column to {SourceModel}.
|
5
5
|
module Tableoid
|
6
6
|
extend ActiveSupport::Concern
|
7
7
|
|
8
|
+
# @!visibility private
|
8
9
|
TABLEOID_AREL_CONDITIONS = lambda do |arel_table, condition|
|
9
10
|
arel_table[:tableoid].send(
|
10
11
|
condition,
|
@@ -13,13 +14,32 @@ module Hoardable
|
|
13
14
|
end.freeze
|
14
15
|
|
15
16
|
included do
|
17
|
+
# @!visibility private
|
16
18
|
attr_writer :tableoid
|
17
19
|
|
20
|
+
# By default, {Hoardable} only returns instances of the parent table, and not the +versions+
|
21
|
+
# in the inherited table.
|
18
22
|
default_scope { where(TABLEOID_AREL_CONDITIONS.call(arel_table, :eq)) }
|
23
|
+
|
24
|
+
# @!scope class
|
25
|
+
# @!method include_versions
|
26
|
+
# @return [ActiveRecord<Object>]
|
27
|
+
#
|
28
|
+
# Returns +versions+ along with instances of the source models, all cast as instances of the
|
29
|
+
# source model’s class.
|
19
30
|
scope :include_versions, -> { unscope(where: [:tableoid]) }
|
31
|
+
|
32
|
+
# @!scope class
|
33
|
+
# @!method versions
|
34
|
+
# @return [ActiveRecord<Object>]
|
35
|
+
#
|
36
|
+
# Returns only +versions+ of the parent +ActiveRecord+ class, cast as instances of the source
|
37
|
+
# model’s class.
|
20
38
|
scope :versions, -> { include_versions.where(TABLEOID_AREL_CONDITIONS.call(arel_table, :not_eq)) }
|
21
39
|
end
|
22
40
|
|
41
|
+
private
|
42
|
+
|
23
43
|
def tableoid
|
24
44
|
connection.execute("SELECT oid FROM pg_class WHERE relname = '#{table_name}'")[0]['oid']
|
25
45
|
end
|
data/lib/hoardable/version.rb
CHANGED
@@ -1,12 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Hoardable
|
4
|
-
# This concern is included into the dynamically generated Version
|
4
|
+
# This concern is included into the dynamically generated +Version+ kind of the parent
|
5
|
+
# +ActiveRecord+ class.
|
5
6
|
module VersionModel
|
6
7
|
extend ActiveSupport::Concern
|
7
8
|
|
8
9
|
included do
|
9
10
|
hoardable_source_key = superclass.model_name.i18n_key
|
11
|
+
|
12
|
+
# A +version+ belongs to it’s parent +ActiveRecord+ source.
|
10
13
|
belongs_to hoardable_source_key, inverse_of: :versions
|
11
14
|
alias_method :hoardable_source, hoardable_source_key
|
12
15
|
|
@@ -19,15 +22,35 @@ module Hoardable
|
|
19
22
|
|
20
23
|
before_create :assign_temporal_tsrange
|
21
24
|
|
25
|
+
# @!scope class
|
26
|
+
# @!method trashed
|
27
|
+
# @return [ActiveRecord<Object>]
|
28
|
+
#
|
29
|
+
# Returns only trashed +versions+ that are orphans.
|
22
30
|
scope :trashed, lambda {
|
23
31
|
left_outer_joins(hoardable_source_key)
|
24
32
|
.where(superclass.table_name => { id: nil })
|
25
33
|
.where(_operation: 'delete')
|
26
34
|
}
|
35
|
+
|
36
|
+
# @!scope class
|
37
|
+
# @!method at
|
38
|
+
# @return [ActiveRecord<Object>]
|
39
|
+
#
|
40
|
+
# Returns +versions+ that were valid at the supplied +datetime+ or +time+.
|
27
41
|
scope :at, ->(datetime) { where(DURING_QUERY, datetime) }
|
42
|
+
|
43
|
+
# @!scope class
|
44
|
+
# @!method with_hoardable_event_uuid
|
45
|
+
# @return [ActiveRecord<Object>]
|
46
|
+
#
|
47
|
+
# Returns all +versions+ that were created as part of the same +ActiveRecord+ database
|
48
|
+
# transaction of the supplied +event_uuid+. Useful in +reverted+ and +untrashed+ callbacks.
|
28
49
|
scope :with_hoardable_event_uuid, ->(event_uuid) { where(_event_uuid: event_uuid) }
|
29
50
|
end
|
30
51
|
|
52
|
+
# Reverts the parent +ActiveRecord+ instance to the saved attributes of this +version+. Raises
|
53
|
+
# an error if the version is trashed.
|
31
54
|
def revert!
|
32
55
|
raise(Error, 'Version is trashed, cannot revert') unless hoardable_operation == 'update'
|
33
56
|
|
@@ -40,6 +63,8 @@ module Hoardable
|
|
40
63
|
end
|
41
64
|
end
|
42
65
|
|
66
|
+
# Inserts a trashed +version+ back into its parent +ActiveRecord+ table with its original
|
67
|
+
# primary key. Raises an error if the version is not trashed.
|
43
68
|
def untrash!
|
44
69
|
raise(Error, 'Version is not trashed, cannot untrash') unless hoardable_operation == 'delete'
|
45
70
|
|
@@ -59,6 +84,9 @@ module Hoardable
|
|
59
84
|
end
|
60
85
|
end
|
61
86
|
|
87
|
+
# Returns the +ActiveRecord+
|
88
|
+
# {https://api.rubyonrails.org/classes/ActiveModel/Dirty.html#method-i-changes changes} that
|
89
|
+
# were present during version creation.
|
62
90
|
def changes
|
63
91
|
_data&.dig('changes')
|
64
92
|
end
|
data/sig/hoardable.rbs
CHANGED
@@ -1,4 +1,86 @@
|
|
1
1
|
module Hoardable
|
2
2
|
VERSION: String
|
3
|
-
|
3
|
+
DATA_KEYS: [:meta, :whodunit, :note, :event_uuid]
|
4
|
+
CONFIG_KEYS: [:enabled, :version_updates, :save_trash]
|
5
|
+
VERSION_CLASS_SUFFIX: String
|
6
|
+
VERSION_TABLE_SUFFIX: String
|
7
|
+
DURING_QUERY: String
|
8
|
+
self.@context: Hash[untyped, untyped]
|
9
|
+
self.@config: untyped
|
10
|
+
|
11
|
+
def self.with: (untyped hash) -> untyped
|
12
|
+
|
13
|
+
module Tableoid
|
14
|
+
TABLEOID_AREL_CONDITIONS: Proc
|
15
|
+
|
16
|
+
private
|
17
|
+
def tableoid: -> untyped
|
18
|
+
|
19
|
+
public
|
20
|
+
attr_writer tableoid: untyped
|
21
|
+
end
|
22
|
+
|
23
|
+
class Error < StandardError
|
24
|
+
end
|
25
|
+
|
26
|
+
module SourceModel
|
27
|
+
include Tableoid
|
28
|
+
|
29
|
+
def trashed?: -> untyped
|
30
|
+
def at: (untyped datetime) -> SourceModel
|
31
|
+
def revert_to!: (untyped datetime) -> SourceModel?
|
32
|
+
|
33
|
+
private
|
34
|
+
def hoardable_callbacks_enabled: -> untyped
|
35
|
+
def hoardable_save_trash: -> untyped
|
36
|
+
def hoardable_version_updates: -> untyped
|
37
|
+
def insert_hoardable_version_on_update: -> untyped
|
38
|
+
def insert_hoardable_version_on_destroy: -> untyped
|
39
|
+
def insert_hoardable_version: (String operation, untyped attrs) -> untyped
|
40
|
+
def find_or_initialize_hoardable_event_uuid: -> untyped
|
41
|
+
def initialize_hoardable_version: (String operation, untyped attrs) -> untyped
|
42
|
+
def initialize_hoardable_data: -> untyped
|
43
|
+
def assign_hoardable_context: (:event_uuid | :meta | :note | :whodunit key) -> nil
|
44
|
+
def delete_hoardable_versions: -> untyped
|
45
|
+
def unset_hoardable_version_and_event_uuid: -> nil
|
46
|
+
|
47
|
+
public
|
48
|
+
def version_class: -> untyped
|
49
|
+
attr_reader hoardable_version: nil
|
50
|
+
end
|
51
|
+
|
52
|
+
module VersionModel
|
53
|
+
@hoardable_source_attributes: untyped
|
54
|
+
@hoardable_source_foreign_key: String
|
55
|
+
@hoardable_source_foreign_id: untyped
|
56
|
+
|
57
|
+
def revert!: -> untyped
|
58
|
+
def untrash!: -> untyped
|
59
|
+
def changes: -> untyped
|
60
|
+
|
61
|
+
private
|
62
|
+
def untrashable_hoardable_source_attributes: -> untyped
|
63
|
+
def hoardable_source_attributes: -> untyped
|
64
|
+
def hoardable_source_foreign_key: -> String
|
65
|
+
def hoardable_source_foreign_id: -> untyped
|
66
|
+
def previous_temporal_tsrange_end: -> untyped
|
67
|
+
def assign_temporal_tsrange: -> Range
|
68
|
+
end
|
69
|
+
|
70
|
+
module Model
|
71
|
+
include VersionModel
|
72
|
+
include SourceModel
|
73
|
+
|
74
|
+
attr_reader _hoardable_options: Hash[untyped, untyped]
|
75
|
+
def hoardable_options: (?nil hash) -> untyped
|
76
|
+
end
|
77
|
+
|
78
|
+
class MigrationGenerator
|
79
|
+
@singularized_table_name: untyped
|
80
|
+
|
81
|
+
def create_versions_table: -> untyped
|
82
|
+
def foreign_key_type: -> String
|
83
|
+
def migration_template_name: -> String
|
84
|
+
def singularized_table_name: -> untyped
|
85
|
+
end
|
4
86
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hoardable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- justin talbott
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-08-
|
11
|
+
date: 2022-08-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|