paper_trail 5.2.3 → 11.0.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.
Files changed (198) hide show
  1. checksums.yaml +5 -5
  2. data/lib/generators/paper_trail/install/USAGE +3 -0
  3. data/lib/generators/paper_trail/install/install_generator.rb +75 -0
  4. data/lib/generators/paper_trail/{templates/add_object_changes_to_versions.rb → install/templates/add_object_changes_to_versions.rb.erb} +1 -1
  5. data/lib/generators/paper_trail/install/templates/create_versions.rb.erb +36 -0
  6. data/lib/generators/paper_trail/migration_generator.rb +38 -0
  7. data/lib/generators/paper_trail/update_item_subtype/USAGE +4 -0
  8. data/lib/generators/paper_trail/update_item_subtype/templates/update_versions_for_item_subtype.rb.erb +85 -0
  9. data/lib/generators/paper_trail/update_item_subtype/update_item_subtype_generator.rb +17 -0
  10. data/lib/paper_trail.rb +82 -130
  11. data/lib/paper_trail/attribute_serializers/attribute_serializer_factory.rb +27 -0
  12. data/lib/paper_trail/attribute_serializers/cast_attribute_serializer.rb +15 -44
  13. data/lib/paper_trail/attribute_serializers/object_attribute.rb +2 -0
  14. data/lib/paper_trail/attribute_serializers/object_changes_attribute.rb +2 -0
  15. data/lib/paper_trail/cleaner.rb +3 -1
  16. data/lib/paper_trail/compatibility.rb +51 -0
  17. data/lib/paper_trail/config.rb +11 -49
  18. data/lib/paper_trail/events/base.rb +323 -0
  19. data/lib/paper_trail/events/create.rb +32 -0
  20. data/lib/paper_trail/events/destroy.rb +42 -0
  21. data/lib/paper_trail/events/update.rb +60 -0
  22. data/lib/paper_trail/frameworks/active_record.rb +2 -1
  23. data/lib/paper_trail/frameworks/active_record/models/paper_trail/version.rb +8 -3
  24. data/lib/paper_trail/frameworks/cucumber.rb +5 -3
  25. data/lib/paper_trail/frameworks/rails.rb +2 -0
  26. data/lib/paper_trail/frameworks/rails/controller.rb +33 -43
  27. data/lib/paper_trail/frameworks/rails/engine.rb +34 -1
  28. data/lib/paper_trail/frameworks/rspec.rb +17 -4
  29. data/lib/paper_trail/frameworks/rspec/helpers.rb +2 -0
  30. data/lib/paper_trail/has_paper_trail.rb +22 -310
  31. data/lib/paper_trail/model_config.rb +157 -109
  32. data/lib/paper_trail/queries/versions/where_object.rb +65 -0
  33. data/lib/paper_trail/queries/versions/where_object_changes.rb +75 -0
  34. data/lib/paper_trail/record_history.rb +3 -9
  35. data/lib/paper_trail/record_trail.rb +169 -319
  36. data/lib/paper_trail/reifier.rb +53 -374
  37. data/lib/paper_trail/request.rb +166 -0
  38. data/lib/paper_trail/serializers/json.rb +9 -10
  39. data/lib/paper_trail/serializers/yaml.rb +15 -28
  40. data/lib/paper_trail/type_serializers/postgres_array_serializer.rb +48 -0
  41. data/lib/paper_trail/version_concern.rb +160 -155
  42. data/lib/paper_trail/version_number.rb +12 -4
  43. metadata +77 -372
  44. data/.github/CONTRIBUTING.md +0 -109
  45. data/.github/ISSUE_TEMPLATE.md +0 -13
  46. data/.gitignore +0 -23
  47. data/.rspec +0 -2
  48. data/.rubocop.yml +0 -99
  49. data/.rubocop_todo.yml +0 -22
  50. data/.travis.yml +0 -41
  51. data/Appraisals +0 -38
  52. data/CHANGELOG.md +0 -560
  53. data/Gemfile +0 -2
  54. data/MIT-LICENSE +0 -20
  55. data/README.md +0 -1654
  56. data/Rakefile +0 -30
  57. data/doc/bug_report_template.rb +0 -69
  58. data/doc/warning_about_not_setting_whodunnit.md +0 -32
  59. data/gemfiles/ar3.gemfile +0 -19
  60. data/gemfiles/ar4.gemfile +0 -8
  61. data/gemfiles/ar5.gemfile +0 -9
  62. data/lib/generators/paper_trail/USAGE +0 -2
  63. data/lib/generators/paper_trail/default_initializer.rb +0 -0
  64. data/lib/generators/paper_trail/install_generator.rb +0 -57
  65. data/lib/generators/paper_trail/templates/add_transaction_id_column_to_versions.rb +0 -13
  66. data/lib/generators/paper_trail/templates/create_version_associations.rb +0 -22
  67. data/lib/generators/paper_trail/templates/create_versions.rb +0 -80
  68. data/lib/paper_trail/attribute_serializers/legacy_active_record_shim.rb +0 -48
  69. data/lib/paper_trail/frameworks/active_record/models/paper_trail/version_association.rb +0 -11
  70. data/lib/paper_trail/frameworks/sinatra.rb +0 -40
  71. data/lib/paper_trail/version_association_concern.rb +0 -17
  72. data/paper_trail.gemspec +0 -56
  73. data/spec/generators/install_generator_spec.rb +0 -66
  74. data/spec/generators/paper_trail/templates/create_versions_spec.rb +0 -51
  75. data/spec/models/animal_spec.rb +0 -36
  76. data/spec/models/boolit_spec.rb +0 -48
  77. data/spec/models/callback_modifier_spec.rb +0 -96
  78. data/spec/models/car_spec.rb +0 -13
  79. data/spec/models/custom_primary_key_record_spec.rb +0 -18
  80. data/spec/models/fluxor_spec.rb +0 -17
  81. data/spec/models/gadget_spec.rb +0 -68
  82. data/spec/models/joined_version_spec.rb +0 -47
  83. data/spec/models/json_version_spec.rb +0 -102
  84. data/spec/models/kitchen/banana_spec.rb +0 -14
  85. data/spec/models/not_on_update_spec.rb +0 -22
  86. data/spec/models/post_with_status_spec.rb +0 -50
  87. data/spec/models/skipper_spec.rb +0 -46
  88. data/spec/models/thing_spec.rb +0 -11
  89. data/spec/models/truck_spec.rb +0 -5
  90. data/spec/models/vehicle_spec.rb +0 -5
  91. data/spec/models/version_spec.rb +0 -272
  92. data/spec/models/widget_spec.rb +0 -343
  93. data/spec/modules/paper_trail_spec.rb +0 -27
  94. data/spec/modules/version_concern_spec.rb +0 -31
  95. data/spec/modules/version_number_spec.rb +0 -43
  96. data/spec/paper_trail/config_spec.rb +0 -33
  97. data/spec/paper_trail_spec.rb +0 -79
  98. data/spec/rails_helper.rb +0 -34
  99. data/spec/requests/articles_spec.rb +0 -34
  100. data/spec/spec_helper.rb +0 -114
  101. data/spec/support/alt_db_init.rb +0 -54
  102. data/test/custom_json_serializer.rb +0 -13
  103. data/test/dummy/Rakefile +0 -7
  104. data/test/dummy/app/controllers/application_controller.rb +0 -33
  105. data/test/dummy/app/controllers/articles_controller.rb +0 -20
  106. data/test/dummy/app/controllers/test_controller.rb +0 -5
  107. data/test/dummy/app/controllers/widgets_controller.rb +0 -32
  108. data/test/dummy/app/helpers/application_helper.rb +0 -2
  109. data/test/dummy/app/models/animal.rb +0 -6
  110. data/test/dummy/app/models/article.rb +0 -24
  111. data/test/dummy/app/models/authorship.rb +0 -5
  112. data/test/dummy/app/models/bar_habtm.rb +0 -4
  113. data/test/dummy/app/models/book.rb +0 -9
  114. data/test/dummy/app/models/boolit.rb +0 -4
  115. data/test/dummy/app/models/callback_modifier.rb +0 -45
  116. data/test/dummy/app/models/car.rb +0 -3
  117. data/test/dummy/app/models/cat.rb +0 -2
  118. data/test/dummy/app/models/chapter.rb +0 -9
  119. data/test/dummy/app/models/citation.rb +0 -5
  120. data/test/dummy/app/models/custom_primary_key_record.rb +0 -13
  121. data/test/dummy/app/models/customer.rb +0 -4
  122. data/test/dummy/app/models/document.rb +0 -4
  123. data/test/dummy/app/models/dog.rb +0 -2
  124. data/test/dummy/app/models/editor.rb +0 -4
  125. data/test/dummy/app/models/editorship.rb +0 -5
  126. data/test/dummy/app/models/elephant.rb +0 -3
  127. data/test/dummy/app/models/fluxor.rb +0 -3
  128. data/test/dummy/app/models/foo_habtm.rb +0 -5
  129. data/test/dummy/app/models/foo_widget.rb +0 -2
  130. data/test/dummy/app/models/fruit.rb +0 -5
  131. data/test/dummy/app/models/gadget.rb +0 -3
  132. data/test/dummy/app/models/kitchen/banana.rb +0 -5
  133. data/test/dummy/app/models/legacy_widget.rb +0 -4
  134. data/test/dummy/app/models/line_item.rb +0 -4
  135. data/test/dummy/app/models/not_on_update.rb +0 -4
  136. data/test/dummy/app/models/order.rb +0 -5
  137. data/test/dummy/app/models/paragraph.rb +0 -5
  138. data/test/dummy/app/models/person.rb +0 -38
  139. data/test/dummy/app/models/post.rb +0 -3
  140. data/test/dummy/app/models/post_with_status.rb +0 -8
  141. data/test/dummy/app/models/protected_widget.rb +0 -3
  142. data/test/dummy/app/models/quotation.rb +0 -5
  143. data/test/dummy/app/models/section.rb +0 -6
  144. data/test/dummy/app/models/skipper.rb +0 -6
  145. data/test/dummy/app/models/song.rb +0 -41
  146. data/test/dummy/app/models/thing.rb +0 -3
  147. data/test/dummy/app/models/translation.rb +0 -4
  148. data/test/dummy/app/models/truck.rb +0 -4
  149. data/test/dummy/app/models/vehicle.rb +0 -4
  150. data/test/dummy/app/models/whatchamajigger.rb +0 -4
  151. data/test/dummy/app/models/widget.rb +0 -16
  152. data/test/dummy/app/models/wotsit.rb +0 -8
  153. data/test/dummy/app/versions/custom_primary_key_record_version.rb +0 -3
  154. data/test/dummy/app/versions/joined_version.rb +0 -6
  155. data/test/dummy/app/versions/json_version.rb +0 -3
  156. data/test/dummy/app/versions/kitchen/banana_version.rb +0 -5
  157. data/test/dummy/app/versions/post_version.rb +0 -3
  158. data/test/dummy/app/views/layouts/application.html.erb +0 -14
  159. data/test/dummy/config.ru +0 -4
  160. data/test/dummy/config/application.rb +0 -80
  161. data/test/dummy/config/boot.rb +0 -10
  162. data/test/dummy/config/database.mysql.yml +0 -19
  163. data/test/dummy/config/database.postgres.yml +0 -15
  164. data/test/dummy/config/database.sqlite.yml +0 -15
  165. data/test/dummy/config/environment.rb +0 -5
  166. data/test/dummy/config/environments/development.rb +0 -41
  167. data/test/dummy/config/environments/production.rb +0 -74
  168. data/test/dummy/config/environments/test.rb +0 -51
  169. data/test/dummy/config/initializers/backtrace_silencers.rb +0 -9
  170. data/test/dummy/config/initializers/inflections.rb +0 -10
  171. data/test/dummy/config/initializers/mime_types.rb +0 -5
  172. data/test/dummy/config/initializers/paper_trail.rb +0 -9
  173. data/test/dummy/config/initializers/secret_token.rb +0 -9
  174. data/test/dummy/config/initializers/session_store.rb +0 -8
  175. data/test/dummy/config/locales/en.yml +0 -5
  176. data/test/dummy/config/routes.rb +0 -4
  177. data/test/dummy/db/migrate/20110208155312_set_up_test_tables.rb +0 -361
  178. data/test/dummy/db/schema.rb +0 -288
  179. data/test/dummy/script/rails +0 -8
  180. data/test/functional/controller_test.rb +0 -90
  181. data/test/functional/enabled_for_controller_test.rb +0 -28
  182. data/test/functional/modular_sinatra_test.rb +0 -46
  183. data/test/functional/sinatra_test.rb +0 -51
  184. data/test/functional/thread_safety_test.rb +0 -46
  185. data/test/test_helper.rb +0 -127
  186. data/test/time_travel_helper.rb +0 -1
  187. data/test/unit/associations_test.rb +0 -1016
  188. data/test/unit/cleaner_test.rb +0 -188
  189. data/test/unit/inheritance_column_test.rb +0 -43
  190. data/test/unit/model_test.rb +0 -1489
  191. data/test/unit/protected_attrs_test.rb +0 -52
  192. data/test/unit/serializer_test.rb +0 -119
  193. data/test/unit/serializers/json_test.rb +0 -95
  194. data/test/unit/serializers/mixin_json_test.rb +0 -37
  195. data/test/unit/serializers/mixin_yaml_test.rb +0 -53
  196. data/test/unit/serializers/yaml_test.rb +0 -54
  197. data/test/unit/timestamp_test.rb +0 -41
  198. data/test/unit/version_test.rb +0 -119
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "paper_trail/events/base"
4
+
5
+ module PaperTrail
6
+ module Events
7
+ # See docs in `Base`.
8
+ #
9
+ # @api private
10
+ class Create < Base
11
+ # Return attributes of nascent `Version` record.
12
+ #
13
+ # @api private
14
+ def data
15
+ data = {
16
+ item: @record,
17
+ event: @record.paper_trail_event || "create",
18
+ whodunnit: PaperTrail.request.whodunnit
19
+ }
20
+ if @record.respond_to?(:updated_at)
21
+ data[:created_at] = @record.updated_at
22
+ end
23
+ if record_object_changes? && changed_notably?
24
+ changes = notable_changes
25
+ data[:object_changes] = prepare_object_changes(changes)
26
+ end
27
+ merge_item_subtype_into(data)
28
+ merge_metadata_into(data)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "paper_trail/events/base"
4
+
5
+ module PaperTrail
6
+ module Events
7
+ # See docs in `Base`.
8
+ #
9
+ # @api private
10
+ class Destroy < Base
11
+ # Return attributes of nascent `Version` record.
12
+ #
13
+ # @api private
14
+ def data
15
+ data = {
16
+ item_id: @record.id,
17
+ item_type: @record.class.base_class.name,
18
+ event: @record.paper_trail_event || "destroy",
19
+ whodunnit: PaperTrail.request.whodunnit
20
+ }
21
+ if record_object?
22
+ data[:object] = recordable_object(false)
23
+ end
24
+ if record_object_changes?
25
+ data[:object_changes] = prepare_object_changes(notable_changes)
26
+ end
27
+ merge_item_subtype_into(data)
28
+ merge_metadata_into(data)
29
+ end
30
+
31
+ private
32
+
33
+ # Rails' implementation (eg. `@record.saved_changes`) returns nothing on
34
+ # destroy, so we have to build the hash we want.
35
+ #
36
+ # @override
37
+ def changes_in_latest_version
38
+ @record.attributes.map { |attr, value| [attr, [value, nil]] }.to_h
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "paper_trail/events/base"
4
+
5
+ module PaperTrail
6
+ module Events
7
+ # See docs in `Base`.
8
+ #
9
+ # @api private
10
+ class Update < Base
11
+ # - is_touch - [boolean] - Used in the two situations that are touch-like:
12
+ # - `after_touch` we call `RecordTrail#record_update`
13
+ # - force_changes - [Hash] - Only used by `RecordTrail#update_columns`,
14
+ # because there dirty-tracking is off, so it has to track its own changes.
15
+ #
16
+ # @api private
17
+ def initialize(record, in_after_callback, is_touch, force_changes)
18
+ super(record, in_after_callback)
19
+ @is_touch = is_touch
20
+ @force_changes = force_changes
21
+ end
22
+
23
+ # Return attributes of nascent `Version` record.
24
+ #
25
+ # @api private
26
+ def data
27
+ data = {
28
+ item: @record,
29
+ event: @record.paper_trail_event || "update",
30
+ whodunnit: PaperTrail.request.whodunnit
31
+ }
32
+ if @record.respond_to?(:updated_at)
33
+ data[:created_at] = @record.updated_at
34
+ end
35
+ if record_object?
36
+ data[:object] = recordable_object(@is_touch)
37
+ end
38
+ if record_object_changes?
39
+ changes = @force_changes.nil? ? notable_changes : @force_changes
40
+ data[:object_changes] = prepare_object_changes(changes)
41
+ end
42
+ merge_item_subtype_into(data)
43
+ merge_metadata_into(data)
44
+ end
45
+
46
+ private
47
+
48
+ # `touch` cannot record `object_changes` because rails' `touch` does not
49
+ # perform dirty-tracking. Specifically, methods from `Dirty`, like
50
+ # `saved_changes`, return the same values before and after `touch`.
51
+ #
52
+ # See https://github.com/rails/rails/issues/33429
53
+ #
54
+ # @api private
55
+ def record_object_changes?
56
+ !@is_touch && super
57
+ end
58
+ end
59
+ end
60
+ end
@@ -1,4 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file only needs to be loaded if the gem is being used outside of Rails,
2
4
  # since otherwise the model(s) will get loaded in via the `Rails::Engine`.
3
- require "paper_trail/frameworks/active_record/models/paper_trail/version_association"
4
5
  require "paper_trail/frameworks/active_record/models/paper_trail/version"
@@ -1,10 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "paper_trail/version_concern"
2
4
 
3
5
  module PaperTrail
4
6
  # This is the default ActiveRecord model provided by PaperTrail. Most simple
5
- # applications will only use this and its partner, `VersionAssociation`, but
6
- # it is possible to sub-class, extend, or even do without this model entirely.
7
- # See the readme for details.
7
+ # applications will use this model as-is, but it is possible to sub-class,
8
+ # extend, or even do without this model entirely. See documentation section
9
+ # 6.a. Custom Version Classes.
10
+ #
11
+ # The paper_trail-association_tracking gem provides a related model,
12
+ # `VersionAssociation`.
8
13
  class Version < ::ActiveRecord::Base
9
14
  include PaperTrail::VersionConcern
10
15
  end
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # before hook for Cucumber
2
4
  Before do
3
5
  PaperTrail.enabled = false
4
- PaperTrail.enabled_for_controller = true
5
- PaperTrail.whodunnit = nil
6
- PaperTrail.controller_info = {} if defined? Rails
6
+ PaperTrail.request.enabled = true
7
+ PaperTrail.request.whodunnit = nil
8
+ PaperTrail.request.controller_info = {} if defined?(::Rails)
7
9
  end
8
10
 
9
11
  module PaperTrail
@@ -1,2 +1,4 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "paper_trail/frameworks/rails/controller"
2
4
  require "paper_trail/frameworks/rails/engine"
@@ -1,27 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module PaperTrail
2
4
  module Rails
3
5
  # Extensions to rails controllers. Provides convenient ways to pass certain
4
6
  # information to the model layer, with `controller_info` and `whodunnit`.
5
- # Also includes a convenient on/off switch, `enabled_for_controller`.
7
+ # Also includes a convenient on/off switch,
8
+ # `paper_trail_enabled_for_controller`.
6
9
  module Controller
7
- def self.included(base)
8
- before = [
10
+ def self.included(controller)
11
+ controller.before_action(
9
12
  :set_paper_trail_enabled_for_controller,
10
13
  :set_paper_trail_controller_info
11
- ]
12
- after = [
13
- :warn_about_not_setting_whodunnit
14
- ]
15
-
16
- if base.respond_to? :before_action
17
- # Rails 4+
18
- before.map { |sym| base.before_action sym }
19
- after.map { |sym| base.after_action sym }
20
- else
21
- # Rails 3.
22
- before.map { |sym| base.before_filter sym }
23
- after.map { |sym| base.after_filter sym }
24
- end
14
+ )
25
15
  end
26
16
 
27
17
  protected
@@ -31,11 +21,11 @@ module PaperTrail
31
21
  #
32
22
  # Override this method in your controller to call a different
33
23
  # method, e.g. `current_person`, or anything you like.
24
+ #
25
+ # @api public
34
26
  def user_for_paper_trail
35
27
  return unless defined?(current_user)
36
- ActiveSupport::VERSION::MAJOR >= 4 ? current_user.try!(:id) : current_user.try(:id)
37
- rescue NoMethodError
38
- current_user
28
+ current_user.try(:id) || current_user
39
29
  end
40
30
 
41
31
  # Returns any information about the controller or request that you
@@ -56,6 +46,8 @@ module PaperTrail
56
46
  # Use the `:meta` option to
57
47
  # `PaperTrail::Model::ClassMethods.has_paper_trail` to store any extra
58
48
  # model-level data you need.
49
+ #
50
+ # @api public
59
51
  def info_for_paper_trail
60
52
  {}
61
53
  end
@@ -65,6 +57,15 @@ module PaperTrail
65
57
  #
66
58
  # Override this method in your controller to specify when PaperTrail
67
59
  # should be off.
60
+ #
61
+ # ```
62
+ # def paper_trail_enabled_for_controller
63
+ # # Don't omit `super` without a good reason.
64
+ # super && request.user_agent != 'Disable User-Agent'
65
+ # end
66
+ # ```
67
+ #
68
+ # @api public
68
69
  def paper_trail_enabled_for_controller
69
70
  ::PaperTrail.enabled?
70
71
  end
@@ -73,39 +74,28 @@ module PaperTrail
73
74
 
74
75
  # Tells PaperTrail whether versions should be saved in the current
75
76
  # request.
77
+ #
78
+ # @api public
76
79
  def set_paper_trail_enabled_for_controller
77
- ::PaperTrail.enabled_for_controller = paper_trail_enabled_for_controller
80
+ ::PaperTrail.request.enabled = paper_trail_enabled_for_controller
78
81
  end
79
82
 
80
83
  # Tells PaperTrail who is responsible for any changes that occur.
84
+ #
85
+ # @api public
81
86
  def set_paper_trail_whodunnit
82
- @set_paper_trail_whodunnit_called = true
83
- ::PaperTrail.whodunnit = user_for_paper_trail if ::PaperTrail.enabled_for_controller?
87
+ if ::PaperTrail.request.enabled?
88
+ ::PaperTrail.request.whodunnit = user_for_paper_trail
89
+ end
84
90
  end
85
91
 
86
92
  # Tells PaperTrail any information from the controller you want to store
87
93
  # alongside any changes that occur.
94
+ #
95
+ # @api public
88
96
  def set_paper_trail_controller_info
89
- ::PaperTrail.controller_info = info_for_paper_trail if ::PaperTrail.enabled_for_controller?
90
- end
91
-
92
- def warn_about_not_setting_whodunnit
93
- return unless ::PaperTrail.enabled_for_controller?
94
-
95
- user_present = user_for_paper_trail.present?
96
- whodunnit_blank = ::PaperTrail.whodunnit.blank?
97
- if user_present && whodunnit_blank && !@set_paper_trail_whodunnit_called
98
- source_file_location = self.class.instance_methods(false).map { |m|
99
- self.class.instance_method(m).source_location.first
100
- }.uniq.first
101
- ::Kernel.warn <<-EOS.strip_heredoc
102
- #{source_file_location}:
103
- user_for_paper_trail is present, but whodunnit has not been set.
104
- PaperTrail no longer adds the set_paper_trail_whodunnit callback for
105
- you. To continue recording whodunnit, please add this before_action
106
- callback to your ApplicationController . For more information,
107
- please see https://git.io/vrTsk
108
- EOS
97
+ if ::PaperTrail.request.enabled?
98
+ ::PaperTrail.request.controller_info = info_for_paper_trail
109
99
  end
110
100
  end
111
101
  end
@@ -1,12 +1,45 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module PaperTrail
2
4
  module Rails
3
5
  # See http://guides.rubyonrails.org/engines.html
4
6
  class Engine < ::Rails::Engine
7
+ DPR_CONFIG_ENABLED = <<~EOS.squish.freeze
8
+ The rails configuration option config.paper_trail.enabled is deprecated.
9
+ Please use PaperTrail.enabled= instead. People were getting confused
10
+ that PT has both, specifically regarding *when* each was happening. If
11
+ you'd like to keep config.paper_trail, join the discussion at
12
+ https://github.com/paper-trail-gem/paper_trail/pull/1176
13
+ EOS
14
+ private_constant :DPR_CONFIG_ENABLED
15
+ DPR_RUDELY_ENABLING = <<~EOS.squish.freeze
16
+ At some point early in the rails boot process, you have set
17
+ PaperTrail.enabled = false. PT's rails engine is now overriding your
18
+ setting, and setting it to true. We're not sure why, but this is how PT
19
+ has worked since 5.0, when the config.paper_trail.enabled option was
20
+ introduced. This is now deprecated. In the future, PT will not override
21
+ your setting. See
22
+ https://github.com/paper-trail-gem/paper_trail/pull/1176 for discussion.
23
+ EOS
24
+ private_constant :DPR_RUDELY_ENABLING
25
+
5
26
  paths["app/models"] << "lib/paper_trail/frameworks/active_record/models"
27
+
28
+ # --- Begin deprecated section ---
6
29
  config.paper_trail = ActiveSupport::OrderedOptions.new
7
30
  initializer "paper_trail.initialisation" do |app|
8
- PaperTrail.enabled = app.config.paper_trail.fetch(:enabled, true)
31
+ enable = app.config.paper_trail[:enabled]
32
+ if enable.nil?
33
+ unless PaperTrail.enabled?
34
+ ::ActiveSupport::Deprecation.warn(DPR_RUDELY_ENABLING)
35
+ PaperTrail.enabled = true
36
+ end
37
+ else
38
+ ::ActiveSupport::Deprecation.warn(DPR_CONFIG_ENABLED)
39
+ PaperTrail.enabled = enable
40
+ end
9
41
  end
42
+ # --- End deprecated section ---
10
43
  end
11
44
  end
12
45
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "rspec/core"
2
4
  require "rspec/matchers"
3
5
  require "paper_trail/frameworks/rspec/helpers"
@@ -8,9 +10,9 @@ RSpec.configure do |config|
8
10
 
9
11
  config.before(:each) do
10
12
  ::PaperTrail.enabled = false
11
- ::PaperTrail.enabled_for_controller = true
12
- ::PaperTrail.whodunnit = nil
13
- ::PaperTrail.controller_info = {} if defined?(::Rails) && defined?(::RSpec::Rails)
13
+ ::PaperTrail.request.enabled = true
14
+ ::PaperTrail.request.whodunnit = nil
15
+ ::PaperTrail.request.controller_info = {} if defined?(::Rails) && defined?(::RSpec::Rails)
14
16
  end
15
17
 
16
18
  config.before(:each, versioning: true) do
@@ -25,5 +27,16 @@ end
25
27
 
26
28
  RSpec::Matchers.define :have_a_version_with do |attributes|
27
29
  # check if the model has a version with the specified attributes
28
- match { |actual| actual.versions.where_object(attributes).any? }
30
+ match do |actual|
31
+ versions_association = actual.class.versions_association_name
32
+ actual.send(versions_association).where_object(attributes).any?
33
+ end
34
+ end
35
+
36
+ RSpec::Matchers.define :have_a_version_with_changes do |attributes|
37
+ # check if the model has a version changes with the specified attributes
38
+ match do |actual|
39
+ versions_association = actual.class.versions_association_name
40
+ actual.send(versions_association).where_object_changes(attributes).any?
41
+ end
29
42
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module PaperTrail
2
4
  module RSpec
3
5
  module Helpers
@@ -1,5 +1,5 @@
1
- require "active_support/core_ext/object" # provides the `try` method
2
- require "paper_trail/attribute_serializers/legacy_active_record_shim"
1
+ # frozen_string_literal: true
2
+
3
3
  require "paper_trail/attribute_serializers/object_attribute"
4
4
  require "paper_trail/attribute_serializers/object_changes_attribute"
5
5
  require "paper_trail/model_config"
@@ -23,18 +23,18 @@ module PaperTrail
23
23
  # Options:
24
24
  #
25
25
  # - :on - The events to track (optional; defaults to all of them). Set
26
- # to an array of `:create`, `:update`, `:destroy` as desired.
27
- # - :class_name - The name of a custom Version class. This class should
28
- # inherit from `PaperTrail::Version`.
26
+ # to an array of `:create`, `:update`, `:destroy` and `:touch` as desired.
27
+ # - :class_name (deprecated) - The name of a custom Version class that
28
+ # includes `PaperTrail::VersionConcern`.
29
29
  # - :ignore - An array of attributes for which a new `Version` will not be
30
- # created if only they change. It can also aceept a Hash as an
30
+ # created if only they change. It can also accept a Hash as an
31
31
  # argument where the key is the attribute to ignore (a `String` or
32
32
  # `Symbol`), which will only be ignored if the value is a `Proc` which
33
33
  # returns truthily.
34
34
  # - :if, :unless - Procs that allow to specify conditions when to save
35
35
  # versions for an object.
36
36
  # - :only - Inverse of `ignore`. A new `Version` will be created only
37
- # for these attributes if supplied it can also aceept a Hash as an
37
+ # for these attributes if supplied it can also accept a Hash as an
38
38
  # argument where the key is the attribute to track (a `String` or
39
39
  # `Symbol`), which will only be counted if the value is a `Proc` which
40
40
  # returns truthily.
@@ -47,328 +47,40 @@ module PaperTrail
47
47
  # are called with `self`, i.e. the model with the paper trail). See
48
48
  # `PaperTrail::Controller.info_for_paper_trail` for how to store data
49
49
  # from the controller.
50
- # - :versions - The name to use for the versions association. Default
51
- # is `:versions`.
50
+ # - :versions - Either,
51
+ # - A String (deprecated) - The name to use for the versions
52
+ # association. Default is `:versions`.
53
+ # - A Hash - options passed to `has_many`, plus `name:` and `scope:`.
52
54
  # - :version - The name to use for the method which returns the version
53
55
  # the instance was reified from. Default is `:version`.
54
- # - :save_changes - Whether or not to save changes to the object_changes
55
- # column if it exists. Default is true
56
- # - :join_tables - If the model has a has_and_belongs_to_many relation
57
- # with an unpapertrailed model, passing the name of the association to
58
- # the join_tables option will paper trail the join table but not save
59
- # the other model, allowing reification of the association but with the
60
- # other models latest state (if the other model is paper trailed, this
61
- # option does nothing)
56
+ #
57
+ # Plugins like the experimental `paper_trail-association_tracking` gem
58
+ # may accept additional options.
59
+ #
60
+ # You can define a default set of options via the configurable
61
+ # `PaperTrail.config.has_paper_trail_defaults` hash in your applications
62
+ # initializer. The hash can contain any of the following options and will
63
+ # provide an overridable default for all models.
62
64
  #
63
65
  # @api public
64
66
  def has_paper_trail(options = {})
65
- paper_trail.setup(options)
67
+ defaults = PaperTrail.config.has_paper_trail_defaults
68
+ paper_trail.setup(defaults.merge(options))
66
69
  end
67
70
 
68
71
  # @api public
69
72
  def paper_trail
70
73
  ::PaperTrail::ModelConfig.new(self)
71
74
  end
72
-
73
- # @api private
74
- def paper_trail_deprecate(new_method, old_method = nil)
75
- old = old_method.nil? ? new_method : old_method
76
- msg = format("Use paper_trail.%s instead of %s", new_method, old)
77
- ::ActiveSupport::Deprecation.warn(msg, caller(2))
78
- end
79
-
80
- # @deprecated
81
- def paper_trail_on_destroy(*args)
82
- paper_trail_deprecate "on_destroy", "paper_trail_on_destroy"
83
- paper_trail.on_destroy(*args)
84
- end
85
-
86
- # @deprecated
87
- def paper_trail_on_update
88
- paper_trail_deprecate "on_update", "paper_trail_on_update"
89
- paper_trail.on_update
90
- end
91
-
92
- # @deprecated
93
- def paper_trail_on_create
94
- paper_trail_deprecate "on_create", "paper_trail_on_create"
95
- paper_trail.on_create
96
- end
97
-
98
- # @deprecated
99
- def paper_trail_off!
100
- paper_trail_deprecate "disable", "paper_trail_off!"
101
- paper_trail.disable
102
- end
103
-
104
- # @deprecated
105
- def paper_trail_on!
106
- paper_trail_deprecate "enable", "paper_trail_on!"
107
- paper_trail.enable
108
- end
109
-
110
- # @deprecated
111
- def paper_trail_enabled_for_model?
112
- paper_trail_deprecate "enabled?", "paper_trail_enabled_for_model?"
113
- paper_trail.enabled?
114
- end
115
-
116
- # @deprecated
117
- def paper_trail_version_class
118
- paper_trail_deprecate "version_class", "paper_trail_version_class"
119
- paper_trail.version_class
120
- end
121
75
  end
122
76
 
123
77
  # Wrap the following methods in a module so we can include them only in the
124
78
  # ActiveRecord models that declare `has_paper_trail`.
125
79
  module InstanceMethods
80
+ # @api public
126
81
  def paper_trail
127
82
  ::PaperTrail::RecordTrail.new(self)
128
83
  end
129
-
130
- # @deprecated
131
- def live?
132
- self.class.paper_trail_deprecate "live?"
133
- paper_trail.live?
134
- end
135
-
136
- # @deprecated
137
- def paper_trail_originator
138
- self.class.paper_trail_deprecate "originator", "paper_trail_originator"
139
- paper_trail.originator
140
- end
141
-
142
- # @deprecated
143
- def originator
144
- self.class.paper_trail_deprecate "originator"
145
- paper_trail.originator
146
- end
147
-
148
- # @deprecated
149
- def clear_rolled_back_versions
150
- self.class.paper_trail_deprecate "clear_rolled_back_versions"
151
- paper_trail.clear_rolled_back_versions
152
- end
153
-
154
- # @deprecated
155
- def source_version
156
- self.class.paper_trail_deprecate "source_version"
157
- paper_trail.source_version
158
- end
159
-
160
- # @deprecated
161
- def version_at(*args)
162
- self.class.paper_trail_deprecate "version_at"
163
- paper_trail.version_at(*args)
164
- end
165
-
166
- # @deprecated
167
- def versions_between(start_time, end_time, _reify_options = {})
168
- self.class.paper_trail_deprecate "versions_between"
169
- paper_trail.versions_between(start_time, end_time)
170
- end
171
-
172
- # @deprecated
173
- def previous_version
174
- self.class.paper_trail_deprecate "previous_version"
175
- paper_trail.previous_version
176
- end
177
-
178
- # @deprecated
179
- def next_version
180
- self.class.paper_trail_deprecate "next_version"
181
- paper_trail.next_version
182
- end
183
-
184
- # @deprecated
185
- def paper_trail_enabled_for_model?
186
- self.class.paper_trail_deprecate "enabled_for_model?", "paper_trail_enabled_for_model?"
187
- paper_trail.enabled_for_model?
188
- end
189
-
190
- # @deprecated
191
- def without_versioning(method = nil, &block)
192
- self.class.paper_trail_deprecate "without_versioning"
193
- paper_trail.without_versioning(method, &block)
194
- end
195
-
196
- # @deprecated
197
- def appear_as_new_record(&block)
198
- self.class.paper_trail_deprecate "appear_as_new_record"
199
- paper_trail.appear_as_new_record(&block)
200
- end
201
-
202
- # @deprecated
203
- def whodunnit(value, &block)
204
- self.class.paper_trail_deprecate "whodunnit"
205
- paper_trail.whodunnit(value, &block)
206
- end
207
-
208
- # @deprecated
209
- def touch_with_version(name = nil)
210
- self.class.paper_trail_deprecate "touch_with_version"
211
- paper_trail.touch_with_version(name)
212
- end
213
-
214
- # `record_create` is deprecated in favor of `paper_trail.record_create`,
215
- # but does not yet print a deprecation warning. When the `after_create`
216
- # callback is registered (by ModelConfig#on_create) we still refer to this
217
- # method by name, e.g.
218
- #
219
- # @model_class.after_create :record_create, if: :save_version?
220
- #
221
- # instead of using the preferred method `paper_trail.record_create`, e.g.
222
- #
223
- # @model_class.after_create { |r| r.paper_trail.record_create if r.save_version?}
224
- #
225
- # We still register the callback by name so that, if someone calls
226
- # `has_paper_trail` twice, the callback will *not* be registered twice.
227
- # Our own test suite calls `has_paper_trail` many times for the same
228
- # class.
229
- #
230
- # In the future, perhaps we should require that users only set up
231
- # PT once per class.
232
- #
233
- # @deprecated
234
- def record_create
235
- paper_trail.record_create
236
- end
237
-
238
- # See deprecation comment for `record_create`
239
- # @deprecated
240
- def record_update(force = nil)
241
- paper_trail.record_update(force)
242
- end
243
-
244
- # @deprecated
245
- def pt_record_object_changes?
246
- self.class.paper_trail_deprecate "record_object_changes?", "pt_record_object_changes?"
247
- paper_trail.record_object_changes?
248
- end
249
-
250
- # @deprecated
251
- def pt_recordable_object
252
- self.class.paper_trail_deprecate "recordable_object", "pt_recordable_object"
253
- paper_trail.recordable_object
254
- end
255
-
256
- # @deprecated
257
- def pt_recordable_object_changes
258
- self.class.paper_trail_deprecate "recordable_object_changes", "pt_recordable_object_changes"
259
- paper_trail.recordable_object_changes
260
- end
261
-
262
- # @deprecated
263
- def changes_for_paper_trail
264
- self.class.paper_trail_deprecate "changes", "changes_for_paper_trail"
265
- paper_trail.changes
266
- end
267
-
268
- # See deprecation comment for `record_create`
269
- # @deprecated
270
- def clear_version_instance!
271
- paper_trail.clear_version_instance
272
- end
273
-
274
- # See deprecation comment for `record_create`
275
- # @deprecated
276
- def reset_timestamp_attrs_for_update_if_needed!
277
- paper_trail.reset_timestamp_attrs_for_update_if_needed
278
- end
279
-
280
- # See deprecation comment for `record_create`
281
- # @deprecated
282
- def record_destroy
283
- paper_trail.record_destroy
284
- end
285
-
286
- # @deprecated
287
- def save_associations(version)
288
- self.class.paper_trail_deprecate "save_associations"
289
- paper_trail.save_associations(version)
290
- end
291
-
292
- # @deprecated
293
- def save_associations_belongs_to(version)
294
- self.class.paper_trail_deprecate "save_associations_belongs_to"
295
- paper_trail.save_associations_belongs_to(version)
296
- end
297
-
298
- # @deprecated
299
- def save_associations_has_and_belongs_to_many(version)
300
- self.class.paper_trail_deprecate(
301
- "save_associations_habtm",
302
- "save_associations_has_and_belongs_to_many"
303
- )
304
- paper_trail.save_associations_habtm(version)
305
- end
306
-
307
- # @deprecated
308
- # @api private
309
- def reset_transaction_id
310
- ::ActiveSupport::Deprecation.warn(
311
- "reset_transaction_id is deprecated, use PaperTrail.clear_transaction_id"
312
- )
313
- PaperTrail.clear_transaction_id
314
- end
315
-
316
- # @deprecated
317
- # @api private
318
- def merge_metadata(data)
319
- self.class.paper_trail_deprecate "merge_metadata"
320
- paper_trail.merge_metadata(data)
321
- end
322
-
323
- # @deprecated
324
- def attributes_before_change
325
- self.class.paper_trail_deprecate "attributes_before_change"
326
- paper_trail.attributes_before_change
327
- end
328
-
329
- # @deprecated
330
- def object_attrs_for_paper_trail
331
- self.class.paper_trail_deprecate "object_attrs_for_paper_trail"
332
- paper_trail.object_attrs_for_paper_trail
333
- end
334
-
335
- # @deprecated
336
- def changed_notably?
337
- self.class.paper_trail_deprecate "changed_notably?"
338
- paper_trail.changed_notably?
339
- end
340
-
341
- # @deprecated
342
- def ignored_attr_has_changed?
343
- self.class.paper_trail_deprecate "ignored_attr_has_changed?"
344
- paper_trail.ignored_attr_has_changed?
345
- end
346
-
347
- # @deprecated
348
- def notably_changed
349
- self.class.paper_trail_deprecate "notably_changed"
350
- paper_trail.notably_changed
351
- end
352
-
353
- # @deprecated
354
- def changed_and_not_ignored
355
- self.class.paper_trail_deprecate "changed_and_not_ignored"
356
- paper_trail.changed_and_not_ignored
357
- end
358
-
359
- # The new method is named "enabled?" for consistency.
360
- # @deprecated
361
- def paper_trail_switched_on?
362
- self.class.paper_trail_deprecate "enabled?", "paper_trail_switched_on?"
363
- paper_trail.enabled?
364
- end
365
-
366
- # @deprecated
367
- # @api private
368
- def save_version?
369
- self.class.paper_trail_deprecate "save_version?"
370
- paper_trail.save_version?
371
- end
372
84
  end
373
85
  end
374
86
  end