hoardable 0.8.0 → 0.9.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1cd77fbd3d35df59423ba95f7286703ae0d3b0f78bd9097b3574c713c38aa4c7
4
- data.tar.gz: d5971e9daf59a9fa5343c13e389b20fc5b6ff193b398d05c958f34dfd056d0cb
3
+ metadata.gz: 5b85dfaf658e447049fcb09281d34dd25188be79f948eda294398f47b19b8244
4
+ data.tar.gz: 67219612736259e2dbc542230cc1490a156a15bc679340176aca35b76aaf516c
5
5
  SHA512:
6
- metadata.gz: 5de03adf485f38e3ee3a24999bf770d92792404894529a5317f9788d15b784c0bcd9aa28b3d2966340a1244296cdc7b4ebe6fdccd6791172b44ca498c4bf5fca
7
- data.tar.gz: a39bd22b66c727ec791e704ec3b24592c068dd2eb29ae0fa7d70a440073bd6d635fd7f24f12d3ba34bf05976b311bab9ec6a5a6fdf9f9069311347d89ae8f8c0
6
+ metadata.gz: cf3c5edfeac5526e7520dc2584caba8bb5399df43acf1ce6bd320b19f44981c154624b9b80c5b415aaeb840fc5d718f1999b4bbaf82eb3ff76149e09621ab0e5
7
+ data.tar.gz: 52112fb9bc55bec2009656cce9571887130333b6460d5478c1a0c113895ccb977ffcc80172954911c6e70d2012f136bf68c64b17bc69ffd7deeaa40a56c97646
data/.rubocop.yml CHANGED
@@ -16,3 +16,6 @@ Metrics/BlockLength:
16
16
 
17
17
  Style/DocumentDynamicEvalDefinition:
18
18
  Enabled: false
19
+
20
+ Naming/PredicateName:
21
+ Enabled: false
data/CHANGELOG.md CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
  - Stability is coming.
4
4
 
5
+ ## [0.9.0] - 2022-10-02
6
+
7
+ - **Breaking Change** - `Hoardable.return_everything` was removed in favor of the newly added
8
+ `Hoardable.at`.
9
+
5
10
  ## [0.8.0] - 2022-10-01
6
11
 
7
12
  - **Breaking Change** - Due to the performance benefit of using `insert` for database injection of
data/README.md CHANGED
@@ -31,6 +31,12 @@ gem 'hoardable'
31
31
 
32
32
  And then execute `bundle install`.
33
33
 
34
+ If you would like to generate an initializer with the global [configuration](#configuration) options:
35
+
36
+ ```
37
+ rails g hoardable:initializer
38
+ ```
39
+
34
40
  ### Model Installation
35
41
 
36
42
  You must include `Hoardable::Model` into an ActiveRecord model that you would like to hoard versions
@@ -64,6 +70,9 @@ _Note:_ If you are on Rails 6.1, you might want to set `config.active_record.sch
64
70
  in `application.rb`, so that the enum type is captured in your schema dump. This is not required in
65
71
  Rails 7.
66
72
 
73
+ _Note:_ Creating an inherited table does not copy over the indexes from the parent table. If you
74
+ need to query versions often, you should add appropriate indexes to the `_versions` tables.
75
+
67
76
  ## Usage
68
77
 
69
78
  ### Overview
@@ -99,7 +108,7 @@ Each `PostVersion` has access to the same attributes, relationships, and other m
99
108
 
100
109
  If you ever need to revert to a specific version, you can call `version.revert!` on it.
101
110
 
102
- ``` ruby
111
+ ```ruby
103
112
  post = Post.create!(title: "Title")
104
113
  post.update!(title: "Whoops")
105
114
  post.reload.versions.last.revert!
@@ -107,7 +116,7 @@ post.title # => "Title"
107
116
  ```
108
117
 
109
118
  If you would like to untrash a specific version, you can call `version.untrash!` on it. This will
110
- re-insert the model in the parent class’s table with it’s original primary key.
119
+ re-insert the model in the parent class’s table with the original primary key.
111
120
 
112
121
  ```ruby
113
122
  post = Post.create!(title: "Title")
@@ -139,16 +148,15 @@ PostVersion.at(1.day.ago).find_by(hoardable_source_id: post.id) # => #<PostVersi
139
148
 
140
149
  The source model class also has an `.at` method:
141
150
 
142
- ``` ruby
151
+ ```ruby
143
152
  Post.at(1.day.ago) # => [#<Post>, #<Post>]
144
153
  ```
145
154
 
146
- This will return an ActiveRecord scoped query of all `Posts` and `PostVersions` that were valid at
147
- that time, all cast as instances of `Post`.
155
+ This will return an ActiveRecord scoped query of all `Post` and `PostVersion` records that were
156
+ valid at that time, all cast as instances of `Post`.
148
157
 
149
- _Note:_ A `Version` is not created upon initial parent model creation. To accurately track the
150
- beginning of the first temporal period, you will need to ensure the source model table has a
151
- `created_at` timestamp column.
158
+ There is also an `at` method on `Hoardable` itself for more complex temporal resource querying. See
159
+ [Relationships](#relationships) for more.
152
160
 
153
161
  By default, `hoardable` will keep copies of records you have destroyed. You can query them
154
162
  specifically with:
@@ -156,10 +164,12 @@ specifically with:
156
164
  ```ruby
157
165
  PostVersion.trashed
158
166
  Post.version_class.trashed # <- same thing as above
167
+ PostVersion.trashed.first.trashed? # <- true
159
168
  ```
160
169
 
161
- _Note:_ Creating an inherited table does not copy over the indexes from the parent table. If you
162
- need to query versions often, you should add appropriate indexes to the `_versions` tables.
170
+ _Note:_ A `Version` is not created upon initial parent model creation. To accurately track the
171
+ beginning of the first temporal period, you will need to ensure the source model table has a
172
+ `created_at` timestamp column.
163
173
 
164
174
  ### Tracking Contextual Data
165
175
 
@@ -263,7 +273,6 @@ The configurable options are:
263
273
  Hoardable.enabled # => default true
264
274
  Hoardable.version_updates # => default true
265
275
  Hoardable.save_trash # => default true
266
- Hoardable.return_everything # => default false
267
276
  ```
268
277
 
269
278
  `Hoardable.enabled` controls whether versions will be ever be created.
@@ -273,10 +282,6 @@ Hoardable.return_everything # => default false
273
282
  `Hoardable.save_trash` controls whether to create versions upon record deletion. When this is set to
274
283
  `false`, all versions of a record will be deleted when the record is destroyed.
275
284
 
276
- `Hoardable.return_everything` controls whether to include versions when doing queries for source
277
- models. This is typically only useful to set around a block, as explained below in
278
- [Relationships](#relationships).
279
-
280
285
  If you would like to temporarily set a config setting, you can use `Hoardable.with`:
281
286
 
282
287
  ```ruby
@@ -323,8 +328,54 @@ class Comment
323
328
  end
324
329
  ```
325
330
 
326
- Sometimes youll trash something that `has_many :children, dependent: :destroy` and both the parent
327
- and child model classes include `Hoardable::Model`. Whenever a hoardable version is created in a
331
+ Sometimes you'll have a Hoardable record that `has_many` other Hoardable records and you will want
332
+ to know the state of both the parent record and the children at a cetain point in time. You
333
+ accomplish this by establishing a `has_many_hoardable` relationship and using the `Hoardable.at`
334
+ method:
335
+
336
+ ```ruby
337
+ class Post
338
+ include Hoardable::Model
339
+ has_many_hoardable :comments
340
+ end
341
+
342
+ def Comment
343
+ include Hoardable::Model
344
+ end
345
+
346
+ post = Post.create!(title: 'Title')
347
+ comment1 = post.comments.create!(body: 'Comment')
348
+ comment2 = post.comments.create!(body: 'Comment')
349
+ datetime = DateTime.current
350
+ comment2.destroy!
351
+ post.update!(title: 'New Title')
352
+ post_id = post.id # 1
353
+
354
+ Hoardable.at(datetime) do
355
+ post = Post.hoardable.find(post_id)
356
+ post.title # => 'Title'
357
+ post.comments.size # => 2
358
+ post.id # => 2
359
+ post.version? # => true
360
+ post.hoardable_source_id # => 1
361
+ end
362
+ ```
363
+
364
+ There are some additional details to point out above. Firstly, it is important to note that the
365
+ final `post.id` yields a different value than the originally created `Post`. This is because the
366
+ `post` within the `#at` block is actually a temporal version, since it has been subsequently
367
+ updated, but it has been reified as a `Post` for the purposes of your business logic (serialization,
368
+ rendering views, exporting, etc). Don’t fret - you will not be able to commit any updates to the
369
+ version, even though it is masquerading as a `Post`.
370
+
371
+ If you are ever unsure if a Hoardable record is a "source" or a "version", you can be sure by
372
+ calling `version?` on it. If you want to get the true original source record ID, you can call
373
+ `hoardable_source_id`. Finally, if you prepend `.hoardable` to a `.find` call on the source model
374
+ class, you can always find the relevant source or temporal version record using just the original
375
+ source record’s id.
376
+
377
+ Sometimes you’ll trash something that `has_many_hoardable :children, dependent: :destroy` and want
378
+ to untrash everything in a similar dependent manner. Whenever a hoardable version is created in a
328
379
  database transaction, it will create or re-use a unique event UUID for that transaction and tag all
329
380
  versions created with it. That way, when you `untrash!` a record, you can find and `untrash!`
330
381
  records that were trashed with it:
@@ -332,7 +383,7 @@ records that were trashed with it:
332
383
  ```ruby
333
384
  class Post < ActiveRecord::Base
334
385
  include Hoardable::Model
335
- has_many :comments, dependent: :destroy # `Comment` also includes `Hoardable::Model`
386
+ has_many_hoardable :comments, dependent: :destroy # `Comment` also includes `Hoardable::Model`
336
387
 
337
388
  after_untrashed do
338
389
  Comment
@@ -344,22 +395,6 @@ class Post < ActiveRecord::Base
344
395
  end
345
396
  ```
346
397
 
347
- If there are models that might be related to versions that are trashed or otherwise, and/or might be
348
- trashed themselves, you can bypass the inherited tables query handling altogether by using the
349
- `return_everything` configuration variable in `Hoardable.with`. This will ensure that you always see
350
- all records, including update and trashed versions.
351
-
352
- ```ruby
353
- post.destroy!
354
-
355
- Hoardable.with(return_everything: true) do
356
- post = Post.find(post.id) # returns the trashed post as if it was not
357
- post.comments # returns the trashed comments as well
358
- end
359
-
360
- post.reload # raises ActiveRecord::RecordNotFound
361
- ```
362
-
363
398
  ## Gem Comparison
364
399
 
365
400
  ### [`paper_trail`](https://github.com/paper-trail-gem/paper_trail)
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators'
4
+
5
+ module Hoardable
6
+ # Generates an initializer file for {Hoardable} configuration.
7
+ class InitializerGenerator < Rails::Generators::Base
8
+ def create_initializer_file
9
+ create_file(
10
+ 'config/initializers/hoardable.rb',
11
+ <<~TEXT
12
+ # Hoardable configuration defaults are below. Learn more at https://github.com/waymondo/hoardable#configuration
13
+ #
14
+ # Hoardable.enabled = true
15
+ # Hoardable.version_updates = true
16
+ # Hoardable.save_trash = true
17
+ TEXT
18
+ )
19
+ end
20
+ end
21
+ end
@@ -10,6 +10,20 @@ class Create<%= class_name.singularize %>Versions < ActiveRecord::Migration[<%=
10
10
  t.enum :_operation, enum_type: 'hoardable_operation', null: false, index: true
11
11
  t.<%= foreign_key_type %> :hoardable_source_id, null: false, index: true
12
12
  end
13
+ execute(
14
+ <<~SQL
15
+ CREATE OR REPLACE FUNCTION hoardable_version_prevent_update() RETURNS trigger
16
+ LANGUAGE plpgsql AS
17
+ $$BEGIN
18
+ RAISE EXCEPTION 'updating a version is not allowed';
19
+ RETURN NEW;
20
+ END;$$;
21
+
22
+ CREATE TRIGGER <%= singularized_table_name %>_versions_prevent_update
23
+ BEFORE UPDATE ON <%= singularized_table_name %>_versions FOR EACH ROW
24
+ EXECUTE PROCEDURE hoardable_version_prevent_update();
25
+ SQL
26
+ )
13
27
  add_index(:<%= singularized_table_name %>_versions, :id, unique: true)
14
28
  add_index(
15
29
  :<%= singularized_table_name %>_versions,
@@ -25,6 +25,20 @@ class Create<%= class_name.singularize %>Versions < ActiveRecord::Migration[<%=
25
25
  t.column :_operation, :hoardable_operation, null: false, index: true
26
26
  t.<%= foreign_key_type %> :hoardable_source_id, null: false, index: true
27
27
  end
28
+ execute(
29
+ <<~SQL
30
+ CREATE OR REPLACE FUNCTION hoardable_version_prevent_update() RETURNS trigger
31
+ LANGUAGE plpgsql AS
32
+ $$BEGIN
33
+ RAISE EXCEPTION 'updating a version is not allowed';
34
+ RETURN NEW;
35
+ END;$$;
36
+
37
+ CREATE TRIGGER <%= singularized_table_name %>_versions_prevent_update
38
+ BEFORE UPDATE ON <%= singularized_table_name %>_versions FOR EACH ROW
39
+ EXECUTE PROCEDURE hoardable_version_prevent_update();
40
+ SQL
41
+ )
28
42
  add_index(:<%= singularized_table_name %>_versions, :id, unique: true)
29
43
  add_index(
30
44
  :<%= singularized_table_name %>_versions,
@@ -7,6 +7,26 @@ module Hoardable
7
7
  module Associations
8
8
  extend ActiveSupport::Concern
9
9
 
10
+ # An +ActiveRecord+ extension that allows looking up {VersionModel}s by +hoardable_source_id+ as
11
+ # if they were {SourceModel}s.
12
+ module HasManyScope
13
+ def scope
14
+ @scope ||= hoardable_scope
15
+ end
16
+
17
+ private
18
+
19
+ def hoardable_scope
20
+ if Hoardable.instance_variable_get('@at') &&
21
+ (hoardable_source_id = @association.owner.hoardable_source_id)
22
+ @association.scope.rewhere(@association.reflection.foreign_key => hoardable_source_id)
23
+ else
24
+ @association.scope
25
+ end
26
+ end
27
+ end
28
+ private_constant :HasManyScope
29
+
10
30
  class_methods do
11
31
  # A wrapper for +ActiveRecord+’s +belongs_to+ that allows for falling back to the most recent
12
32
  # trashed +version+, in the case that the related source has been trashed.
@@ -29,6 +49,12 @@ module Hoardable
29
49
  end
30
50
  RUBY
31
51
  end
52
+
53
+ # A wrapper for +ActiveRecord+’s +has_many+ that allows for finding temporal versions of a
54
+ # record cast as instances of the {SourceModel}, when doing a {Hoardable#at} query.
55
+ def has_many_hoardable(name, scope = nil, **options)
56
+ has_many(name, scope, **options) { include HasManyScope }
57
+ end
32
58
  end
33
59
  end
34
60
  end
@@ -23,6 +23,15 @@ module Hoardable
23
23
  Thread.current[:hoardable_event_uuid] ||= ActiveRecord::Base.connection.query('SELECT gen_random_uuid();')[0][0]
24
24
  end
25
25
 
26
+ def hoardable_version_source_id
27
+ @hoardable_version_source_id ||= query_hoardable_version_source_id
28
+ end
29
+
30
+ def query_hoardable_version_source_id
31
+ primary_key = source_record.class.primary_key
32
+ version_class.where(primary_key => source_record.read_attribute(primary_key)).pluck('hoardable_source_id')[0]
33
+ end
34
+
26
35
  def initialize_version_attributes(operation)
27
36
  source_record.attributes_before_type_cast.without('id').merge(
28
37
  source_record.changes.transform_values { |h| h[0] },
@@ -8,7 +8,7 @@ module Hoardable
8
8
 
9
9
  # Symbols for use with setting {Hoardable} configuration. See {file:README.md#configuration
10
10
  # README} for more.
11
- CONFIG_KEYS = %i[enabled version_updates save_trash return_everything warn_on_missing_created_at_column].freeze
11
+ CONFIG_KEYS = %i[enabled version_updates save_trash warn_on_missing_created_at_column].freeze
12
12
 
13
13
  VERSION_CLASS_SUFFIX = 'Version'
14
14
  private_constant :VERSION_CLASS_SUFFIX
@@ -36,7 +36,7 @@ module Hoardable
36
36
 
37
37
  @context = {}
38
38
  @config = CONFIG_KEYS.to_h do |key|
39
- [key, key != :return_everything]
39
+ [key, true]
40
40
  end
41
41
 
42
42
  class << self
@@ -75,6 +75,17 @@ module Hoardable
75
75
  @context = current_context
76
76
  end
77
77
 
78
+ # Allows performing a query for record states at a certain time. Returned {SourceModel}
79
+ # instances within the block may be {SourceModel} or {VersionModel} records.
80
+ #
81
+ # @param datetime [DateTime, Time] the datetime or time to temporally query records at
82
+ def at(datetime)
83
+ @at = datetime
84
+ yield
85
+ ensure
86
+ @at = nil
87
+ end
88
+
78
89
  # @!visibility private
79
90
  def logger
80
91
  @logger ||= ActiveSupport::TaggedLogging.new(Logger.new($stdout))
@@ -1,8 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Hoardable
4
- # This concern provides support for PostgreSQL’s tableoid system column to {SourceModel}.
5
- module Tableoid
4
+ # This concern provides support for PostgreSQL’s tableoid system column to {SourceModel} and
5
+ # temporal +ActiveRecord+ scopes.
6
+ module Scopes
6
7
  extend ActiveSupport::Concern
7
8
 
8
9
  TABLEOID_AREL_CONDITIONS = lambda do |arel_table, condition|
@@ -19,10 +20,10 @@ module Hoardable
19
20
 
20
21
  # By default {Hoardable} only returns instances of the parent table, and not the +versions+ in
21
22
  # the inherited table. This can be bypassed by using the {.include_versions} scope or wrapping
22
- # the code in a `Hoardable.with(return_everything: true)` block.
23
+ # the code in a `Hoardable.at(datetime)` block.
23
24
  default_scope do
24
- if hoardable_config[:return_everything]
25
- where(nil)
25
+ if (hoardable_at = Hoardable.instance_variable_get('@at'))
26
+ at(hoardable_at)
26
27
  else
27
28
  exclude_versions
28
29
  end
@@ -51,6 +52,18 @@ module Hoardable
51
52
  # Excludes +versions+ of the parent +ActiveRecord+ class. This is included by default in the
52
53
  # source model’s +default_scope+.
53
54
  scope :exclude_versions, -> { where(TABLEOID_AREL_CONDITIONS.call(arel_table, :eq)) }
55
+
56
+ # @!scope class
57
+ # @!method at
58
+ # @return [ActiveRecord<Object>]
59
+ #
60
+ # Returns instances of the source model and versions that were valid at the supplied
61
+ # +datetime+ or +time+, all cast as instances of the source model.
62
+ scope :at, lambda { |datetime|
63
+ include_versions.where(id: version_class.at(datetime).select('id')).or(
64
+ where.not(id: version_class.select(:hoardable_source_id).where(DURING_QUERY, datetime))
65
+ )
66
+ }
54
67
  end
55
68
 
56
69
  private
@@ -16,15 +16,30 @@ module Hoardable
16
16
  # @return [String] The database operation that created the +version+ - either +update+ or +delete+.
17
17
  delegate :hoardable_event_uuid, :hoardable_operation, to: :hoardable_version, allow_nil: true
18
18
 
19
+ # A module for overriding +ActiveRecord#find_one+’ in the case you are doing a temporal query
20
+ # and the current {SourceModel} record may in fact be a {VersionModel} record.
21
+ module FinderMethods
22
+ def find_one(id)
23
+ conditions = { primary_key => [id, *version_class.where(hoardable_source_id: id).select(primary_key).ids] }
24
+ find_by(conditions) || where(conditions).raise_record_not_found_exception!
25
+ end
26
+ end
27
+ private_constant :FinderMethods
28
+
19
29
  class_methods do
20
30
  # The dynamically generated +Version+ class for this model.
21
31
  def version_class
22
32
  "#{name}#{VERSION_CLASS_SUFFIX}".constantize
23
33
  end
34
+
35
+ # Extends the current {SourceModel} scoping to include Hoardable’s {FinderMethods} overrides.
36
+ def hoardable
37
+ extending(FinderMethods)
38
+ end
24
39
  end
25
40
 
26
41
  included do
27
- include Tableoid
42
+ include Scopes
28
43
 
29
44
  around_update(if: [HOARDABLE_CALLBACKS_ENABLED, HOARDABLE_VERSION_UPDATES]) do |_, block|
30
45
  hoardable_client.insert_hoardable_version('update', &block)
@@ -48,25 +63,22 @@ module Hoardable
48
63
  inverse_of: :hoardable_source,
49
64
  foreign_key: :hoardable_source_id
50
65
  )
51
-
52
- # @!scope class
53
- # @!method at
54
- # @return [ActiveRecord<Object>]
55
- #
56
- # Returns instances of the source model and versions that were valid at the supplied
57
- # +datetime+ or +time+, all cast as instances of the source model.
58
- scope :at, lambda { |datetime|
59
- include_versions.where(id: version_class.at(datetime).select('id')).or(
60
- where.not(id: version_class.select(:hoardable_source_id).where(DURING_QUERY, datetime))
61
- )
62
- }
63
66
  end
64
67
 
65
- # Returns a boolean of whether the record is actually a trashed +version+.
68
+ # Returns a boolean of whether the record is actually a trashed +version+ cast as an instance of the
69
+ # source model.
66
70
  #
67
71
  # @return [Boolean]
68
72
  def trashed?
69
- versions.trashed.only_most_recent.first&.hoardable_source_foreign_id == id
73
+ versions.trashed.only_most_recent.first&.hoardable_source_id == id
74
+ end
75
+
76
+ # Returns a boolean of whether the record is actually a +version+ cast as an instance of the
77
+ # source model.
78
+ #
79
+ # @return [Boolean]
80
+ def version?
81
+ !!hoardable_client.hoardable_version_source_id
70
82
  end
71
83
 
72
84
  # Returns the +version+ at the supplied +datetime+ or +time+. It will return +self+ if there is
@@ -89,6 +101,15 @@ module Hoardable
89
101
  version.is_a?(version_class) ? version.revert! : self
90
102
  end
91
103
 
104
+ # Returns the +hoardable_source_id+ that represents the original {SourceModel} record’s ID. Will
105
+ # return nil if the current {SourceModel} record is not an instance of a {VersionModel} cast as
106
+ # {SourceModel}.
107
+ #
108
+ # @return [Integer, nil]
109
+ def hoardable_source_id
110
+ hoardable_client.hoardable_version_source_id || id
111
+ end
112
+
92
113
  delegate :version_class, to: :class
93
114
 
94
115
  private
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Hoardable
4
- VERSION = '0.8.0'
4
+ VERSION = '0.9.1'
5
5
  end
@@ -113,17 +113,17 @@ module Hoardable
113
113
  _data&.dig('changes')
114
114
  end
115
115
 
116
- # Returns the foreign reference that represents the source model of the version.
117
- def hoardable_source_foreign_id
118
- @hoardable_source_foreign_id ||= public_send(:hoardable_source_id)
116
+ # Returns the ID of the {SourceModel} that created this {VersionModel}
117
+ def hoardable_source_id
118
+ read_attribute('hoardable_source_id')
119
119
  end
120
120
 
121
121
  private
122
122
 
123
123
  def insert_untrashed_source
124
124
  superscope = self.class.superclass.unscoped
125
- superscope.insert(hoardable_source_attributes.merge('id' => hoardable_source_foreign_id))
126
- superscope.find(hoardable_source_foreign_id)
125
+ superscope.insert(hoardable_source_attributes.merge('id' => hoardable_source_id))
126
+ superscope.find(hoardable_source_id)
127
127
  end
128
128
 
129
129
  def hoardable_source_attributes
data/lib/hoardable.rb CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  require_relative 'hoardable/version'
4
4
  require_relative 'hoardable/hoardable'
5
- require_relative 'hoardable/tableoid'
5
+ require_relative 'hoardable/scopes'
6
6
  require_relative 'hoardable/error'
7
7
  require_relative 'hoardable/database_client'
8
8
  require_relative 'hoardable/source_model'
@@ -10,3 +10,4 @@ require_relative 'hoardable/version_model'
10
10
  require_relative 'hoardable/model'
11
11
  require_relative 'hoardable/associations'
12
12
  require_relative 'generators/hoardable/migration_generator'
13
+ require_relative 'generators/hoardable/initializer_generator'
data/sig/hoardable.rbs CHANGED
@@ -1,7 +1,7 @@
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, :return_everything, :warn_on_missing_created_at_column]
4
+ CONFIG_KEYS: [:enabled, :version_updates, :save_trash, :warn_on_missing_created_at_column]
5
5
  VERSION_CLASS_SUFFIX: String
6
6
  VERSION_TABLE_SUFFIX: String
7
7
  DURING_QUERY: String
@@ -10,12 +10,14 @@ module Hoardable
10
10
  HOARDABLE_VERSION_UPDATES: ^(untyped) -> untyped
11
11
  self.@context: Hash[untyped, untyped]
12
12
  self.@config: untyped
13
+ self.@at: nil
13
14
  self.@logger: untyped
14
15
 
15
16
  def self.with: (untyped hash) -> untyped
17
+ def self.at: (untyped datetime) -> untyped
16
18
  def self.logger: -> untyped
17
19
 
18
- module Tableoid
20
+ module Scopes
19
21
  TABLEOID_AREL_CONDITIONS: Proc
20
22
 
21
23
  private
@@ -29,10 +31,14 @@ module Hoardable
29
31
  end
30
32
 
31
33
  class DatabaseClient
32
- attr_reader source_model: SourceModel
33
- def initialize: (SourceModel source_model) -> void
34
+ @hoardable_version_source_id: untyped
35
+
36
+ attr_reader source_record: SourceModel
37
+ def initialize: (SourceModel source_record) -> void
34
38
  def insert_hoardable_version: (untyped operation) -> untyped
35
39
  def find_or_initialize_hoardable_event_uuid: -> untyped
40
+ def hoardable_version_source_id: -> untyped
41
+ def query_hoardable_version_source_id: -> untyped
36
42
  def initialize_version_attributes: (untyped operation) -> untyped
37
43
  def initialize_temporal_range: -> Range
38
44
  def initialize_hoardable_data: -> untyped
@@ -44,29 +50,35 @@ module Hoardable
44
50
  end
45
51
 
46
52
  module SourceModel
47
- include Tableoid
53
+ include Scopes
48
54
  @hoardable_client: DatabaseClient
49
55
 
50
56
  attr_reader hoardable_version: untyped
51
57
  def trashed?: -> untyped
58
+ def version?: -> untyped
52
59
  def at: (untyped datetime) -> SourceModel
53
60
  def revert_to!: (untyped datetime) -> SourceModel?
61
+ def hoardable_source_id: -> untyped
54
62
 
55
63
  private
56
64
  def hoardable_client: -> DatabaseClient
57
65
 
58
66
  public
59
67
  def version_class: -> untyped
68
+ def hoardable: -> untyped
69
+
70
+ module FinderMethods
71
+ def find_one: (untyped id) -> untyped
72
+ end
60
73
  end
61
74
 
62
75
  module VersionModel
63
- @hoardable_source_foreign_id: untyped
64
76
  @hoardable_source_attributes: untyped
65
77
 
66
78
  def revert!: -> untyped
67
79
  def untrash!: -> untyped
68
80
  def changes: -> untyped
69
- def hoardable_source_foreign_id: -> untyped
81
+ def hoardable_source_id: -> untyped
70
82
 
71
83
  private
72
84
  def insert_untrashed_source: -> untyped
@@ -88,6 +100,17 @@ module Hoardable
88
100
 
89
101
  module Associations
90
102
  def belongs_to_trashable: (untyped name, ?nil scope, **untyped) -> untyped
103
+ def has_many_hoardable: (untyped name, ?nil scope, **untyped) -> untyped
104
+
105
+ module HasManyScope
106
+ @scope: untyped
107
+ @association: bot
108
+
109
+ def scope: -> untyped
110
+
111
+ private
112
+ def hoardable_scope: -> untyped
113
+ end
91
114
  end
92
115
 
93
116
  class MigrationGenerator
@@ -98,4 +121,8 @@ module Hoardable
98
121
  def migration_template_name: -> String
99
122
  def singularized_table_name: -> untyped
100
123
  end
124
+
125
+ class InitializerGenerator
126
+ def create_initializer_file: -> untyped
127
+ end
101
128
  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.8.0
4
+ version: 0.9.1
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-10-01 00:00:00.000000000 Z
11
+ date: 2022-10-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -104,6 +104,7 @@ files:
104
104
  - LICENSE.txt
105
105
  - README.md
106
106
  - Rakefile
107
+ - lib/generators/hoardable/initializer_generator.rb
107
108
  - lib/generators/hoardable/migration_generator.rb
108
109
  - lib/generators/hoardable/templates/migration.rb.erb
109
110
  - lib/generators/hoardable/templates/migration_6.rb.erb
@@ -113,8 +114,8 @@ files:
113
114
  - lib/hoardable/error.rb
114
115
  - lib/hoardable/hoardable.rb
115
116
  - lib/hoardable/model.rb
117
+ - lib/hoardable/scopes.rb
116
118
  - lib/hoardable/source_model.rb
117
- - lib/hoardable/tableoid.rb
118
119
  - lib/hoardable/version.rb
119
120
  - lib/hoardable/version_model.rb
120
121
  - sig/hoardable.rbs