paper_trail 4.2.0 → 7.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (171) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/paper_trail/install_generator.rb +91 -17
  3. data/lib/generators/paper_trail/templates/add_object_changes_to_versions.rb.erb +12 -0
  4. data/lib/generators/paper_trail/templates/{add_transaction_id_column_to_versions.rb → add_transaction_id_column_to_versions.rb.erb} +3 -1
  5. data/lib/generators/paper_trail/templates/create_version_associations.rb.erb +22 -0
  6. data/lib/generators/paper_trail/templates/{create_versions.rb → create_versions.rb.erb} +9 -7
  7. data/lib/paper_trail.rb +180 -148
  8. data/lib/paper_trail/attribute_serializers/README.md +10 -0
  9. data/lib/paper_trail/attribute_serializers/cast_attribute_serializer.rb +80 -0
  10. data/lib/paper_trail/attribute_serializers/legacy_active_record_shim.rb +48 -0
  11. data/lib/paper_trail/attribute_serializers/object_attribute.rb +39 -0
  12. data/lib/paper_trail/attribute_serializers/object_changes_attribute.rb +42 -0
  13. data/lib/paper_trail/cleaner.rb +16 -10
  14. data/lib/paper_trail/config.rb +28 -27
  15. data/lib/paper_trail/frameworks/active_record/models/paper_trail/version.rb +5 -1
  16. data/lib/paper_trail/frameworks/active_record/models/paper_trail/version_association.rb +6 -2
  17. data/lib/paper_trail/frameworks/cucumber.rb +1 -0
  18. data/lib/paper_trail/frameworks/rails.rb +2 -7
  19. data/lib/paper_trail/frameworks/rails/controller.rb +20 -18
  20. data/lib/paper_trail/frameworks/rails/engine.rb +6 -1
  21. data/lib/paper_trail/frameworks/rspec.rb +17 -6
  22. data/lib/paper_trail/frameworks/rspec/helpers.rb +3 -1
  23. data/lib/paper_trail/has_paper_trail.rb +25 -503
  24. data/lib/paper_trail/model_config.rb +207 -0
  25. data/lib/paper_trail/queries/versions/where_object.rb +60 -0
  26. data/lib/paper_trail/queries/versions/where_object_changes.rb +68 -0
  27. data/lib/paper_trail/record_history.rb +2 -12
  28. data/lib/paper_trail/record_trail.rb +573 -0
  29. data/lib/paper_trail/reifier.rb +164 -215
  30. data/lib/paper_trail/reifiers/belongs_to.rb +48 -0
  31. data/lib/paper_trail/reifiers/has_and_belongs_to_many.rb +50 -0
  32. data/lib/paper_trail/reifiers/has_many.rb +110 -0
  33. data/lib/paper_trail/reifiers/has_many_through.rb +90 -0
  34. data/lib/paper_trail/reifiers/has_one.rb +76 -0
  35. data/lib/paper_trail/serializers/json.rb +16 -7
  36. data/lib/paper_trail/serializers/yaml.rb +9 -13
  37. data/lib/paper_trail/version_association_concern.rb +3 -5
  38. data/lib/paper_trail/version_concern.rb +138 -111
  39. data/lib/paper_trail/version_number.rb +10 -9
  40. metadata +95 -327
  41. data/.gitignore +0 -22
  42. data/.rspec +0 -2
  43. data/.travis.yml +0 -41
  44. data/CHANGELOG.md +0 -362
  45. data/CONTRIBUTING.md +0 -84
  46. data/Gemfile +0 -2
  47. data/MIT-LICENSE +0 -20
  48. data/README.md +0 -1535
  49. data/Rakefile +0 -30
  50. data/doc/bug_report_template.rb +0 -65
  51. data/gemfiles/ar3.gemfile +0 -61
  52. data/lib/generators/paper_trail/templates/add_object_changes_to_versions.rb +0 -10
  53. data/lib/generators/paper_trail/templates/create_version_associations.rb +0 -17
  54. data/lib/paper_trail/attributes_serialization.rb +0 -89
  55. data/lib/paper_trail/frameworks/sinatra.rb +0 -38
  56. data/paper_trail.gemspec +0 -59
  57. data/spec/generators/install_generator_spec.rb +0 -67
  58. data/spec/models/animal_spec.rb +0 -36
  59. data/spec/models/boolit_spec.rb +0 -48
  60. data/spec/models/callback_modifier_spec.rb +0 -96
  61. data/spec/models/fluxor_spec.rb +0 -19
  62. data/spec/models/gadget_spec.rb +0 -70
  63. data/spec/models/joined_version_spec.rb +0 -47
  64. data/spec/models/json_version_spec.rb +0 -103
  65. data/spec/models/kitchen/banana_spec.rb +0 -14
  66. data/spec/models/not_on_update_spec.rb +0 -19
  67. data/spec/models/post_with_status_spec.rb +0 -17
  68. data/spec/models/skipper_spec.rb +0 -46
  69. data/spec/models/thing_spec.rb +0 -11
  70. data/spec/models/version_spec.rb +0 -239
  71. data/spec/models/widget_spec.rb +0 -298
  72. data/spec/modules/paper_trail_spec.rb +0 -27
  73. data/spec/modules/version_concern_spec.rb +0 -32
  74. data/spec/modules/version_number_spec.rb +0 -44
  75. data/spec/paper_trail/config_spec.rb +0 -52
  76. data/spec/paper_trail_spec.rb +0 -66
  77. data/spec/rails_helper.rb +0 -34
  78. data/spec/requests/articles_spec.rb +0 -30
  79. data/spec/spec_helper.rb +0 -95
  80. data/spec/support/alt_db_init.rb +0 -59
  81. data/test/custom_json_serializer.rb +0 -13
  82. data/test/dummy/Rakefile +0 -7
  83. data/test/dummy/app/controllers/application_controller.rb +0 -20
  84. data/test/dummy/app/controllers/articles_controller.rb +0 -17
  85. data/test/dummy/app/controllers/test_controller.rb +0 -5
  86. data/test/dummy/app/controllers/widgets_controller.rb +0 -31
  87. data/test/dummy/app/helpers/application_helper.rb +0 -2
  88. data/test/dummy/app/models/animal.rb +0 -6
  89. data/test/dummy/app/models/article.rb +0 -16
  90. data/test/dummy/app/models/authorship.rb +0 -5
  91. data/test/dummy/app/models/book.rb +0 -9
  92. data/test/dummy/app/models/boolit.rb +0 -4
  93. data/test/dummy/app/models/callback_modifier.rb +0 -45
  94. data/test/dummy/app/models/cat.rb +0 -2
  95. data/test/dummy/app/models/chapter.rb +0 -9
  96. data/test/dummy/app/models/citation.rb +0 -5
  97. data/test/dummy/app/models/customer.rb +0 -4
  98. data/test/dummy/app/models/document.rb +0 -4
  99. data/test/dummy/app/models/dog.rb +0 -2
  100. data/test/dummy/app/models/editor.rb +0 -4
  101. data/test/dummy/app/models/editorship.rb +0 -5
  102. data/test/dummy/app/models/elephant.rb +0 -3
  103. data/test/dummy/app/models/fluxor.rb +0 -3
  104. data/test/dummy/app/models/foo_widget.rb +0 -2
  105. data/test/dummy/app/models/fruit.rb +0 -5
  106. data/test/dummy/app/models/gadget.rb +0 -3
  107. data/test/dummy/app/models/kitchen/banana.rb +0 -5
  108. data/test/dummy/app/models/legacy_widget.rb +0 -4
  109. data/test/dummy/app/models/line_item.rb +0 -4
  110. data/test/dummy/app/models/not_on_update.rb +0 -4
  111. data/test/dummy/app/models/order.rb +0 -5
  112. data/test/dummy/app/models/paragraph.rb +0 -5
  113. data/test/dummy/app/models/person.rb +0 -38
  114. data/test/dummy/app/models/post.rb +0 -3
  115. data/test/dummy/app/models/post_with_status.rb +0 -8
  116. data/test/dummy/app/models/protected_widget.rb +0 -3
  117. data/test/dummy/app/models/quotation.rb +0 -5
  118. data/test/dummy/app/models/section.rb +0 -6
  119. data/test/dummy/app/models/skipper.rb +0 -6
  120. data/test/dummy/app/models/song.rb +0 -32
  121. data/test/dummy/app/models/thing.rb +0 -3
  122. data/test/dummy/app/models/translation.rb +0 -4
  123. data/test/dummy/app/models/whatchamajigger.rb +0 -4
  124. data/test/dummy/app/models/widget.rb +0 -15
  125. data/test/dummy/app/models/wotsit.rb +0 -8
  126. data/test/dummy/app/versions/joined_version.rb +0 -5
  127. data/test/dummy/app/versions/json_version.rb +0 -3
  128. data/test/dummy/app/versions/kitchen/banana_version.rb +0 -5
  129. data/test/dummy/app/versions/post_version.rb +0 -3
  130. data/test/dummy/app/views/layouts/application.html.erb +0 -14
  131. data/test/dummy/config.ru +0 -4
  132. data/test/dummy/config/application.rb +0 -69
  133. data/test/dummy/config/boot.rb +0 -10
  134. data/test/dummy/config/database.mysql.yml +0 -19
  135. data/test/dummy/config/database.postgres.yml +0 -15
  136. data/test/dummy/config/database.sqlite.yml +0 -15
  137. data/test/dummy/config/environment.rb +0 -5
  138. data/test/dummy/config/environments/development.rb +0 -40
  139. data/test/dummy/config/environments/production.rb +0 -73
  140. data/test/dummy/config/environments/test.rb +0 -41
  141. data/test/dummy/config/initializers/backtrace_silencers.rb +0 -7
  142. data/test/dummy/config/initializers/inflections.rb +0 -10
  143. data/test/dummy/config/initializers/mime_types.rb +0 -5
  144. data/test/dummy/config/initializers/paper_trail.rb +0 -10
  145. data/test/dummy/config/initializers/secret_token.rb +0 -7
  146. data/test/dummy/config/initializers/session_store.rb +0 -8
  147. data/test/dummy/config/locales/en.yml +0 -5
  148. data/test/dummy/config/routes.rb +0 -4
  149. data/test/dummy/db/migrate/20110208155312_set_up_test_tables.rb +0 -287
  150. data/test/dummy/db/schema.rb +0 -246
  151. data/test/dummy/script/rails +0 -6
  152. data/test/functional/controller_test.rb +0 -91
  153. data/test/functional/enabled_for_controller_test.rb +0 -29
  154. data/test/functional/modular_sinatra_test.rb +0 -48
  155. data/test/functional/sinatra_test.rb +0 -49
  156. data/test/functional/thread_safety_test.rb +0 -48
  157. data/test/paper_trail_test.rb +0 -38
  158. data/test/test_helper.rb +0 -105
  159. data/test/time_travel_helper.rb +0 -15
  160. data/test/unit/associations_test.rb +0 -726
  161. data/test/unit/cleaner_test.rb +0 -182
  162. data/test/unit/inheritance_column_test.rb +0 -43
  163. data/test/unit/model_test.rb +0 -1373
  164. data/test/unit/protected_attrs_test.rb +0 -47
  165. data/test/unit/serializer_test.rb +0 -117
  166. data/test/unit/serializers/json_test.rb +0 -88
  167. data/test/unit/serializers/mixin_json_test.rb +0 -36
  168. data/test/unit/serializers/mixin_yaml_test.rb +0 -49
  169. data/test/unit/serializers/yaml_test.rb +0 -52
  170. data/test/unit/timestamp_test.rb +0 -43
  171. data/test/unit/version_test.rb +0 -119
@@ -0,0 +1,10 @@
1
+ Attribute Serializers
2
+ =====================
3
+
4
+ "Serialization" here refers to the preparation of data for insertion into a
5
+ database, particularly the `object` and `object_changes` columns in the
6
+ `versions` table.
7
+
8
+ Likewise, "deserialization" refers to any processing of data after they
9
+ have been read from the database, for example preparing the result of
10
+ `VersionConcern#changeset`.
@@ -0,0 +1,80 @@
1
+ module PaperTrail
2
+ # :nodoc:
3
+ module AttributeSerializers
4
+ # The `CastAttributeSerializer` (de)serializes model attribute values. For
5
+ # example, the string "1.99" serializes into the integer `1` when assigned
6
+ # to an attribute of type `ActiveRecord::Type::Integer`.
7
+ #
8
+ # This implementation depends on the `type_for_attribute` method, which was
9
+ # introduced in rails 4.2. In older versions of rails, we shim this method
10
+ # with `LegacyActiveRecordShim`.
11
+ class CastAttributeSerializer
12
+ def initialize(klass)
13
+ @klass = klass
14
+ end
15
+
16
+ private
17
+
18
+ # Returns a hash mapping attributes to hashes that map strings to
19
+ # integers. Example:
20
+ #
21
+ # ```
22
+ # { "status" => { "draft"=>0, "published"=>1, "archived"=>2 } }
23
+ # ```
24
+ #
25
+ # ActiveRecord::Enum was added in AR 4.1
26
+ # http://edgeguides.rubyonrails.org/4_1_release_notes.html#active-record-enums
27
+ def defined_enums
28
+ @defined_enums ||= (@klass.respond_to?(:defined_enums) ? @klass.defined_enums : {})
29
+ end
30
+ end
31
+
32
+ if ::ActiveRecord::VERSION::MAJOR >= 5
33
+ # This implementation uses AR 5's `serialize` and `deserialize`.
34
+ class CastAttributeSerializer
35
+ def serialize(attr, val)
36
+ @klass.type_for_attribute(attr).serialize(val)
37
+ end
38
+
39
+ def deserialize(attr, val)
40
+ if defined_enums[attr] && val.is_a?(::String)
41
+ # Because PT 4 used to save the string version of enums to `object_changes`
42
+ val
43
+ else
44
+ @klass.type_for_attribute(attr).deserialize(val)
45
+ end
46
+ end
47
+ end
48
+ else
49
+ # This implementation uses AR 4.2's `type_cast_for_database`. For
50
+ # versions of AR < 4.2 we provide an implementation of
51
+ # `type_cast_for_database` in our shim attribute type classes,
52
+ # `NoOpAttribute` and `SerializedAttribute`.
53
+ class CastAttributeSerializer
54
+ def serialize(attr, val)
55
+ castable_val = val
56
+ if defined_enums[attr]
57
+ # `attr` is an enum. Find the number that corresponds to `val`. If `val` is
58
+ # a number already, there won't be a corresponding entry, just use `val`.
59
+ castable_val = defined_enums[attr][val] || val
60
+ end
61
+ @klass.type_for_attribute(attr).type_cast_for_database(castable_val)
62
+ end
63
+
64
+ def deserialize(attr, val)
65
+ if defined_enums[attr] && val.is_a?(::String)
66
+ # Because PT 4 used to save the string version of enums to `object_changes`
67
+ val
68
+ else
69
+ val = @klass.type_for_attribute(attr).type_cast_from_database(val)
70
+ if defined_enums[attr]
71
+ defined_enums[attr].key(val)
72
+ else
73
+ val
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,48 @@
1
+ module PaperTrail
2
+ module AttributeSerializers
3
+ # Included into model if AR version is < 4.2. Backport Rails 4.2 and later's
4
+ # `type_for_attribute` so we can build on a common interface.
5
+ module LegacyActiveRecordShim
6
+ # An attribute which needs no processing. It is part of our backport (shim)
7
+ # of rails 4.2's attribute API. See `type_for_attribute` below.
8
+ class NoOpAttribute
9
+ def type_cast_for_database(value)
10
+ value
11
+ end
12
+
13
+ def type_cast_from_database(data)
14
+ data
15
+ end
16
+ end
17
+ NO_OP_ATTRIBUTE = NoOpAttribute.new
18
+
19
+ # An attribute which requires manual (de)serialization to/from what we get
20
+ # from the database. It is part of our backport (shim) of rails 4.2's
21
+ # attribute API. See `type_for_attribute` below.
22
+ class SerializedAttribute
23
+ def initialize(coder)
24
+ @coder = coder.respond_to?(:dump) ? coder : PaperTrail.serializer
25
+ end
26
+
27
+ def type_cast_for_database(value)
28
+ @coder.dump(value)
29
+ end
30
+
31
+ def type_cast_from_database(data)
32
+ @coder.load(data)
33
+ end
34
+ end
35
+
36
+ def type_for_attribute(attr_name)
37
+ serialized_attribute_types[attr_name.to_s] || NO_OP_ATTRIBUTE
38
+ end
39
+
40
+ def serialized_attribute_types
41
+ @attribute_types ||= Hash[serialized_attributes.map do |attr_name, coder|
42
+ [attr_name, SerializedAttribute.new(coder)]
43
+ end]
44
+ end
45
+ private :serialized_attribute_types
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,39 @@
1
+ require "paper_trail/attribute_serializers/cast_attribute_serializer"
2
+
3
+ module PaperTrail
4
+ module AttributeSerializers
5
+ # Serialize or deserialize the `version.object` column.
6
+ class ObjectAttribute
7
+ def initialize(model_class)
8
+ @model_class = model_class
9
+ end
10
+
11
+ def serialize(attributes)
12
+ alter(attributes, :serialize)
13
+ end
14
+
15
+ def deserialize(attributes)
16
+ alter(attributes, :deserialize)
17
+ end
18
+
19
+ private
20
+
21
+ # Modifies `attributes` in place.
22
+ # TODO: Return a new hash instead.
23
+ def alter(attributes, serialization_method)
24
+ # Don't serialize before values before inserting into columns of type
25
+ # `JSON` on `PostgreSQL` databases.
26
+ return attributes if object_col_is_json?
27
+
28
+ serializer = CastAttributeSerializer.new(@model_class)
29
+ attributes.each do |key, value|
30
+ attributes[key] = serializer.send(serialization_method, key, value)
31
+ end
32
+ end
33
+
34
+ def object_col_is_json?
35
+ @model_class.paper_trail.version_class.object_col_is_json?
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,42 @@
1
+ require "paper_trail/attribute_serializers/cast_attribute_serializer"
2
+
3
+ module PaperTrail
4
+ module AttributeSerializers
5
+ # Serialize or deserialize the `version.object_changes` column.
6
+ class ObjectChangesAttribute
7
+ def initialize(item_class)
8
+ @item_class = item_class
9
+ end
10
+
11
+ def serialize(changes)
12
+ alter(changes, :serialize)
13
+ end
14
+
15
+ def deserialize(changes)
16
+ alter(changes, :deserialize)
17
+ end
18
+
19
+ private
20
+
21
+ # Modifies `changes` in place.
22
+ # TODO: Return a new hash instead.
23
+ def alter(changes, serialization_method)
24
+ # Don't serialize before values before inserting into columns of type
25
+ # `JSON` on `PostgreSQL` databases.
26
+ return changes if object_changes_col_is_json?
27
+
28
+ serializer = CastAttributeSerializer.new(@item_class)
29
+ changes.clone.each do |key, change|
30
+ # `change` is an Array with two elements, representing before and after.
31
+ changes[key] = Array(change).map do |value|
32
+ serializer.send(serialization_method, key, value)
33
+ end
34
+ end
35
+ end
36
+
37
+ def object_changes_col_is_json?
38
+ @item_class.paper_trail.version_class.object_changes_col_is_json?
39
+ end
40
+ end
41
+ end
42
+ end
@@ -1,4 +1,5 @@
1
1
  module PaperTrail
2
+ # Utilities for deleting version records.
2
3
  module Cleaner
3
4
  # Destroys all but the most recent version(s) for items on a given date
4
5
  # (or on all dates). Useful for deleting drafts.
@@ -6,7 +7,8 @@ module PaperTrail
6
7
  # Options:
7
8
  #
8
9
  # - :keeping - An `integer` indicating the number of versions to be kept for
9
- # each item per date. Defaults to `1`.
10
+ # each item per date. Defaults to `1`. The most recent matching versions
11
+ # are kept.
10
12
  # - :date - Should either be a `Date` object specifying which date to
11
13
  # destroy versions for or `:all`, which will specify that all dates
12
14
  # should be cleaned. Defaults to `:all`.
@@ -14,13 +16,13 @@ module PaperTrail
14
16
  # causes all items to be cleaned. Defaults to `nil`.
15
17
  #
16
18
  def clean_versions!(options = {})
17
- options = {:keeping => 1, :date => :all}.merge(options)
18
- gather_versions(options[:item_id], options[:date]).each do |item_id, versions|
19
- group_versions_by_date(versions).each do |date, _versions|
19
+ options = { keeping: 1, date: :all }.merge(options)
20
+ gather_versions(options[:item_id], options[:date]).each do |_item_id, item_versions|
21
+ group_versions_by_date(item_versions).each do |_date, date_versions|
20
22
  # Remove the number of versions we wish to keep from the collection
21
23
  # of versions prior to destruction.
22
- _versions.pop(options[:keeping])
23
- _versions.map(&:destroy)
24
+ date_versions.pop(options[:keeping])
25
+ date_versions.map(&:destroy)
24
26
  end
25
27
  end
26
28
  end
@@ -30,10 +32,14 @@ module PaperTrail
30
32
  # Returns a hash of versions grouped by the `item_id` attribute formatted
31
33
  # like this: {:item_id => PaperTrail::Version}. If `item_id` or `date` is
32
34
  # set, versions will be narrowed to those pointing at items with those ids
33
- # that were created on specified date.
35
+ # that were created on specified date. Versions are returned in
36
+ # chronological order.
34
37
  def gather_versions(item_id = nil, date = :all)
35
- raise ArgumentError.new("`date` argument must receive a Timestamp or `:all`") unless date == :all || date.respond_to?(:to_date)
36
- versions = item_id ? PaperTrail::Version.where(:item_id => item_id) : PaperTrail::Version
38
+ unless date == :all || date.respond_to?(:to_date)
39
+ raise ArgumentError, "Expected date to be a Timestamp or :all"
40
+ end
41
+ versions = item_id ? PaperTrail::Version.where(item_id: item_id) : PaperTrail::Version
42
+ versions = versions.order(PaperTrail::Version.timestamp_sort_order)
37
43
  versions = versions.between(date.to_date, date.to_date + 1.day) unless date == :all
38
44
 
39
45
  # If `versions` has not been converted to an ActiveRecord::Relation yet,
@@ -46,7 +52,7 @@ module PaperTrail
46
52
  # versions.
47
53
  # @api private
48
54
  def group_versions_by_date(versions)
49
- versions.group_by { |v| v.send(PaperTrail.timestamp_field).to_date }
55
+ versions.group_by { |v| v.created_at.to_date }
50
56
  end
51
57
  end
52
58
  end
@@ -1,47 +1,48 @@
1
- require 'singleton'
2
- require 'paper_trail/serializers/yaml'
1
+ require "singleton"
2
+ require "paper_trail/serializers/yaml"
3
3
 
4
4
  module PaperTrail
5
+ # Global configuration affecting all threads. Some thread-specific
6
+ # configuration can be found in `paper_trail.rb`, others in `controller.rb`.
5
7
  class Config
6
8
  include Singleton
7
- attr_accessor :timestamp_field, :serializer, :version_limit
9
+ attr_accessor :serializer, :version_limit
8
10
  attr_writer :track_associations
9
11
 
10
12
  def initialize
11
- @timestamp_field = :created_at
12
- @serializer = PaperTrail::Serializers::YAML
13
- end
14
-
15
- def serialized_attributes
16
- ActiveSupport::Deprecation.warn(
17
- "PaperTrail.config.serialized_attributes is deprecated without " +
18
- "replacement and always returns false."
19
- )
20
- false
21
- end
13
+ # Variables which affect all threads, whose access is synchronized.
14
+ @mutex = Mutex.new
15
+ @enabled = true
22
16
 
23
- def serialized_attributes=(_)
24
- ActiveSupport::Deprecation.warn(
25
- "PaperTrail.config.serialized_attributes= is deprecated without " +
26
- "replacement and no longer has any effect."
27
- )
17
+ # Variables which affect all threads, whose access is *not* synchronized.
18
+ @serializer = PaperTrail::Serializers::YAML
28
19
  end
29
20
 
30
- def track_associations
31
- @track_associations.nil? ?
32
- PaperTrail::VersionAssociation.table_exists? :
21
+ # Previously, we checked `PaperTrail::VersionAssociation.table_exists?`
22
+ # here, but that proved to be problematic in situations when the database
23
+ # connection had not been established, or when the database does not exist
24
+ # yet (as with `rake db:create`).
25
+ def track_associations?
26
+ if @track_associations.nil?
27
+ ActiveSupport::Deprecation.warn <<-EOS.strip_heredoc.gsub(/\s+/, " ")
28
+ PaperTrail.config.track_associations has not been set. As of PaperTrail 5, it
29
+ defaults to false. Tracking associations is an experimental feature so
30
+ we recommend setting PaperTrail.config.track_associations = false in
31
+ your config/initializers/paper_trail.rb
32
+ EOS
33
+ false
34
+ else
33
35
  @track_associations
36
+ end
34
37
  end
35
- alias_method :track_associations?, :track_associations
36
38
 
37
39
  # Indicates whether PaperTrail is on or off. Default: true.
38
40
  def enabled
39
- value = PaperTrail.paper_trail_store.fetch(:paper_trail_enabled, true)
40
- value.nil? ? true : value
41
+ @mutex.synchronize { !!@enabled }
41
42
  end
42
43
 
43
- def enabled= enable
44
- PaperTrail.paper_trail_store[:paper_trail_enabled] = enable
44
+ def enabled=(enable)
45
+ @mutex.synchronize { @enabled = enable }
45
46
  end
46
47
  end
47
48
  end
@@ -1,6 +1,10 @@
1
- require 'paper_trail/version_concern'
1
+ require "paper_trail/version_concern"
2
2
 
3
3
  module PaperTrail
4
+ # 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.
4
8
  class Version < ::ActiveRecord::Base
5
9
  include PaperTrail::VersionConcern
6
10
  end
@@ -1,7 +1,11 @@
1
- require 'paper_trail/version_association_concern'
1
+ require "paper_trail/version_association_concern"
2
2
 
3
3
  module PaperTrail
4
+ # This is the default ActiveRecord model provided by PaperTrail. Most simple
5
+ # applications will only use this and its partner, `Version`, but it is
6
+ # possible to sub-class, extend, or even do without this model entirely.
7
+ # See the readme for details.
4
8
  class VersionAssociation < ::ActiveRecord::Base
5
9
  include PaperTrail::VersionAssociationConcern
6
10
  end
7
- end
11
+ end
@@ -8,6 +8,7 @@ end
8
8
 
9
9
  module PaperTrail
10
10
  module Cucumber
11
+ # Helper method for enabling PT in Cucumber features.
11
12
  module Extensions
12
13
  # :call-seq:
13
14
  # with_versioning
@@ -1,7 +1,2 @@
1
- require 'paper_trail/frameworks/rails/controller'
2
- require 'paper_trail/frameworks/rails/engine'
3
-
4
- module PaperTrail
5
- module Rails
6
- end
7
- end
1
+ require "paper_trail/frameworks/rails/controller"
2
+ require "paper_trail/frameworks/rails/engine"
@@ -1,24 +1,14 @@
1
1
  module PaperTrail
2
2
  module Rails
3
+ # Extensions to rails controllers. Provides convenient ways to pass certain
4
+ # information to the model layer, with `controller_info` and `whodunnit`.
5
+ # Also includes a convenient on/off switch, `enabled_for_controller`.
3
6
  module Controller
4
-
5
- def self.included(base)
6
- before = [
7
+ def self.included(controller)
8
+ controller.before_action(
7
9
  :set_paper_trail_enabled_for_controller,
8
- :set_paper_trail_whodunnit,
9
10
  :set_paper_trail_controller_info
10
- ]
11
- after = []
12
-
13
- if base.respond_to? :before_action
14
- # Rails 4+
15
- before.map {|sym| base.before_action sym }
16
- after.map {|sym| base.after_action sym }
17
- else
18
- # Rails 3.
19
- before.map {|sym| base.before_filter sym }
20
- after.map {|sym| base.after_filter sym }
21
- end
11
+ )
22
12
  end
23
13
 
24
14
  protected
@@ -76,6 +66,7 @@ module PaperTrail
76
66
 
77
67
  # Tells PaperTrail who is responsible for any changes that occur.
78
68
  def set_paper_trail_whodunnit
69
+ @set_paper_trail_whodunnit_called = true
79
70
  ::PaperTrail.whodunnit = user_for_paper_trail if ::PaperTrail.enabled_for_controller?
80
71
  end
81
72
 
@@ -85,10 +76,21 @@ module PaperTrail
85
76
  ::PaperTrail.controller_info = info_for_paper_trail if ::PaperTrail.enabled_for_controller?
86
77
  end
87
78
 
79
+ # We have removed this warning. We no longer add it as a callback.
80
+ # However, some people use `skip_after_action :warn_about_not_setting_whodunnit`,
81
+ # so removing this method would be a breaking change. We can remove it
82
+ # in the next major version.
83
+ def warn_about_not_setting_whodunnit
84
+ ::ActiveSupport::Deprecation.warn(
85
+ "warn_about_not_setting_whodunnit is a no-op and is deprecated."
86
+ )
87
+ end
88
88
  end
89
89
  end
90
+ end
90
91
 
91
- if defined?(::ActionController)
92
- ::ActiveSupport.on_load(:action_controller) { include PaperTrail::Rails::Controller }
92
+ if defined?(::ActionController)
93
+ ::ActiveSupport.on_load(:action_controller) do
94
+ include ::PaperTrail::Rails::Controller
93
95
  end
94
96
  end