paper_trail-association_tracking 1.1.0 → 2.1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 844d3ff1eb96a7bae834ad57625e2fb87cf37ebbea76bd489621a31c2a57d6f7
4
- data.tar.gz: 0cd147df0a5ee52494abcda09e0fc44c10ebae176cc567a3659debb7533ad72c
3
+ metadata.gz: 51f0ba0d9f3c256f374002822d5f7e88444b6be465dd2189c8107d90160ed457
4
+ data.tar.gz: 046c163be73401cc97d593b48fc8a6fb91e09480303c6ab00df3f7818fc25ddd
5
5
  SHA512:
6
- metadata.gz: b49a595381d282b2ace65a18405921fba2970a22dde79841b5b7e42d148392b37caac9323136721cbebb9e0f0b74962d333e38883f923a934bb599b54dcf967a
7
- data.tar.gz: '0180dff00868dfb4e49be3722df2210c630aa1550cf2963714d445f1b0c7d4eadfc96db258bcf88b4554949720821a33f3f00178b2ee4aeb61c52c26238de047'
6
+ metadata.gz: d0e720740047a827254138caa7d8019d2ca29f5a4ee1a53fd7cc51f93d8a04998f2c8f661415840bc379f4196673347e35656f18fc2c70d14809fd47b9532f6b
7
+ data.tar.gz: dd3e7ecc22c067f5f60fe0fd1d21a7997bb91e62ed39955ac2a337cce83071617d93c2f49ec70f0a6de96c37efe6625041a4b0e3e2c57739c7b2ef30bbe135c9
data/CHANGELOG.md CHANGED
@@ -1,14 +1,50 @@
1
1
  # CHANGELOG
2
2
 
3
- ## Unreleased
3
+ ### Unreleased - [View Diff](https://github.com/westonganger/paper_trail-association_tracking/compare/v2.1.1...master)
4
4
 
5
- - None
5
+ - Nothing yet
6
6
 
7
- ## 1.1.0 - 2018-12-28
7
+ ### 2.1.3 - [View Diff](https://github.com/westonganger/paper_trail-association_tracking/compare/v2.1.1...v2.1.3)
8
8
 
9
- - [#10](https://github.com/westonganger/paper_trail-association_tracking/pull/9) - The `has_many: true` option now reifies polymorphic associations. Previously they were skipped.
10
- - [#9](https://github.com/westonganger/paper_trail-association_tracking/pull/9) - The `belongs_to: true` option now reifies polymorphic associations. Previously they were skipped.
9
+ - [PR #24](https://github.com/westonganger/paper_trail-association_tracking/pull/24) - Fix reification on STI models that have parent child relationships
10
+ - Last version that is compatible with `paper_trail` due to the change in the loading mechanism
11
11
 
12
- ## 1.0.0 - 2018-06-04
12
+ ### 2.1.2
13
+
14
+ - Release yanked, had bug preventing installation
15
+
16
+ ### 2.1.1 - 2020-10-21 - [View Diff](https://github.com/westonganger/paper_trail-association_tracking/compare/v2.1.0...v2.1.1)
17
+
18
+ - Bug fix for reify on `has_many :through` relationships when `:source` is specified
19
+ - Bug fix for reify on `has_many :through` relationships where the association is a has_one on the through model
20
+ - Bug fix to ensure install generator will set `PaperTrail.association_tracking = true`
21
+
22
+ ### 2.1.0 - 2020-08-14 - [View Diff](https://github.com/westonganger/paper_trail-association_tracking/compare/v2.0.0...v2.1.0)
23
+
24
+ - [PR #18](https://github.com/westonganger/paper_trail-association_tracking/pull/18) - Improve performance for `Model.reify(has_many: true)` by separating the SQL subquery.
25
+ - [PR #15](https://github.com/westonganger/paper_trail-association_tracking/pull/15) - Recreate `version_associations.foreign_key` index to utilize the new `version_associations.foreign_type` column
26
+ - Update test matrix to support multiple versions of PT-core and ActiveRecord
27
+ - Remove deprecated methods `clear_transaction_id`, `transaction_id` and `transaction_id=`
28
+
29
+ ### 2.0.0 - 2019-01-22 - [View Diff](https://github.com/westonganger/paper_trail-association_tracking/compare/v1.1.1...v2.0.0)
30
+
31
+ - [PR #11](https://github.com/westonganger/paper_trail-association_tracking/issues/11) - Remove null constraint on `version_associations.foreign_type` column which was added in `v1.1.0`. This fixes issues adding the column to existing projects who are upgrading.
32
+ - Add generator `rails g paper_trail_association_tracking:add_foreign_type_to_version_associations` for `versions_associations.foreign_type` column for upgrading applications from `v1.0.0` or earlier.
33
+
34
+ ### How to Upgrade from v1.0.0 or earlier
35
+
36
+ - Run `rails g paper_trail_association_tracking:add_foreign_type_to_version_associations` and then migrate your database.
37
+
38
+ ### 1.1.1 - 2018-01-14 - [View Diff](https://github.com/westonganger/paper_trail-association_tracking/compare/v1.1.0...v1.1.1)
39
+
40
+ - Same as v2 release, this is released simply to maintain a working `v1` branch since `v1.1.0` was broken
41
+
42
+ ### 1.1.0 - 2018-12-28 - [View Diff](https://github.com/westonganger/paper_trail-association_tracking/compare/v1.0.0...v1.1.0)
43
+
44
+ - Note: This release is somewhat broken, please upgrade to `v2.0.0` or stay on `v1.0.0`
45
+ - [PR #10](https://github.com/westonganger/paper_trail-association_tracking/pull/10) - The `has_many: true` option now reifies polymorphic associations. Previously they were skipped.
46
+ - [PR #9](https://github.com/westonganger/paper_trail-association_tracking/pull/9) - The `belongs_to: true` option now reifies polymorphic associations. Previously they were skipped.
47
+
48
+ ### 1.0.0 - 2018-06-04
13
49
 
14
50
  - [PT #1070](https://github.com/paper-trail-gem/paper_trail/issues/1070), [#2](https://github.com/westonganger/paper_trail-association_tracking/issues/2) - Extracted from paper_trail gem in v9.2
data/README.md CHANGED
@@ -1,173 +1,130 @@
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://travis-ci.org/westonganger/paper_trail-association_tracking' target='_blank'><img height='21' style='border:0px;height:21px;' src='https://api.travis-ci.org/westonganger/paper_trail-association_tracking.svg?branch=master' border='0' alt='Build Status' /></a>
4
+ <a href='https://travis-ci.com/westonganger/paper_trail-association_tracking' target='_blank'><img height='21' style='border:0px;height:21px;' src='https://api.travis-ci.com/westonganger/paper_trail-association_tracking.svg?branch=master' border='0' alt='Build Status' /></a>
5
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>
6
6
 
7
- Plugin for the [PaperTrail](https://github.com/paper-trail-gem/paper_trail.git) gem to track and reify associations.
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
- This gem was extracted from PaperTrail in v9.2 to simplify things in PaperTrail and association tracking seperately.
12
- At this time, `paper_trail` has a runtime dependency on this gem and will keep running the existing tests related
13
- to association tracking. This arrangement will be maintained for a few years, if practical.
11
+ PaperTrail-AssociationTracking can restore three types of associations: Has-One, Has-Many, and Has-Many-Through.
12
+
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
- A little history lesson, discussed as early as 2009, and first implemented in late 2014, association
16
- tracking was part of PT core until 2018 as an experimental feature and was use at your own risk. This gem now
17
- maintains a list of known issues and we hope the community can help remove some of them via PR's.
18
15
 
19
- ## Table of Contents
20
16
 
21
- <!-- toc -->
17
+
18
+ ## Table of Contents
22
19
 
23
20
  - [Install](#install)
24
- - [Associations](#associations)
21
+ - [Usage](#usage)
22
+ - [Limitations](#limitations)
25
23
  - [Known Issues](#known-issues)
26
24
  - [Contributing](#contributing)
27
25
  - [Credits](#credits)
28
26
 
29
- <!-- tocstop -->
30
27
 
31
28
  # Install
32
29
 
33
30
  ```ruby
34
31
  # Gemfile
35
32
 
36
- gem 'paper_trail' # Requires v9.2+
33
+ gem 'paper_trail' # Minimum required version is v9.2.0
37
34
  gem 'paper_trail-association_tracking'
38
35
  ```
39
36
 
40
- # Association Tracking
41
-
42
- This plugin currently can restore three types of associations: Has-One, Has-Many, and
43
- Has-Many-Through. In order to do this, you will need to do two things:
37
+ Then run `rails generate paper_trail_association_tracking:install` which will do the following two things for you:
44
38
 
45
39
  1. Create a `version_associations` table
46
- 2. Set `PaperTrail.config.track_associations = true` (e.g. in an initializer)
40
+ 2. Set `PaperTrail.config.track_associations = true` in an initializer
47
41
 
42
+ # Usage
48
43
 
49
- Both will be done for you automatically if you run the PaperTrail-AssociationTracking generator (e.g. `rails generate paper_trail_association_tracking:install`)
44
+ First, ensure that you have added `has_paper_trail` to your main model and all associated models that are to be tracked.
50
45
 
51
- If you want to add this functionality after the initial installation, you will
52
- need to create the `version_associations` table manually, and you will need to
53
- ensure that `PaperTrail.config.track_associations = true` is set.
46
+ To restore associations as they were at the time you must pass any of the following options to the `reify` method.
54
47
 
55
- PaperTrail will store in the `version_associations` table additional information
56
- to correlate versions of the association and versions of the model when the
57
- associated record is changed. When reifying the model, PaperTrail can use this
58
- table, together with the `transaction_id` to find the correct version of the
59
- association and reify it. The `transaction_id` is a unique id for version records
60
- created in the same transaction. It is used to associate the version of the model
61
- and the version of the association that are created in the same transaction.
48
+ - To restore Has-Many and Has-Many-Through associations, use option `has_many: true`
49
+ - To restore Has-One associations , use option `has_one: true` to `reify`
50
+ - To restore Belongs-To associations, use option `belongs_to: true`
62
51
 
63
- To restore Has-One associations as they were at the time, pass option `has_one:
64
- true` to `reify`. To restore Has-Many and Has-Many-Through associations, use
65
- option `has_many: true`. To restore Belongs-To association, use
66
- option `belongs_to: true`. For example:
52
+ For example:
67
53
 
68
54
  ```ruby
69
- class Location < ActiveRecord::Base
70
- belongs_to :treasure
71
- has_paper_trail
72
- end
73
-
74
- class Treasure < ActiveRecord::Base
75
- has_one :location
76
- has_paper_trail
77
- end
78
-
79
- treasure.amount # 100
80
- treasure.location.latitude # 12.345
81
-
82
- treasure.update_attributes amount: 153
83
- treasure.location.update_attributes latitude: 54.321
84
-
85
- t = treasure.versions.last.reify(has_one: true)
86
- t.amount # 100
87
- t.location.latitude # 12.345
55
+ item.versions.last.reify(has_many: true, has_one: true, belongs_to: false)
88
56
  ```
89
57
 
90
- If the parent and child are updated in one go, PaperTrail-AssociationTracking can use the
91
- aforementioned `transaction_id` to reify the models as they were before the
92
- transaction (instead of before the update to the model).
58
+ If you want the reified associations to be saved upon calling `save` on the parent model then you must set `autosave: true` on all required associations. A little tip, `accepts_nested_attributes` automatically sets `autosave` to true but you should probably still state it explicitly.
93
59
 
94
- ```ruby
95
- treasure.amount # 100
96
- treasure.location.latitude # 12.345
60
+ For example:
97
61
 
98
- Treasure.transaction do
99
- treasure.location.update_attributes latitude: 54.321
100
- treasure.update_attributes amount: 153
62
+ ```ruby
63
+ class Product
64
+ has_many :photos, autosave: true
101
65
  end
102
66
 
103
- t = treasure.versions.last.reify(has_one: true)
104
- t.amount # 100
105
- t.location.latitude # 12.345, instead of 54.321
67
+ product = Product.first.versions.last.reify(has_many: true, has_one: true, belongs_to: false)
68
+ product.save! ### now this will also save all reified photos
106
69
  ```
107
70
 
108
- By default, PaperTrail-AssociationTracking excludes an associated record from the reified parent
109
- model if the associated record exists in the live model but did not exist as at
110
- the time the version was created. This is usually what you want if you just want
111
- to look at the reified version. But if you want to persist it, it would be
112
- better to pass in option `mark_for_destruction: true` so that the associated
113
- record is included and marked for destruction. Note that `mark_for_destruction`
114
- only has [an effect on associations marked with `autosave: true`](http://api.rubyonrails.org/classes/ActiveRecord/AutosaveAssociation.html#method-i-mark_for_destruction).
71
+ If you do not set `autosave: true` true on the association then you will have to save/delete them manually.
115
72
 
116
- ```ruby
117
- class Widget < ActiveRecord::Base
118
- has_paper_trail
119
- has_one :wotsit, autosave: true
120
- end
73
+ For example:
121
74
 
122
- class Wotsit < ActiveRecord::Base
75
+ ```ruby
76
+ class Product < ActiveRecord::Base
123
77
  has_paper_trail
124
- belongs_to :widget
78
+ has_many :photos, autosave: false ### or if autosave not set
125
79
  end
126
80
 
127
- widget = Widget.create(name: 'widget_0')
128
- widget.update_attributes(name: 'widget_1')
129
- widget.create_wotsit(name: 'wotsit')
81
+ product = Product.create(name: 'product_0')
82
+ product.photos.create(name: 'photo')
83
+ product.update(name: 'product_a')
84
+ product.photos.create(name: 'photo')
85
+
86
+ reified_product = product.versions.last.reify(has_many: true, mark_for_destruction: true)
87
+ reified_product.save!
88
+ reified_product.name # product_a
89
+ reified_product.photos.size # 2
90
+ reified_product.photos.reload
91
+ reified_product.photos.size # 1 ### bad, didnt save the associations
92
+
93
+ product = Product.create(name: 'product_1')
94
+ product.update(name: 'product_b')
95
+ product.photos.create(name: 'photo')
96
+
97
+ reified_product = product.versions.last.reify(has_many: true, mark_for_destruction: true)
98
+ reified_product.save!
99
+ reified_product.name # product_b
100
+ reified_product.photos.size # 1
101
+ reified_product.photos.each{|x| x.marked_for_destruction? ? x.destroy! : x.save! }
102
+ reified_product.photos.size # 0
103
+ ```
130
104
 
131
- widget_0 = widget.versions.last.reify(has_one: true)
132
- widget_0.wotsit # nil
105
+ It will also respect AR transactions by utilizing the aforementioned `transaction_id` to reify the models as they were before the transaction (instead of before the update to the model).
133
106
 
134
- widget_0 = widget.versions.last.reify(has_one: true, mark_for_destruction: true)
135
- widget_0.wotsit.marked_for_destruction? # true
136
- widget_0.save!
137
- widget.reload.wotsit # nil
138
- ```
107
+ For example:
139
108
 
140
- # Known Issues
109
+ ```ruby
110
+ item.amount # 100
111
+ item.location.latitude # 12.345
141
112
 
142
- Associations have the following known issues, in order of descending importance. Use in Production at your own risk.
113
+ Item.transaction do
114
+ item.location.update(latitude: 54.321)
115
+ item.update(amount: 153)
116
+ end
143
117
 
144
- **PR's for these issues will happily be accepted**
118
+ t = item.versions.last.reify(has_one: true)
119
+ t.amount # 100
120
+ t.location.latitude # 12.345, instead of 54.321
121
+ ```
145
122
 
146
- If you notice anything here that should be updated/removed/edited feel free to create an issue.
123
+ # Limitations
147
124
 
148
- 1. PaperTrail-AssociationTracking only reifies the first level of associations.
149
- 1. Sometimes the has_one association will find more than one possible candidate and will raise a `PaperTrailAssociationTracking::Reifiers::HasOne::FoundMoreThanOne` error. For example, see `spec/models/person_spec.rb`
150
- - If you are not using STI, you may want to just assume the first result (of multiple) is the correct one and continue. PaperTrail <= v8 did this without error or warning. To do so add the following line to your initializer: `PaperTrail.config.association_reify_error_behaviour = :warn`. Valid options are: `[:error, :warn, :ignore]`
151
- - When using STI, even if you enable `:warn` you will likely still end up recieving an `ActiveRecord::AssociationTypeMismatch` error.
152
- 1. Not compatible with [transactional tests](https://github.com/rails/rails/blob/591a0bb87fff7583e01156696fbbf929d48d3e54/activerecord/lib/active_record/fixtures.rb#L142), aka. transactional fixtures. - [PT Issue #542](https://github.com/airblade/paper_trail/issues/542)
153
- 1. Requires database timestamp columns with fractional second precision.
154
- - Sqlite and postgres timestamps have fractional second precision by default.
155
- [MySQL timestamps do not](https://dev.mysql.com/doc/refman/5.6/en/fractional-seconds.html). Furthermore, MySQL 5.5 and earlier do not
156
- support fractional second precision at all.
157
- - Also, support for fractional seconds in MySQL was not added to
158
- rails until ActiveRecord 4.2 (https://github.com/rails/rails/pull/14359).
159
- 1. PaperTrail-AssociationTracking can't restore an association properly if the association record
160
- can be updated to replace its parent model (by replacing the foreign key)
161
- 1. Currently PaperTrail-AssociationTracking only supports a single `version_associations` table.
162
- Therefore, you can only use a single table to store the versions for
163
- all related models. Sorry for those who use multiple version tables.
164
- 1. PaperTrail-AssociationTracking relies on the callbacks on the association model (and the :through
165
- association model for Has-Many-Through associations) to record the versions
166
- and the relationship between the versions. If the association is changed
167
- without invoking the callbacks, Reification won't work. Below are some
168
- examples:
169
-
170
- Given these models:
125
+ 1. Only reifies the first level of associations. If you want to include nested associations simply add `:through` relationships to your model.
126
+ 1. Currently we only supports a single `version_associations` table. Therefore, you can only use a single table to store the versions for all related models.
127
+ 1. Relies on the callbacks on the association model (and the `:through` association model for Has-Many-Through associations) to record the versions and the relationship between the versions. If the association is changed without invoking the callbacks, then reification won't work. Example:
171
128
 
172
129
  ```ruby
173
130
  class Book < ActiveRecord::Base
@@ -187,59 +144,41 @@ If you notice anything here that should be updated/removed/edited feel free to c
187
144
  has_many :books, through: :authorships
188
145
  has_paper_trail
189
146
  end
190
- ```
191
-
192
- Then each of the following will store authorship versions:
193
-
194
- ```ruby
195
- @book.authors << @dostoyevsky
196
- @book.authors.create name: 'Tolstoy'
147
+
148
+ ### Each of the following will store authorship versions:
149
+ @book.authors << @john
150
+ @book.authors.create(name: 'Jack')
197
151
  @book.authorships.last.destroy
198
152
  @book.authorships.clear
199
- @book.author_ids = [@solzhenistyn.id, @dostoyevsky.id]
200
- ```
201
-
202
- But none of these will:
203
-
204
- ```ruby
205
- @book.authors.delete @tolstoy
153
+ @book.author_ids = [@john.id, @joe.id]
154
+
155
+ ### But none of these will:
156
+ @book.authors.delete @john
206
157
  @book.author_ids = []
207
158
  @book.authors = []
208
159
  ```
209
160
 
210
- Having said that, you can apparently get all these working (I haven't tested it
211
- myself) with this patch:
212
-
213
- ```ruby
214
- # config/initializers/active_record_patch.rb
215
-
216
- class HasManyThroughAssociationPatch
217
- def delete_records(records, method)
218
- method ||= :destroy
219
- super
220
- end
221
- end
222
-
223
- ActiveRecord::Associations::HasManyThroughAssociation.prepend(HasManyThroughAssociationPatch)
224
- ```
225
161
 
226
- See [PT Issue #113](https://github.com/paper-trail-gem/paper_trail/issues/113) for a discussion about this.
162
+ # Known Issues
227
163
 
164
+ 1. Sometimes the has_one association will find more than one possible candidate and will raise a `PaperTrailAssociationTracking::Reifiers::HasOne::FoundMoreThanOne` error. For example, see `spec/models/person_spec.rb`
165
+ - If you are not using STI, you may want to just assume the first result of multiple is the correct one and continue. PaperTrail <= v8 did this without error or warning. To do so add the following line to your initializer: `PaperTrail.config.association_reify_error_behaviour = :warn`. Valid options are: `[:error, :warn, :ignore]`
166
+ - When using STI, even if you enable `:warn` you will likely still end up recieving an `ActiveRecord::AssociationTypeMismatch` error. See [PT Issue #594](https://github.com/airblade/paper_trail/issues/594). I strongly recommend that you do not use STI, however if you do need to decide to use STI, please see https://github.com/paper-trail-gem/paper_trail#4b1-the-optional-item_subtype-column
167
+ 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.
228
168
 
229
- ### Regarding ActiveRecord Single Table Inheritance (STI)
230
169
 
231
- At this time during `reify` any STI `has_one` associations will raise a `PaperTrailAssociationTracking::Reifiers::HasOne::FoundMoreThanOne` error. See [PT Issue #594](https://github.com/airblade/paper_trail/issues/594)
170
+ # Contributing
232
171
 
233
- Something to note though, is while the PaperTrail gem supports [Single Table Inheritance](http://api.rubyonrails.org/classes/ActiveRecord/Base.html#class-ActiveRecord::Base-label-Single+table+inheritance), I do NOT recommend STI ever. Your better off rolling your own solution rather than using STI.
172
+ We use the `appraisal` gem for testing multiple versions of `paper_trail` and `activerecord`. Please use the following steps to test using `appraisal`.
234
173
 
235
- # Contributing
174
+ 1. `bundle exec appraisal install`
175
+ 2. `bundle exec appraisal rake test`
236
176
 
237
- See the paper_trail [contribution guidelines](https://github.com/paper-trail-gem/paper_trail/blob/master/.github/CONTRIBUTING.md)
238
177
 
239
178
  # Credits
240
179
 
241
- Plugin authored by [Weston Ganger](https://github.com/westonganger) & Jared Beck
180
+ Maintained by [Weston Ganger](https://westonganger.com) - [@westonganger](https://github.com/westonganger)
242
181
 
243
- Maintained by [Weston Ganger](https://github.com/westonganger) & [Jared Beck](https://github.com/jaredbeck)
182
+ Plugin authored by [Weston Ganger](https://westonganger.com) - [@westonganger](https://github.com/westonganger)
244
183
 
245
184
  Associations code originally contributed by Ben Atkins, Jared Beck, Andy Stewart & more
data/Rakefile CHANGED
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  require "bundler"
4
2
  Bundler::GemHelper.install_tasks
5
3
 
@@ -20,9 +18,8 @@ Rake::TestTask.new(:test) do |t|
20
18
  t.pattern = "test/**/*_test.rb"
21
19
  t.verbose = false
22
20
 
23
- # Enabling ruby interpreter warnings (-w) is, sadly, impractical. There are
24
- # too many noisy warnings that we have no control over, e.g. caused by libs we
25
- # depend on.
21
+ ### Enabling ruby interpreter warnings (-w) is, sadly, impractical.
22
+ ### There are too many noisy warnings that we have no control over, e.g. caused by libs we depend on.
26
23
  t.warning = false
27
24
  end
28
25
 
@@ -33,29 +30,5 @@ RSpec::Core::RakeTask.new(:spec) do |t|
33
30
  t.verbose = false # hide list of specs bit.ly/1nVq3Jn
34
31
  end
35
32
 
36
- task :autocorrect do
37
- rules = [
38
- 'FrozenStringLiteralComment',
39
- 'Layout/EmptyLineAfterMagicComment',
40
- 'Layout/EmptyLinesAroundBlockBody',
41
- 'Layout/EmptyLinesAroundClassBody',
42
- 'Layout/EmptyLinesAroundMethodBody',
43
- 'Layout/EmptyLinesAroundModuleBody',
44
- 'Layout/TrailingWhitespace',
45
- 'Style/EmptyMethod',
46
- 'Style/TrailingCommaInArguments',
47
- ]
48
-
49
- rules.each do |rule|
50
- `bundle exec rubocop --auto-correct --only #{rule}`
51
- end
52
-
53
- Rake::Task['rubocop'].invoke
54
- end
55
-
56
- require "rubocop/rake_task"
57
- RuboCop::RakeTask.new
58
-
59
- ### TODO: Allow rubocop to fail, but still continue
60
33
  desc "Default: run all available test suites"
61
34
  task default: %i[prepare test spec]
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+ require "rails/generators/active_record"
5
+
6
+ module PaperTrailAssociationTracking
7
+ # Installs PaperTrail in a rails app.
8
+ class AddForeignTypeToVersionAssociationsGenerator < ::Rails::Generators::Base
9
+ include ::Rails::Generators::Migration
10
+
11
+ # Class names of MySQL adapters.
12
+ # - `MysqlAdapter` - Used by gems: `mysql`, `activerecord-jdbcmysql-adapter`.
13
+ # - `Mysql2Adapter` - Used by `mysql2` gem.
14
+ MYSQL_ADAPTERS = [
15
+ "ActiveRecord::ConnectionAdapters::MysqlAdapter",
16
+ "ActiveRecord::ConnectionAdapters::Mysql2Adapter"
17
+ ].freeze
18
+
19
+ source_root File.expand_path("../templates", __FILE__)
20
+
21
+ desc "Generates (but does not run) a migration to add a the foreign_type column to the version_associations table after upgrading from v1.0 or earlier."
22
+
23
+ def create_migrations
24
+ add_paper_trail_migration("add_foreign_type_to_version_associations")
25
+ end
26
+
27
+ def self.next_migration_number(dirname)
28
+ ::ActiveRecord::Generators::Base.next_migration_number(dirname)
29
+ end
30
+
31
+ protected
32
+
33
+ def add_paper_trail_migration(template)
34
+ migration_dir = File.expand_path("db/migrate")
35
+ if self.class.migration_exists?(migration_dir, template)
36
+ ::Kernel.warn "Migration already exists: #{template}"
37
+ else
38
+ migration_template(
39
+ "#{template}.rb.erb",
40
+ "db/migrate/#{template}.rb",
41
+ migration_version: migration_version
42
+ )
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ def migration_version
49
+ "[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
50
+ end
51
+ end
52
+ end
@@ -28,7 +28,7 @@ module PaperTrailAssociationTracking
28
28
  def create_initializer
29
29
  create_file(
30
30
  "config/initializers/paper_trail.rb",
31
- "PaperTrail.config.track_associations = #{!!options.with_associations?}\n",
31
+ "PaperTrail.config.track_associations = true\n",
32
32
  "PaperTrail.config.association_reify_error_behaviour = :error"
33
33
  )
34
34
  end
@@ -55,10 +55,7 @@ module PaperTrailAssociationTracking
55
55
  private
56
56
 
57
57
  def migration_version
58
- major = ActiveRecord::VERSION::MAJOR
59
- if major >= 5
60
- "[#{major}.#{ActiveRecord::VERSION::MINOR}]"
61
- end
58
+ "[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
62
59
  end
63
60
  end
64
61
  end
@@ -0,0 +1,21 @@
1
+ # This migration and AddTransactionIdColumnToVersions provide the necessary
2
+ # schema for tracking associations.
3
+ class AddForeignTypeToVersionAssociations < ActiveRecord::Migration<%= migration_version %>
4
+ def self.up
5
+ add_column :version_associations, :foreign_type, :string, index: true
6
+ remove_index :version_associations,
7
+ name: "index_version_associations_on_foreign_key"
8
+ add_index :version_associations,
9
+ %i(foreign_key_name foreign_key_id foreign_type),
10
+ name: "index_version_associations_on_foreign_key"
11
+ end
12
+
13
+ def self.down
14
+ remove_index :version_associations,
15
+ name: "index_version_associations_on_foreign_key"
16
+ remove_column :version_associations, :foreign_type
17
+ add_index :version_associations,
18
+ %i(foreign_key_name foreign_key_id),
19
+ name: "index_version_associations_on_foreign_key"
20
+ end
21
+ end
@@ -6,7 +6,7 @@ class CreateVersionAssociations < ActiveRecord::Migration<%= migration_version %
6
6
  t.integer :version_id
7
7
  t.string :foreign_key_name, null: false
8
8
  t.integer :foreign_key_id
9
- t.string :foreign_type, null: false
9
+ t.string :foreign_type
10
10
  end
11
11
  add_index :version_associations, [:version_id]
12
12
  add_index :version_associations,
@@ -55,8 +55,7 @@ end
55
55
 
56
56
  # Require frameworks
57
57
  if defined?(::Rails)
58
- # Rails module is sometimes defined by gems like rails-html-sanitizer
59
- # so we check for presence of Rails.application.
58
+ # Rails module is sometimes defined by gems like rails-html-sanitizer so we check for presence of Rails.application.
60
59
  if defined?(::Rails.application)
61
60
  require "paper_trail_association_tracking/frameworks/rails"
62
61
  else
@@ -6,33 +6,6 @@ module PaperTrailAssociationTracking
6
6
  def transaction?
7
7
  ::ActiveRecord::Base.connection.open_transactions.positive?
8
8
  end
9
-
10
- # @deprecated
11
- def clear_transaction_id
12
- ::ActiveSupport::Deprecation.warn(
13
- "PaperTrail.clear_transaction_id is deprecated, use PaperTrail.request.clear_transaction_id",
14
- caller(1)
15
- )
16
- request.clear_transaction_id
17
- end
18
-
19
- # @deprecated
20
- def transaction_id
21
- ::ActiveSupport::Deprecation.warn(
22
- "PaperTrail.transaction_id is deprecated without replacement.",
23
- caller(1)
24
- )
25
- request.transaction_id
26
- end
27
-
28
- # @deprecated
29
- def transaction_id=(id)
30
- ::ActiveSupport::Deprecation.warn(
31
- "PaperTrail.transaction_id= is deprecated without replacement.",
32
- caller(1)
33
- )
34
- request.transaction_id = id
35
- end
36
9
  end
37
10
  end
38
11
  end
@@ -78,14 +78,13 @@ module PaperTrailAssociationTracking
78
78
  #
79
79
  # @api private
80
80
  # @param klass - An ActiveRecord class.
81
- # @param version_id_subquery - String. A SQL subquery that selects
82
- # the IDs of version records.
81
+ # @param version_ids - Array. The IDs of version records.
83
82
  # @return A `Hash` mapping IDs to `Version`s
84
83
  #
85
- def versions_by_id(klass, version_id_subquery)
84
+ def versions_by_id(klass, version_ids)
86
85
  klass.
87
86
  paper_trail.version_class.
88
- where("id IN (#{version_id_subquery})").
87
+ where(id: version_ids).
89
88
  inject({}) { |a, e| a.merge!(e.item_id => e) }
90
89
  end
91
90
 
@@ -95,17 +94,23 @@ module PaperTrailAssociationTracking
95
94
  # from the point in time identified by `tx_id` or `version_at`.
96
95
  # @api private
97
96
  def load_versions_for_hm_association(assoc, model, version_table, tx_id, version_at)
98
- version_id_subquery = ::PaperTrail::VersionAssociation.
97
+ # For STI models, associations may be defined to reference superclasses, so looking up
98
+ # based on only the child-most class is not appropriate.
99
+ sti_model_names = model.class.ancestors
100
+ .select { |x| x <= model.class.base_class && x.method_defined?(assoc.name) }
101
+ .map(&:name)
102
+
103
+ version_ids = ::PaperTrail::VersionAssociation.
99
104
  joins(model.class.version_association_name).
100
- select("MIN(version_id)").
105
+ select("MIN(version_id) as version_id").
101
106
  where("foreign_key_name = ?", assoc.foreign_key).
102
107
  where("foreign_key_id = ?", model.id).
103
- where("foreign_type = ?", model.class.name).
108
+ where(foreign_type: sti_model_names + [nil]).
104
109
  where("#{version_table}.item_type = ?", assoc.klass.base_class.name).
105
110
  where("created_at >= ? OR transaction_id = ?", version_at, tx_id).
106
111
  group("item_id").
107
- to_sql
108
- versions_by_id(model.class, version_id_subquery)
112
+ map{|e| e.version_id}
113
+ versions_by_id(model.class, version_ids)
109
114
  end
110
115
  end
111
116
  end
@@ -53,7 +53,16 @@ module PaperTrailAssociationTracking
53
53
  # association, that is, `model.paragraphs`, has not been loaded. So,
54
54
  # we do that now.
55
55
  through_collection.flat_map { |through_model|
56
- through_model.public_send(assoc.name.to_sym).to_a
56
+ records = through_model.public_send(assoc.source_reflection_name)
57
+
58
+ if records.respond_to?(:to_a)
59
+ # Has Many association
60
+ records = records.to_a
61
+ else
62
+ # Has One association - Nothing more to do
63
+ end
64
+
65
+ records
57
66
  }
58
67
  end
59
68
 
@@ -73,8 +82,8 @@ module PaperTrailAssociationTracking
73
82
  # `version_at`.
74
83
  # @api private
75
84
  def load_versions_for_hmt_association(assoc, ids, tx_id, version_at)
76
- version_id_subquery = assoc.klass.paper_trail.version_class.
77
- select("MIN(id)").
85
+ version_ids = assoc.klass.paper_trail.version_class.
86
+ select("MIN(id) as id").
78
87
  where("item_type = ?", assoc.klass.base_class.name).
79
88
  where("item_id IN (?)", ids).
80
89
  where(
@@ -83,8 +92,8 @@ module PaperTrailAssociationTracking
83
92
  tx_id
84
93
  ).
85
94
  group("item_id").
86
- to_sql
87
- ::PaperTrailAssociationTracking::Reifiers::HasMany.versions_by_id(assoc.klass, version_id_subquery)
95
+ map{|e| e.id}
96
+ ::PaperTrailAssociationTracking::Reifiers::HasMany.versions_by_id(assoc.klass, version_ids)
88
97
  end
89
98
  end
90
99
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PaperTrailAssociationTracking
4
- VERSION = "1.1.0"
4
+ VERSION = "2.1.3".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: 1.1.0
4
+ version: 2.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Weston Ganger
@@ -10,196 +10,176 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2018-12-28 00:00:00.000000000 Z
13
+ date: 2021-04-20 00:00:00.000000000 Z
14
14
  dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: paper_trail
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - "<"
20
+ - !ruby/object:Gem::Version
21
+ version: '12.0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - "<"
27
+ - !ruby/object:Gem::Version
28
+ version: '12.0'
15
29
  - !ruby/object:Gem::Dependency
16
30
  name: appraisal
17
31
  requirement: !ruby/object:Gem::Requirement
18
32
  requirements:
19
- - - "~>"
33
+ - - ">="
20
34
  - !ruby/object:Gem::Version
21
- version: '2.2'
35
+ version: '0'
22
36
  type: :development
23
37
  prerelease: false
24
38
  version_requirements: !ruby/object:Gem::Requirement
25
39
  requirements:
26
- - - "~>"
40
+ - - ">="
27
41
  - !ruby/object:Gem::Version
28
- version: '2.2'
42
+ version: '0'
29
43
  - !ruby/object:Gem::Dependency
30
44
  name: byebug
31
45
  requirement: !ruby/object:Gem::Requirement
32
46
  requirements:
33
- - - "~>"
47
+ - - ">="
34
48
  - !ruby/object:Gem::Version
35
- version: '9.1'
49
+ version: '0'
36
50
  type: :development
37
51
  prerelease: false
38
52
  version_requirements: !ruby/object:Gem::Requirement
39
53
  requirements:
40
- - - "~>"
54
+ - - ">="
41
55
  - !ruby/object:Gem::Version
42
- version: '9.1'
56
+ version: '0'
43
57
  - !ruby/object:Gem::Dependency
44
58
  name: ffaker
45
59
  requirement: !ruby/object:Gem::Requirement
46
60
  requirements:
47
- - - "~>"
61
+ - - ">="
48
62
  - !ruby/object:Gem::Version
49
- version: '2.7'
63
+ version: '0'
50
64
  type: :development
51
65
  prerelease: false
52
66
  version_requirements: !ruby/object:Gem::Requirement
53
67
  requirements:
54
- - - "~>"
68
+ - - ">="
55
69
  - !ruby/object:Gem::Version
56
- version: '2.7'
70
+ version: '0'
57
71
  - !ruby/object:Gem::Dependency
58
72
  name: generator_spec
59
73
  requirement: !ruby/object:Gem::Requirement
60
74
  requirements:
61
- - - "~>"
75
+ - - ">="
62
76
  - !ruby/object:Gem::Version
63
- version: 0.9.4
77
+ version: '0'
64
78
  type: :development
65
79
  prerelease: false
66
80
  version_requirements: !ruby/object:Gem::Requirement
67
81
  requirements:
68
- - - "~>"
82
+ - - ">="
69
83
  - !ruby/object:Gem::Version
70
- version: 0.9.4
84
+ version: '0'
71
85
  - !ruby/object:Gem::Dependency
72
86
  name: mysql2
73
87
  requirement: !ruby/object:Gem::Requirement
74
88
  requirements:
75
- - - "~>"
89
+ - - ">="
76
90
  - !ruby/object:Gem::Version
77
- version: 0.4.10
91
+ version: '0'
78
92
  type: :development
79
93
  prerelease: false
80
94
  version_requirements: !ruby/object:Gem::Requirement
81
95
  requirements:
82
- - - "~>"
96
+ - - ">="
83
97
  - !ruby/object:Gem::Version
84
- version: 0.4.10
98
+ version: '0'
85
99
  - !ruby/object:Gem::Dependency
86
100
  name: pg
87
101
  requirement: !ruby/object:Gem::Requirement
88
102
  requirements:
89
- - - "~>"
103
+ - - ">="
90
104
  - !ruby/object:Gem::Version
91
- version: 0.21.0
105
+ version: '0'
92
106
  type: :development
93
107
  prerelease: false
94
108
  version_requirements: !ruby/object:Gem::Requirement
95
109
  requirements:
96
- - - "~>"
110
+ - - ">="
97
111
  - !ruby/object:Gem::Version
98
- version: 0.21.0
112
+ version: '0'
99
113
  - !ruby/object:Gem::Dependency
100
114
  name: rack-test
101
115
  requirement: !ruby/object:Gem::Requirement
102
116
  requirements:
103
117
  - - ">="
104
118
  - !ruby/object:Gem::Version
105
- version: 0.6.3
106
- - - "<"
107
- - !ruby/object:Gem::Version
108
- version: '0.9'
119
+ version: '0'
109
120
  type: :development
110
121
  prerelease: false
111
122
  version_requirements: !ruby/object:Gem::Requirement
112
123
  requirements:
113
124
  - - ">="
114
125
  - !ruby/object:Gem::Version
115
- version: 0.6.3
116
- - - "<"
117
- - !ruby/object:Gem::Version
118
- version: '0.9'
126
+ version: '0'
119
127
  - !ruby/object:Gem::Dependency
120
128
  name: rake
121
129
  requirement: !ruby/object:Gem::Requirement
122
130
  requirements:
123
- - - "~>"
131
+ - - ">="
124
132
  - !ruby/object:Gem::Version
125
- version: '12.3'
133
+ version: '0'
126
134
  type: :development
127
135
  prerelease: false
128
136
  version_requirements: !ruby/object:Gem::Requirement
129
137
  requirements:
130
- - - "~>"
138
+ - - ">="
131
139
  - !ruby/object:Gem::Version
132
- version: '12.3'
140
+ version: '0'
133
141
  - !ruby/object:Gem::Dependency
134
142
  name: rspec-rails
135
143
  requirement: !ruby/object:Gem::Requirement
136
144
  requirements:
137
- - - "~>"
138
- - !ruby/object:Gem::Version
139
- version: 3.7.2
140
- type: :development
141
- prerelease: false
142
- version_requirements: !ruby/object:Gem::Requirement
143
- requirements:
144
- - - "~>"
145
- - !ruby/object:Gem::Version
146
- version: 3.7.2
147
- - !ruby/object:Gem::Dependency
148
- name: rubocop
149
- requirement: !ruby/object:Gem::Requirement
150
- requirements:
151
- - - "~>"
152
- - !ruby/object:Gem::Version
153
- version: 0.51.0
154
- type: :development
155
- prerelease: false
156
- version_requirements: !ruby/object:Gem::Requirement
157
- requirements:
158
- - - "~>"
159
- - !ruby/object:Gem::Version
160
- version: 0.51.0
161
- - !ruby/object:Gem::Dependency
162
- name: rubocop-rspec
163
- requirement: !ruby/object:Gem::Requirement
164
- requirements:
165
- - - "~>"
145
+ - - ">="
166
146
  - !ruby/object:Gem::Version
167
- version: 1.19.0
147
+ version: '0'
168
148
  type: :development
169
149
  prerelease: false
170
150
  version_requirements: !ruby/object:Gem::Requirement
171
151
  requirements:
172
- - - "~>"
152
+ - - ">="
173
153
  - !ruby/object:Gem::Version
174
- version: 1.19.0
154
+ version: '0'
175
155
  - !ruby/object:Gem::Dependency
176
156
  name: sqlite3
177
157
  requirement: !ruby/object:Gem::Requirement
178
158
  requirements:
179
- - - "~>"
159
+ - - ">="
180
160
  - !ruby/object:Gem::Version
181
- version: '1.3'
161
+ version: '0'
182
162
  type: :development
183
163
  prerelease: false
184
164
  version_requirements: !ruby/object:Gem::Requirement
185
165
  requirements:
186
- - - "~>"
166
+ - - ">="
187
167
  - !ruby/object:Gem::Version
188
- version: '1.3'
168
+ version: '0'
189
169
  - !ruby/object:Gem::Dependency
190
170
  name: timecop
191
171
  requirement: !ruby/object:Gem::Requirement
192
172
  requirements:
193
- - - "~>"
173
+ - - ">="
194
174
  - !ruby/object:Gem::Version
195
- version: 0.9.1
175
+ version: '0'
196
176
  type: :development
197
177
  prerelease: false
198
178
  version_requirements: !ruby/object:Gem::Requirement
199
179
  requirements:
200
- - - "~>"
180
+ - - ">="
201
181
  - !ruby/object:Gem::Version
202
- version: 0.9.1
182
+ version: '0'
203
183
  description: Plugin for the PaperTrail gem to track and reify associations
204
184
  email: weston@westonganger.com
205
185
  executables: []
@@ -210,7 +190,9 @@ files:
210
190
  - LICENSE
211
191
  - README.md
212
192
  - Rakefile
193
+ - lib/generators/paper_trail_association_tracking/add_foreign_type_to_version_associations_generator.rb
213
194
  - lib/generators/paper_trail_association_tracking/install_generator.rb
195
+ - lib/generators/paper_trail_association_tracking/templates/add_foreign_type_to_version_associations.rb.erb
214
196
  - lib/generators/paper_trail_association_tracking/templates/add_transaction_id_column_to_versions.rb.erb
215
197
  - lib/generators/paper_trail_association_tracking/templates/create_version_associations.rb.erb
216
198
  - lib/paper_trail-association_tracking.rb
@@ -250,9 +232,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
250
232
  requirements:
251
233
  - - ">="
252
234
  - !ruby/object:Gem::Version
253
- version: 1.3.6
235
+ version: '0'
254
236
  requirements: []
255
- rubygems_version: 3.0.1
237
+ rubygems_version: 3.1.2
256
238
  signing_key:
257
239
  specification_version: 4
258
240
  summary: Plugin for the PaperTrail gem to track and reify associations