paper_trail-association_tracking 2.2.1 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3b49b412d6cd431cd4310dadde716d334231225fed80e84c5d4d8696f42fcb0f
4
- data.tar.gz: a77500b35d0f66a1840272b8efd9891ce876da341756fe47077cd1257e4f26b2
3
+ metadata.gz: 5a94904cbcb068a832c7aee7d04d63750631a0dddc282da68665c98cf053baed
4
+ data.tar.gz: bfb10257058405a0b4e99a555724d53b01cc050d18c6f00fb27979f8c415ded9
5
5
  SHA512:
6
- metadata.gz: dff6c0eacc9cf46bb6ed00edbed900426ac3b842b7e5046bb9511422b44d78bb88782d7ffc4c4322c40e28426ee0cc2c3c4fdcd7630f0c0ca4b294dabaa9f815
7
- data.tar.gz: 41c42f324a608af7c22d7b442827eedf15f4d6c79e0c023eb93adc99f177076a95b84c7dc18acdf8f8a3f0d3a9726378d542d18f02b8bc92a3a18092d9e792d2
6
+ metadata.gz: e52ddb1d136efd024b7b138dd5e2bb4676ec1f77fd6f20aeb54048e7d886e560681bac88fec4fbf1216af7aa27dc7eb485e02f5b6623a402b903de6a91cbcd8a
7
+ data.tar.gz: 5a2b6bbc604f5637ffa8758411874af0ac8c1c4a6b80f5d4f595e2c01e41399d64b69b608a1e83c6137c78373123a2078aa137749b5b24b8ef72d6d201f0dbbf
data/CHANGELOG.md CHANGED
@@ -1,22 +1,27 @@
1
1
  # CHANGELOG
2
2
 
3
- ### Unreleased - [View Diff](https://github.com/westonganger/paper_trail-association_tracking/compare/v2.2.1...master)
4
- - Nothing yet
3
+ ### Unreleased - [View Diff](https://github.com/westonganger/paper_trail-association_tracking/compare/v2.3.0...master)
4
+ - Nothing yet
5
5
 
6
- ### v2.2.1 - [View Diff](https://github.com/westonganger/paper_trail-association_tracking/compare/v2.2.0...v2.2.1)
6
+ ### v2.3.0 - 2025-04-17 - [View Diff](https://github.com/westonganger/paper_trail-association_tracking/compare/v2.2.1...v2.3.0)
7
+ - [#46](https://github.com/westonganger/paper_trail-association_tracking/pull/46) - Add support for custom version association class with separate database connection
8
+ - [#49](https://github.com/westonganger/paper_trail-association_tracking/pull/49) - Fix has_many though associations when the through association is singular
9
+ - [#48](https://github.com/westonganger/paper_trail-association_tracking/pull/48) - Fix belongs_to polymorphic associations with "empty string" type
10
+
11
+ ### v2.2.1 - 2022-03-28 - [View Diff](https://github.com/westonganger/paper_trail-association_tracking/compare/v2.2.0...v2.2.1)
7
12
  - [PR #38](https://github.com/westonganger/paper_trail-association_tracking/pull/38) - Fix the issue where reifying has_one association with `dependent: :destroy` could destroy a live record
8
13
 
9
- ### v2.2.0 - [View Diff](https://github.com/westonganger/paper_trail-association_tracking/compare/v2.1.3...v2.2.0)
14
+ ### v2.2.0 - 2022-03-14 - [View Diff](https://github.com/westonganger/paper_trail-association_tracking/compare/v2.1.3...v2.2.0)
10
15
 
11
16
  - [PR #36](https://github.com/westonganger/paper_trail-association_tracking/pull/36) - Fix load order for paper_trail v12+
12
17
  - Drop support for Ruby 2.5
13
18
  - Add Github Actions CI supporting multiple version of Ruby, Rails and multiple databases types
14
19
 
15
- ### 2.1.3 - [View Diff](https://github.com/westonganger/paper_trail-association_tracking/compare/v2.1.1...v2.1.3)
20
+ ### 2.1.3 - 2021-04-20 - [View Diff](https://github.com/westonganger/paper_trail-association_tracking/compare/v2.1.1...v2.1.3)
16
21
 
17
22
  - [PR #24](https://github.com/westonganger/paper_trail-association_tracking/pull/24) - Fix reification on STI models that have parent child relationships
18
23
 
19
- ### 2.1.2
24
+ ### 2.1.2 - 2021-04-20
20
25
 
21
26
  - A late night oopsies, Release yanked immediately, had bug preventing installation.
22
27
 
data/README.md CHANGED
@@ -1,30 +1,32 @@
1
1
  # PaperTrail-AssociationTracking
2
2
 
3
3
  <a href="https://badge.fury.io/rb/paper_trail-association_tracking" target="_blank"><img height="21" style='border:0px;height:21px;' border='0' src="https://badge.fury.io/rb/paper_trail-association_tracking.svg" alt="Gem Version"></a>
4
- <a href='https://github.com/westonganger/paper_trail-association_tracking/actions' target='_blank'><img src="https://github.com/westonganger/paper_trail-association_tracking/workflows/Tests/badge.svg" style="max-width:100%;" height='21' style='border:0px;height:21px;' border='0' alt="CI Status"></a>
5
- <a href='https://rubygems.org/gems/paper_trail-association_tracking' target='_blank'><img height='21' style='border:0px;height:21px;' src='https://ruby-gem-downloads-badge.herokuapp.com/paper_trail-association_tracking?label=rubygems&type=total&total_label=downloads&color=brightgreen' border='0' alt='RubyGems Downloads' /></a>
4
+ <a href='https://github.com/westonganger/paper_trail-association_tracking/actions' target='_blank'><img src="https://github.com/westonganger/paper_trail-association_tracking/actions/workflows/test.yml/badge.svg?branch=master" style="max-width:100%;" height='21' style='border:0px;height:21px;' border='0' alt="CI Status"></a>
5
+ <a href='https://rubygems.org/gems/paper_trail-association_tracking' target='_blank'><img height='21' style='border:0px;height:21px;' src='https://img.shields.io/gem/dt/paper_trail-association_tracking?color=brightgreen&label=Rubygems%20Downloads' border='0' alt='RubyGems Downloads' /></a>
6
6
 
7
- Plugin for the [PaperTrail](https://github.com/paper-trail-gem/paper_trail.git) gem to track and reify associations. This gem was extracted from PaperTrail for v9.2.0 to simplify things in PaperTrail and association tracking separately.
7
+ Plugin for the [PaperTrail](https://github.com/paper-trail-gem/paper_trail.git) gem to track and reify associations. This gem was extracted from PaperTrail for v9.2.0 to simplify things in PaperTrail and association tracking separately.
8
8
 
9
9
  **PR's will happily be accepted**
10
10
 
11
- PaperTrail-AssociationTracking can restore three types of associations: Has-One, Has-Many, and Has-Many-Through.
11
+ PaperTrail-AssociationTracking can restore three types of associations: Has-One, Has-Many, and Has-Many-Through.
12
12
 
13
13
  It will store in the `version_associations` table additional information to correlate versions of the association and versions of the model when the associated record is changed. When reifying the model, it will utilize this table, together with the `transaction_id` to find the correct version of the association and reify it. The `transaction_id` is a unique id for version records created in the same transaction. It is used to associate the version of the model and the version of the association that are created in the same transaction.
14
14
 
15
-
16
-
17
-
18
15
  ## Table of Contents
19
16
 
17
+ - [Alternative Solution](#alternative-solution)
20
18
  - [Install](#install)
21
19
  - [Usage](#usage)
22
20
  - [Limitations](#limitations)
23
21
  - [Known Issues](#known-issues)
24
22
  - [Contributing](#contributing)
25
23
  - [Credits](#credits)
26
- - [Alternative Solution](#alternative-solution)
27
24
 
25
+ # Alternative Solution
26
+
27
+ Model versioning and restoration require concious thought, design, and understanding. You should understand your versioning and restoration process completely. This gem paper_trail-association-tracking is mostly a blackbox solution which encourages you to set it up and then assume its Just Working<sup>TM</sup>. This can make for major data problems later.
28
+
29
+ Instead I recommend a newer gem that I have created for handling snapshots of records and associations called [active_snapshot](https://github.com/westonganger/active_snapshot). This gem does not utilize `paper_trail` at all. The focus of the [active_snapshot](https://github.com/westonganger/active_snapshot) gem is to have a simple and fully understandable design is easy to customize and know inside and out for your projects needs.
28
30
 
29
31
  # Install
30
32
 
@@ -67,7 +69,7 @@ product = Product.first.versions.last.reify(has_many: true, has_one: true, belon
67
69
  product.save! ### now this will also save all reified photos
68
70
  ```
69
71
 
70
- If you do not set `autosave: true` true on the association then you will have to save/delete them manually.
72
+ If you do not set `autosave: true` true on the association then you will have to save/delete them manually.
71
73
 
72
74
  For example:
73
75
 
@@ -119,6 +121,21 @@ t.amount # 100
119
121
  t.location.latitude # 12.345, instead of 54.321
120
122
  ```
121
123
 
124
+ # Configuration
125
+
126
+ You can configure a different version association class by using the following configuration:
127
+
128
+ ```ruby
129
+ class ProductionVersionAssociation < PaperTrail::VersionAssociation
130
+ # You can change the table name, i.e.:
131
+ self.table_name = "product_version_associations"
132
+ end
133
+
134
+ class Product < ActiveRecord::Base
135
+ has_paper_trail version_associations: { class_name: "ProductVersionAssociation" }
136
+ end
137
+ ```
138
+
122
139
  # Limitations
123
140
 
124
141
  1. Only reifies the first level of associations. If you want to include nested associations simply add `:through` relationships to your model.
@@ -143,14 +160,14 @@ t.location.latitude # 12.345, instead of 54.321
143
160
  has_many :books, through: :authorships
144
161
  has_paper_trail
145
162
  end
146
-
163
+
147
164
  ### Each of the following will store authorship versions:
148
165
  @book.authors << @john
149
166
  @book.authors.create(name: 'Jack')
150
167
  @book.authorships.last.destroy
151
168
  @book.authorships.clear
152
169
  @book.author_ids = [@john.id, @joe.id]
153
-
170
+
154
171
  ### But none of these will:
155
172
  @book.authors.delete @john
156
173
  @book.author_ids = []
@@ -166,14 +183,6 @@ t.location.latitude # 12.345, instead of 54.321
166
183
  1. Not compatible with transactional tests, see [PT Issue #542](https://github.com/airblade/paper_trail/issues/542). However, apparently there has been some success by using the [transactional_capybara](https://rubygems.org/gems/transactional_capybara) gem.
167
184
 
168
185
 
169
- # Contributing
170
-
171
- We use the `appraisal` gem for testing multiple versions of `paper_trail` and `activerecord`. Please use the following steps to test using `appraisal`.
172
-
173
- 1. `bundle exec appraisal install`
174
- 2. `bundle exec appraisal rake test`
175
-
176
-
177
186
  # Credits
178
187
 
179
188
  Maintained by [Weston Ganger](https://westonganger.com) - [@westonganger](https://github.com/westonganger)
@@ -181,9 +190,3 @@ Maintained by [Weston Ganger](https://westonganger.com) - [@westonganger](https:
181
190
  Plugin authored by [Weston Ganger](https://westonganger.com) - [@westonganger](https://github.com/westonganger)
182
191
 
183
192
  Associations code originally contributed by Ben Atkins, Jared Beck, Andy Stewart & more
184
-
185
- # Alternative Solution
186
-
187
- Model Versioning and Restoration require concious thought, design, and understanding. You should understand your versioning and restoration process completely. Because PT-AT it is mostly a blackbox solution which encourages you to set it up and then assume its "Just Working". This can make for major data problems later.
188
-
189
- Instead I recommend a newer gem that I have created for handling snapshots of records and associations called [active_snapshot](https://github.com/westonganger/active_snapshot). This gem does not utilize `paper_trail` at all. The focus of this gem is to have a simple and fully understandable design is easy to customize and know inside and out for your projects needs.
data/Rakefile CHANGED
@@ -1,31 +1,16 @@
1
1
  require "bundler"
2
2
  Bundler::GemHelper.install_tasks
3
3
 
4
- desc "Set a relevant database.yml for testing"
5
- task :prepare do
6
- ENV["DB"] ||= "sqlite"
7
- FileUtils.cp(
8
- "spec/dummy_app/config/database.#{ENV['DB']}.yml",
9
- "spec/dummy_app/config/database.yml"
10
- )
11
- end
4
+ require "rspec/core/rake_task"
5
+ RSpec::Core::RakeTask.new(:spec)
12
6
 
13
- require "rake/testtask"
14
- desc "Run tests on PaperTrail with Test::Unit."
15
- Rake::TestTask.new(:test) do |t|
16
- t.libs << "lib"
17
- t.libs << "test"
18
- t.pattern = "test/**/*_test.rb"
19
- t.verbose = false
20
- t.warning = false
21
- end
7
+ task test: [:spec]
22
8
 
23
- require "rspec/core/rake_task"
24
- desc "Run tests on PaperTrail with RSpec"
25
- task(:spec).clear
26
- RSpec::Core::RakeTask.new(:spec) do |t|
27
- t.verbose = false # hide list of specs
28
- end
9
+ task default: [:spec]
10
+
11
+ task :console do
12
+ require "paper_trail-association-tracking"
29
13
 
30
- desc "Default: run all available test suites"
31
- task default: %i[prepare test spec]
14
+ require "irb"
15
+ binding.irb
16
+ end
@@ -10,10 +10,17 @@ module PaperTrailAssociationTracking
10
10
  def setup(options = {})
11
11
  super
12
12
 
13
+ @model_class.class_attribute :version_association_class_name
14
+ @model_class.version_association_class_name = options.dig(:version_associations, :class_name) || "PaperTrail::VersionAssociation"
15
+
13
16
  setup_transaction_callbacks
14
17
  setup_callbacks_for_habtm(options[:join_tables])
15
18
  end
16
19
 
20
+ def version_association_class
21
+ @version_association_class ||= @model_class.version_association_class_name.constantize
22
+ end
23
+
17
24
  private
18
25
 
19
26
  # Raises an error if the provided class is an `abstract_class`.
@@ -133,7 +133,7 @@ module PaperTrailAssociationTracking
133
133
  @record.class.reflect_on_all_associations(:has_and_belongs_to_many).each do |a|
134
134
  next unless save_habtm_association?(a)
135
135
  habtm_assoc_ids(a).each do |id|
136
- ::PaperTrail::VersionAssociation.create(
136
+ @record.class.paper_trail.version_association_class.create(
137
137
  version_id: version.transaction_id,
138
138
  foreign_key_name: a.name,
139
139
  foreign_key_id: id,
@@ -170,7 +170,7 @@ module PaperTrailAssociationTracking
170
170
 
171
171
  if assoc.options[:polymorphic]
172
172
  foreign_type = @record.send(assoc.foreign_type)
173
- if foreign_type && ::PaperTrail.request.enabled_for_model?(foreign_type.constantize)
173
+ if foreign_type.present? && ::PaperTrail.request.enabled_for_model?(foreign_type.constantize)
174
174
  assoc_version_args[:foreign_key_id] = @record.send(assoc.foreign_key)
175
175
  assoc_version_args[:foreign_type] = foreign_type
176
176
  end
@@ -180,7 +180,7 @@ module PaperTrailAssociationTracking
180
180
  end
181
181
 
182
182
  if assoc_version_args.key?(:foreign_key_id)
183
- ::PaperTrail::VersionAssociation.create(assoc_version_args)
183
+ @record.class.paper_trail.version_association_class.create(assoc_version_args)
184
184
  end
185
185
  end
186
186
 
@@ -8,7 +8,7 @@ module PaperTrailAssociationTracking
8
8
  class << self
9
9
  # @api private
10
10
  def reify(pt_enabled, assoc, model, options, transaction_id)
11
- version_ids = ::PaperTrail::VersionAssociation.
11
+ version_ids = model.class.paper_trail.version_association_class.
12
12
  where("foreign_key_name = ?", assoc.name).
13
13
  where("version_id = ?", transaction_id).
14
14
  pluck(:foreign_key_id)
@@ -100,7 +100,7 @@ module PaperTrailAssociationTracking
100
100
  .select { |x| x <= model.class.base_class && x.method_defined?(assoc.name) }
101
101
  .map(&:name)
102
102
 
103
- version_ids = ::PaperTrail::VersionAssociation.
103
+ version_ids = model.class.paper_trail.version_association_class.
104
104
  joins(model.class.version_association_name).
105
105
  select("MIN(version_id) as version_id").
106
106
  where("foreign_key_name = ?", assoc.foreign_key).
@@ -11,7 +11,7 @@ module PaperTrailAssociationTracking
11
11
  # Load the collection of through-models. For example, if `model` is a
12
12
  # Chapter, having many Paragraphs through Sections, then
13
13
  # `through_collection` will contain Sections.
14
- through_collection = model.send(assoc.options[:through])
14
+ through_collection = through_collection(assoc, model, options, transaction_id)
15
15
 
16
16
  # Now, given the collection of "through" models (e.g. sections), load
17
17
  # the collection of "target" models (e.g. paragraphs)
@@ -24,6 +24,27 @@ module PaperTrailAssociationTracking
24
24
 
25
25
  private
26
26
 
27
+ # Examine the `through_reflection`, i.e., the "through:" option on the association.
28
+ #
29
+ # @api private
30
+ def through_collection(assoc, model, options, transaction_id)
31
+ through_reflection = assoc.through_reflection
32
+ # If the through association is has_many, we can just return the reified association
33
+ return model.send(assoc.options[:through]) if through_reflection.collection?
34
+
35
+ # If the model wasn't reified with belongs_to: true/has_one: true, then
36
+ # the through association hasn't been reified yet.
37
+ unless model.association(assoc.options[:through]).loaded?
38
+ if through_reflection.belongs_to?
39
+ BelongsTo.reify(through_reflection, model, options, transaction_id)
40
+ else
41
+ HasOne.reify(through_reflection, model, options, transaction_id)
42
+ end
43
+ end
44
+ # Wrap the association in a collection for `collection_through_has_many`
45
+ [*model.send(assoc.options[:through])]
46
+ end
47
+
27
48
  # Examine the `source_reflection`, i.e. the "source" of `assoc` the
28
49
  # `ThroughReflection`. The source can be a `BelongsToReflection`
29
50
  # or a `HasManyReflection`.
@@ -90,13 +90,17 @@ module PaperTrailAssociationTracking
90
90
  # @api private
91
91
  def load_versions(assoc, model, transaction_id, version_at, base_class_name)
92
92
  version_table_name = model.class.paper_trail.version_class.table_name
93
- model.class.paper_trail.version_class.joins(:version_associations).
94
- where("version_associations.foreign_key_name = ?", assoc.foreign_key).
95
- where("version_associations.foreign_key_id = ?", model.id).
93
+
94
+ version_ids = model.class.paper_trail.version_association_class.
95
+ joins(model.class.version_association_name).
96
+ where("foreign_key_name = ?", assoc.foreign_key).
97
+ where("foreign_key_id = ?", model.id).
96
98
  where("#{version_table_name}.item_type = ?", base_class_name).
97
99
  where("created_at >= ? OR transaction_id = ?", version_at, transaction_id).
98
- order("#{version_table_name}.id ASC").
99
- load
100
+ order("version_id ASC").
101
+ pluck("version_id")
102
+
103
+ model.class.paper_trail.version_class.find(version_ids)
100
104
  end
101
105
 
102
106
  # @api private
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PaperTrailAssociationTracking
4
- VERSION = "2.2.1".freeze
4
+ VERSION = "2.3.0".freeze
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: paper_trail-association_tracking
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.1
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Weston Ganger
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2022-03-29 00:00:00.000000000 Z
13
+ date: 2025-04-17 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: paper_trail
@@ -26,48 +26,6 @@ dependencies:
26
26
  - - ">="
27
27
  - !ruby/object:Gem::Version
28
28
  version: '12.0'
29
- - !ruby/object:Gem::Dependency
30
- name: appraisal
31
- requirement: !ruby/object:Gem::Requirement
32
- requirements:
33
- - - ">="
34
- - !ruby/object:Gem::Version
35
- version: '0'
36
- type: :development
37
- prerelease: false
38
- version_requirements: !ruby/object:Gem::Requirement
39
- requirements:
40
- - - ">="
41
- - !ruby/object:Gem::Version
42
- version: '0'
43
- - !ruby/object:Gem::Dependency
44
- name: byebug
45
- requirement: !ruby/object:Gem::Requirement
46
- requirements:
47
- - - ">="
48
- - !ruby/object:Gem::Version
49
- version: '0'
50
- type: :development
51
- prerelease: false
52
- version_requirements: !ruby/object:Gem::Requirement
53
- requirements:
54
- - - ">="
55
- - !ruby/object:Gem::Version
56
- version: '0'
57
- - !ruby/object:Gem::Dependency
58
- name: ffaker
59
- requirement: !ruby/object:Gem::Requirement
60
- requirements:
61
- - - ">="
62
- - !ruby/object:Gem::Version
63
- version: '0'
64
- type: :development
65
- prerelease: false
66
- version_requirements: !ruby/object:Gem::Requirement
67
- requirements:
68
- - - ">="
69
- - !ruby/object:Gem::Version
70
- version: '0'
71
29
  - !ruby/object:Gem::Dependency
72
30
  name: generator_spec
73
31
  requirement: !ruby/object:Gem::Requirement
@@ -82,20 +40,6 @@ dependencies:
82
40
  - - ">="
83
41
  - !ruby/object:Gem::Version
84
42
  version: '0'
85
- - !ruby/object:Gem::Dependency
86
- name: rack-test
87
- requirement: !ruby/object:Gem::Requirement
88
- requirements:
89
- - - ">="
90
- - !ruby/object:Gem::Version
91
- version: '0'
92
- type: :development
93
- prerelease: false
94
- version_requirements: !ruby/object:Gem::Requirement
95
- requirements:
96
- - - ">="
97
- - !ruby/object:Gem::Version
98
- version: '0'
99
43
  - !ruby/object:Gem::Dependency
100
44
  name: rake
101
45
  requirement: !ruby/object:Gem::Requirement
@@ -124,20 +68,6 @@ dependencies:
124
68
  - - ">="
125
69
  - !ruby/object:Gem::Version
126
70
  version: '0'
127
- - !ruby/object:Gem::Dependency
128
- name: sqlite3
129
- requirement: !ruby/object:Gem::Requirement
130
- requirements:
131
- - - ">="
132
- - !ruby/object:Gem::Version
133
- version: '0'
134
- type: :development
135
- prerelease: false
136
- version_requirements: !ruby/object:Gem::Requirement
137
- requirements:
138
- - - ">="
139
- - !ruby/object:Gem::Version
140
- version: '0'
141
71
  - !ruby/object:Gem::Dependency
142
72
  name: timecop
143
73
  requirement: !ruby/object:Gem::Requirement
@@ -205,7 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
205
135
  - !ruby/object:Gem::Version
206
136
  version: '0'
207
137
  requirements: []
208
- rubygems_version: 3.2.32
138
+ rubygems_version: 3.4.22
209
139
  signing_key:
210
140
  specification_version: 4
211
141
  summary: Plugin for the PaperTrail gem to track and reify associations