paper_trail 14.0.0 → 17.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.
- checksums.yaml +4 -4
- data/lib/generators/paper_trail/install/USAGE +29 -1
- data/lib/generators/paper_trail/install/install_generator.rb +17 -5
- data/lib/generators/paper_trail/install/templates/add_object_changes_to_versions.rb.erb +2 -2
- data/lib/generators/paper_trail/install/templates/create_versions.rb.erb +11 -8
- data/lib/generators/paper_trail/migration_generator.rb +29 -2
- data/lib/generators/paper_trail/update_item_subtype/templates/update_versions_for_item_subtype.rb.erb +7 -6
- data/lib/generators/paper_trail/update_item_subtype/update_item_subtype_generator.rb +23 -2
- data/lib/paper_trail/attribute_serializers/cast_attribute_serializer.rb +1 -5
- data/lib/paper_trail/attribute_serializers/object_attribute.rb +10 -3
- data/lib/paper_trail/attribute_serializers/object_changes_attribute.rb +10 -3
- data/lib/paper_trail/compatibility.rb +2 -2
- data/lib/paper_trail/config.rb +3 -1
- data/lib/paper_trail/events/base.rb +1 -1
- data/lib/paper_trail/frameworks/active_record.rb +1 -1
- data/lib/paper_trail/frameworks/cucumber.rb +1 -1
- data/lib/paper_trail/frameworks/rails/railtie.rb +5 -1
- data/lib/paper_trail/frameworks/rspec.rb +8 -8
- data/lib/paper_trail/has_paper_trail.rb +6 -0
- data/lib/paper_trail/model_config.rb +8 -7
- data/lib/paper_trail/queries/versions/where_object.rb +1 -1
- data/lib/paper_trail/queries/versions/where_object_changes.rb +1 -1
- data/lib/paper_trail/queries/versions/where_object_changes_from.rb +1 -1
- data/lib/paper_trail/queries/versions/where_object_changes_to.rb +1 -1
- data/lib/paper_trail/record_trail.rb +41 -15
- data/lib/paper_trail/reifier.rb +3 -3
- data/lib/paper_trail/serializers/yaml.rb +1 -1
- data/lib/paper_trail/version_concern.rb +1 -1
- data/lib/paper_trail/version_number.rb +1 -1
- data/lib/paper_trail.rb +4 -0
- metadata +111 -28
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ce4b87054886d17b9dea51dfcf6e9ddc948eaf331417b8dc5b992793e177a670
|
|
4
|
+
data.tar.gz: 32f2ff0f24978fe54e08a65dfe8c83ec023eaaf9ab676c0f791b398907a8fc80
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 772518531867cafb80017ebbb42837412fc67b80ec9416cfc9269595084e266f312609115171868b4124747769f1aba03fd5ee1b932691b52128aaec6fa2c583
|
|
7
|
+
data.tar.gz: 3b28ed9bbbf1fef2eac6d106c5fedcb1566b88d7877782e115130f4f8386f5e6bf60f4123edc1518e41478b918fac9c371c98fea5e0b49745fcd384cffa85baa
|
|
@@ -1,3 +1,31 @@
|
|
|
1
1
|
Description:
|
|
2
2
|
Generates (but does not run) a migration to add a versions table. Also generates an initializer
|
|
3
|
-
file for configuring PaperTrail.
|
|
3
|
+
file for configuring PaperTrail. Can be customized by providing a Version class name.
|
|
4
|
+
See section 5.c. Generators in README.md for more information.
|
|
5
|
+
|
|
6
|
+
Examples:
|
|
7
|
+
rails generate paper_trail:install
|
|
8
|
+
|
|
9
|
+
This will create:
|
|
10
|
+
db/migrate/[TIMESTAMP]_create_versions.rb
|
|
11
|
+
config/initializers/paper_trail.rb
|
|
12
|
+
|
|
13
|
+
rails generate paper_trail:install --with-changes
|
|
14
|
+
|
|
15
|
+
This will create:
|
|
16
|
+
db/migrate/[TIMESTAMP]_create_versions.rb
|
|
17
|
+
db/migrate/[TIMESTAMP]_add_object_changes_to_versions.rb
|
|
18
|
+
config/initializers/paper_trail.rb
|
|
19
|
+
|
|
20
|
+
rails generate paper_trail:install CommentVersion
|
|
21
|
+
|
|
22
|
+
This will create:
|
|
23
|
+
db/migrate/[TIMESTAMP]_create_comment_versions.rb
|
|
24
|
+
config/initializers/paper_trail.rb
|
|
25
|
+
|
|
26
|
+
rails generate paper_trail:install ProductVersion --with-changes --uuid
|
|
27
|
+
|
|
28
|
+
This will create:
|
|
29
|
+
db/migrate/[TIMESTAMP]_create_product_versions.rb
|
|
30
|
+
db/migrate/[TIMESTAMP]_add_object_changes_to_product_versions.rb
|
|
31
|
+
config/initializers/paper_trail.rb
|
|
@@ -27,18 +27,21 @@ module PaperTrail
|
|
|
27
27
|
desc: "Use uuid instead of bigint for item_id type (use only if tables use UUIDs)"
|
|
28
28
|
)
|
|
29
29
|
|
|
30
|
-
desc "Generates (but does not run) a migration to add a versions table." \
|
|
31
|
-
"
|
|
30
|
+
desc "Generates (but does not run) a migration to add a versions table. " \
|
|
31
|
+
"Can be customized by providing a Version class name. " \
|
|
32
|
+
"See section 5.c. Generators in README.md for more information."
|
|
32
33
|
|
|
33
34
|
def create_migration_file
|
|
35
|
+
# Use the table_name to create the proper migration filename
|
|
34
36
|
add_paper_trail_migration(
|
|
35
|
-
"
|
|
37
|
+
"create_#{table_name}",
|
|
36
38
|
item_type_options: item_type_options,
|
|
37
39
|
versions_table_options: versions_table_options,
|
|
38
|
-
item_id_type_options: item_id_type_options
|
|
40
|
+
item_id_type_options: item_id_type_options,
|
|
41
|
+
version_table_primary_key_type: version_table_primary_key_type
|
|
39
42
|
)
|
|
40
43
|
if options.with_changes?
|
|
41
|
-
add_paper_trail_migration("
|
|
44
|
+
add_paper_trail_migration("add_object_changes_to_#{table_name}")
|
|
42
45
|
end
|
|
43
46
|
end
|
|
44
47
|
|
|
@@ -49,6 +52,15 @@ module PaperTrail
|
|
|
49
52
|
options.uuid? ? "string" : "bigint"
|
|
50
53
|
end
|
|
51
54
|
|
|
55
|
+
# To use uuid for version table primary key
|
|
56
|
+
def version_table_primary_key_type
|
|
57
|
+
if options.uuid?
|
|
58
|
+
", id: :uuid"
|
|
59
|
+
else
|
|
60
|
+
""
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
52
64
|
# MySQL 5.6 utf8mb4 limit is 191 chars for keys used in indexes.
|
|
53
65
|
# See https://github.com/paper-trail-gem/paper_trail/issues/651
|
|
54
66
|
def item_type_options
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# This migration adds the optional `object_changes` column, in which PaperTrail
|
|
2
2
|
# will store the `changes` diff for each update event. See the readme for
|
|
3
3
|
# details.
|
|
4
|
-
class
|
|
4
|
+
class AddObjectChangesTo<%= version_class_name.pluralize %> < ActiveRecord::Migration<%= migration_version %>
|
|
5
5
|
# The largest text column available in all supported RDBMS.
|
|
6
6
|
# See `create_versions.rb` for details.
|
|
7
7
|
TEXT_BYTES = 1_073_741_823
|
|
8
8
|
|
|
9
9
|
def change
|
|
10
|
-
add_column
|
|
10
|
+
add_column :<%= table_name %>, :object_changes, :text, limit: TEXT_BYTES
|
|
11
11
|
end
|
|
12
12
|
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# This migration creates the
|
|
1
|
+
# This migration creates the `<%= table_name %>` table for the <%= version_class_name %> class.
|
|
2
2
|
# All other migrations PT provides are optional.
|
|
3
|
-
class
|
|
3
|
+
class Create<%= version_class_name.pluralize %> < ActiveRecord::Migration<%= migration_version %>
|
|
4
4
|
|
|
5
5
|
# The largest text column available in all supported RDBMS is
|
|
6
6
|
# 1024^3 - 1 bytes, roughly one gibibyte. We specify a size
|
|
@@ -9,12 +9,10 @@ class CreateVersions < ActiveRecord::Migration<%= migration_version %>
|
|
|
9
9
|
TEXT_BYTES = 1_073_741_823
|
|
10
10
|
|
|
11
11
|
def change
|
|
12
|
-
create_table
|
|
13
|
-
|
|
14
|
-
t
|
|
15
|
-
t.string :event, null: false
|
|
12
|
+
create_table :<%= table_name %><%= versions_table_options %><%= version_table_primary_key_type %> do |t|
|
|
13
|
+
# Consider using bigint type for performance if you are going to store only numeric ids.
|
|
14
|
+
# t.bigint :whodunnit
|
|
16
15
|
t.string :whodunnit
|
|
17
|
-
t.text :object, limit: TEXT_BYTES
|
|
18
16
|
|
|
19
17
|
# Known issue in MySQL: fractional second precision
|
|
20
18
|
# -------------------------------------------------
|
|
@@ -32,7 +30,12 @@ class CreateVersions < ActiveRecord::Migration<%= migration_version %>
|
|
|
32
30
|
# MySQL users should use the following line for `created_at`
|
|
33
31
|
# t.datetime :created_at, limit: 6
|
|
34
32
|
t.datetime :created_at
|
|
33
|
+
|
|
34
|
+
t.<%= item_id_type_options %> :item_id, null: false
|
|
35
|
+
t.string :item_type<%= item_type_options %>
|
|
36
|
+
t.string :event, null: false
|
|
37
|
+
t.text :object, limit: TEXT_BYTES
|
|
35
38
|
end
|
|
36
|
-
add_index
|
|
39
|
+
add_index :<%= table_name %>, %i[item_type item_id]
|
|
37
40
|
end
|
|
38
41
|
end
|
|
@@ -8,6 +8,10 @@ module PaperTrail
|
|
|
8
8
|
class MigrationGenerator < ::Rails::Generators::Base
|
|
9
9
|
include ::Rails::Generators::Migration
|
|
10
10
|
|
|
11
|
+
# Define arguments for the generator
|
|
12
|
+
argument :version_class_name, type: :string, default: "Version",
|
|
13
|
+
desc: "The name of the Version class (e.g., CommentVersion)"
|
|
14
|
+
|
|
11
15
|
def self.next_migration_number(dirname)
|
|
12
16
|
::ActiveRecord::Generators::Base.next_migration_number(dirname)
|
|
13
17
|
end
|
|
@@ -19,10 +23,17 @@ module PaperTrail
|
|
|
19
23
|
if self.class.migration_exists?(migration_dir, template)
|
|
20
24
|
::Kernel.warn "Migration already exists: #{template}"
|
|
21
25
|
else
|
|
26
|
+
# Map the dynamic template name to the actual template file
|
|
27
|
+
template_file = map_template_name(template)
|
|
28
|
+
|
|
22
29
|
migration_template(
|
|
23
|
-
"#{
|
|
30
|
+
"#{template_file}.rb.erb",
|
|
24
31
|
"db/migrate/#{template}.rb",
|
|
25
|
-
{
|
|
32
|
+
{
|
|
33
|
+
migration_version: migration_version,
|
|
34
|
+
table_name: table_name,
|
|
35
|
+
version_class_name: version_class_name
|
|
36
|
+
}.merge(extra_options)
|
|
26
37
|
)
|
|
27
38
|
end
|
|
28
39
|
end
|
|
@@ -34,5 +45,21 @@ module PaperTrail
|
|
|
34
45
|
ActiveRecord::VERSION::MINOR
|
|
35
46
|
)
|
|
36
47
|
end
|
|
48
|
+
|
|
49
|
+
# Convert Version class name to table name using Rails conventions
|
|
50
|
+
def table_name
|
|
51
|
+
version_class_name.underscore.pluralize
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Map the dynamic template name to the actual template file
|
|
55
|
+
def map_template_name(template)
|
|
56
|
+
if template.start_with?("create_")
|
|
57
|
+
"create_versions"
|
|
58
|
+
elsif template.start_with?("add_object_changes_to_")
|
|
59
|
+
"add_object_changes_to_versions"
|
|
60
|
+
else
|
|
61
|
+
template
|
|
62
|
+
end
|
|
63
|
+
end
|
|
37
64
|
end
|
|
38
65
|
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# This migration updates existing `versions` that have `item_type` that refers to
|
|
2
2
|
# the base_class, and changes them to refer to the subclass instead.
|
|
3
|
-
class
|
|
3
|
+
class Update<%= version_class_name.pluralize %>ForItemSubtype < ActiveRecord::Migration<%= migration_version %>
|
|
4
4
|
include ActionView::Helpers::TextHelper
|
|
5
5
|
def up
|
|
6
6
|
<%=
|
|
@@ -18,7 +18,8 @@ class UpdateVersionsForItemSubtype < ActiveRecord::Migration<%= migration_versio
|
|
|
18
18
|
# # Versions of item_type "Plant" with IDs between 42 and 1337 will be updated based on `genus`
|
|
19
19
|
# hints = {"Animal"=>{1..4=>"species"}, "Plant"=>{42..1337=>"genus"}}
|
|
20
20
|
hint_descriptions = ""
|
|
21
|
-
hints
|
|
21
|
+
# Use @hints over args to not break the test itself since args could now include --version_class_name=CommentVersion
|
|
22
|
+
hints = (@hints || []).inject(Hash.new{|h, k| h[k] = {}}) do |s, v|
|
|
22
23
|
klass, column, range = parse_custom_entry(v)
|
|
23
24
|
hint_descriptions << " # Versions of item_type \"#{klass}\" with IDs between #{
|
|
24
25
|
range.first} and #{range.last} will be updated based on \`#{column}\`\n"
|
|
@@ -32,7 +33,7 @@ class UpdateVersionsForItemSubtype < ActiveRecord::Migration<%= migration_versio
|
|
|
32
33
|
%>
|
|
33
34
|
# Find all ActiveRecord models mentioned in existing versions
|
|
34
35
|
changes = Hash.new { |h, k| h[k] = [] }
|
|
35
|
-
model_names =
|
|
36
|
+
model_names = <%= fully_qualified_version_class_name %>.select(:item_type).distinct
|
|
36
37
|
model_names.map(&:item_type).each do |model_name|
|
|
37
38
|
hint = hints[model_name] if defined?(hints)
|
|
38
39
|
begin
|
|
@@ -40,7 +41,7 @@ class UpdateVersionsForItemSubtype < ActiveRecord::Migration<%= migration_versio
|
|
|
40
41
|
# Actually implements an inheritance_column? (Usually "type")
|
|
41
42
|
has_inheritance_column = klass.columns.map(&:name).include?(klass.inheritance_column)
|
|
42
43
|
# Find domain of types stored in PaperTrail versions
|
|
43
|
-
|
|
44
|
+
<%= fully_qualified_version_class_name %>.where(item_type: model_name, item_subtype: nil).select(:id, :object, :object_changes).each do |obj|
|
|
44
45
|
if (object_detail = PaperTrail.serializer.load(obj.object || obj.object_changes))
|
|
45
46
|
is_found = false
|
|
46
47
|
subtype_name = nil
|
|
@@ -72,11 +73,11 @@ class UpdateVersionsForItemSubtype < ActiveRecord::Migration<%= migration_versio
|
|
|
72
73
|
v.sort.each do |id|
|
|
73
74
|
block_of_ids << id
|
|
74
75
|
if (id_count += 1) % 100 == 0
|
|
75
|
-
num_updated +=
|
|
76
|
+
num_updated += <%= fully_qualified_version_class_name %>.where(id: block_of_ids).update_all(item_subtype: k)
|
|
76
77
|
block_of_ids = []
|
|
77
78
|
end
|
|
78
79
|
end
|
|
79
|
-
num_updated +=
|
|
80
|
+
num_updated += <%= fully_qualified_version_class_name %>.where(id: block_of_ids).update_all(item_subtype: k)
|
|
80
81
|
if num_updated > 0
|
|
81
82
|
say "Associated #{pluralize(num_updated, 'record')} to #{k}", subitem: true
|
|
82
83
|
end
|
|
@@ -7,13 +7,34 @@ module PaperTrail
|
|
|
7
7
|
class UpdateItemSubtypeGenerator < MigrationGenerator
|
|
8
8
|
source_root File.expand_path("templates", __dir__)
|
|
9
9
|
|
|
10
|
+
# Remove the inherited version_class_name argument as we use an option instead
|
|
11
|
+
remove_argument :version_class_name
|
|
12
|
+
|
|
13
|
+
argument :hints, type: :array, default: [], banner: "hint1 hint2"
|
|
14
|
+
|
|
15
|
+
class_option :version_class_name,
|
|
16
|
+
type: :string,
|
|
17
|
+
default: "Version",
|
|
18
|
+
aliases: ["-v"],
|
|
19
|
+
desc: "The name of the Version class (e.g., CommentVersion)"
|
|
20
|
+
|
|
10
21
|
desc(
|
|
11
|
-
"Generates (but does not run) a migration to update item_subtype for "\
|
|
22
|
+
"Generates (but does not run) a migration to update item_subtype for " \
|
|
12
23
|
"STI entries in an existing versions table."
|
|
13
24
|
)
|
|
14
25
|
|
|
15
26
|
def create_migration_file
|
|
16
|
-
add_paper_trail_migration("
|
|
27
|
+
add_paper_trail_migration("update_#{table_name}_for_item_subtype", sti_type_options: options)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Return the version class name from options
|
|
31
|
+
def version_class_name
|
|
32
|
+
options[:version_class_name]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Return the fully qualified class name for use in ERB templates
|
|
36
|
+
def fully_qualified_version_class_name
|
|
37
|
+
version_class_name == "Version" ? "PaperTrail::Version" : version_class_name
|
|
17
38
|
end
|
|
18
39
|
end
|
|
19
40
|
end
|
|
@@ -32,7 +32,7 @@ module PaperTrail
|
|
|
32
32
|
if defined_enums[attr] && val.is_a?(::String)
|
|
33
33
|
# Because PT 4 used to save the string version of enums to `object_changes`
|
|
34
34
|
val
|
|
35
|
-
elsif
|
|
35
|
+
elsif val.is_a?(ActiveRecord::Type::Time::Value)
|
|
36
36
|
# Because Rails 7 time attribute throws a delegation error when you deserialize
|
|
37
37
|
# it with the factory.
|
|
38
38
|
# See ActiveRecord::Type::Time::Value crashes when loaded from YAML on rails 7.0
|
|
@@ -43,10 +43,6 @@ module PaperTrail
|
|
|
43
43
|
end
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
-
def rails_gte_7_0?
|
|
47
|
-
::ActiveRecord.gem_version >= ::Gem::Version.new("7.0.0")
|
|
48
|
-
end
|
|
49
|
-
|
|
50
46
|
def serialize(attr, val)
|
|
51
47
|
AttributeSerializerFactory.for(@klass, attr).serialize(val)
|
|
52
48
|
end
|
|
@@ -8,6 +8,9 @@ module PaperTrail
|
|
|
8
8
|
class ObjectAttribute
|
|
9
9
|
def initialize(model_class)
|
|
10
10
|
@model_class = model_class
|
|
11
|
+
|
|
12
|
+
# ActiveRecord since 7.0 has a built-in encryption mechanism
|
|
13
|
+
@encrypted_attributes = @model_class.encrypted_attributes&.map(&:to_s)
|
|
11
14
|
end
|
|
12
15
|
|
|
13
16
|
def serialize(attributes)
|
|
@@ -23,14 +26,18 @@ module PaperTrail
|
|
|
23
26
|
# Modifies `attributes` in place.
|
|
24
27
|
# TODO: Return a new hash instead.
|
|
25
28
|
def alter(attributes, serialization_method)
|
|
26
|
-
# Don't serialize before values before inserting into columns of type
|
|
29
|
+
# Don't serialize non-encrypted before values before inserting into columns of type
|
|
27
30
|
# `JSON` on `PostgreSQL` databases.
|
|
28
|
-
|
|
31
|
+
attributes_to_serialize =
|
|
32
|
+
object_col_is_json? ? attributes.slice(*@encrypted_attributes) : attributes
|
|
33
|
+
return attributes if attributes_to_serialize.blank?
|
|
29
34
|
|
|
30
35
|
serializer = CastAttributeSerializer.new(@model_class)
|
|
31
|
-
|
|
36
|
+
attributes_to_serialize.each do |key, value|
|
|
32
37
|
attributes[key] = serializer.send(serialization_method, key, value)
|
|
33
38
|
end
|
|
39
|
+
|
|
40
|
+
attributes
|
|
34
41
|
end
|
|
35
42
|
|
|
36
43
|
def object_col_is_json?
|
|
@@ -8,6 +8,9 @@ module PaperTrail
|
|
|
8
8
|
class ObjectChangesAttribute
|
|
9
9
|
def initialize(item_class)
|
|
10
10
|
@item_class = item_class
|
|
11
|
+
|
|
12
|
+
# ActiveRecord since 7.0 has a built-in encryption mechanism
|
|
13
|
+
@encrypted_attributes = @item_class.encrypted_attributes&.map(&:to_s)
|
|
11
14
|
end
|
|
12
15
|
|
|
13
16
|
def serialize(changes)
|
|
@@ -23,17 +26,21 @@ module PaperTrail
|
|
|
23
26
|
# Modifies `changes` in place.
|
|
24
27
|
# TODO: Return a new hash instead.
|
|
25
28
|
def alter(changes, serialization_method)
|
|
26
|
-
# Don't serialize before values before inserting into columns of type
|
|
29
|
+
# Don't serialize non-encrypted before values before inserting into columns of type
|
|
27
30
|
# `JSON` on `PostgreSQL` databases.
|
|
28
|
-
|
|
31
|
+
changes_to_serialize =
|
|
32
|
+
object_changes_col_is_json? ? changes.slice(*@encrypted_attributes) : changes.clone
|
|
33
|
+
return changes if changes_to_serialize.blank?
|
|
29
34
|
|
|
30
35
|
serializer = CastAttributeSerializer.new(@item_class)
|
|
31
|
-
|
|
36
|
+
changes_to_serialize.each do |key, change|
|
|
32
37
|
# `change` is an Array with two elements, representing before and after.
|
|
33
38
|
changes[key] = Array(change).map do |value|
|
|
34
39
|
serializer.send(serialization_method, key, value)
|
|
35
40
|
end
|
|
36
41
|
end
|
|
42
|
+
|
|
43
|
+
changes
|
|
37
44
|
end
|
|
38
45
|
|
|
39
46
|
def object_changes_col_is_json?
|
|
@@ -17,8 +17,8 @@ module PaperTrail
|
|
|
17
17
|
# newer rails versions. Most PT users should avoid incompatible rails
|
|
18
18
|
# versions.
|
|
19
19
|
module Compatibility
|
|
20
|
-
ACTIVERECORD_GTE = ">=
|
|
21
|
-
ACTIVERECORD_LT = "<
|
|
20
|
+
ACTIVERECORD_GTE = ">= 7.1" # enforced in gemspec
|
|
21
|
+
ACTIVERECORD_LT = "< 8.2" # not enforced in gemspec
|
|
22
22
|
|
|
23
23
|
E_INCOMPATIBLE_AR = <<-EOS
|
|
24
24
|
PaperTrail %s is not compatible with ActiveRecord %s. We allow PT
|
data/lib/paper_trail/config.rb
CHANGED
|
@@ -14,7 +14,8 @@ module PaperTrail
|
|
|
14
14
|
:object_changes_adapter,
|
|
15
15
|
:serializer,
|
|
16
16
|
:version_limit,
|
|
17
|
-
:has_paper_trail_defaults
|
|
17
|
+
:has_paper_trail_defaults,
|
|
18
|
+
:version_error_behavior
|
|
18
19
|
)
|
|
19
20
|
|
|
20
21
|
def initialize
|
|
@@ -25,6 +26,7 @@ module PaperTrail
|
|
|
25
26
|
# Variables which affect all threads, whose access is *not* synchronized.
|
|
26
27
|
@serializer = PaperTrail::Serializers::YAML
|
|
27
28
|
@has_paper_trail_defaults = {}
|
|
29
|
+
@version_error_behavior = :legacy
|
|
28
30
|
end
|
|
29
31
|
|
|
30
32
|
# Indicates whether PaperTrail is on or off. Default: true.
|
|
@@ -157,7 +157,7 @@ module PaperTrail
|
|
|
157
157
|
# @api private
|
|
158
158
|
def ignored_attr_has_changed?
|
|
159
159
|
ignored = calculated_ignored_array + @record.paper_trail_options[:skip]
|
|
160
|
-
ignored.any? && (
|
|
160
|
+
ignored.any? && changed_in_latest_version.intersect?(ignored)
|
|
161
161
|
end
|
|
162
162
|
|
|
163
163
|
# Rails 5.1 changed the API of `ActiveRecord::Dirty`. See
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# Either ActiveRecord has already been loaded by the Lazy Load Hook in our
|
|
4
4
|
# Railtie, or else we load it now.
|
|
5
5
|
require "active_record"
|
|
6
|
-
|
|
6
|
+
PaperTrail::Compatibility.check_activerecord(ActiveRecord.gem_version)
|
|
7
7
|
|
|
8
8
|
# Now we can load the parts of PT that depend on AR.
|
|
9
9
|
require "paper_trail/has_paper_trail"
|
|
@@ -10,7 +10,7 @@ module PaperTrail
|
|
|
10
10
|
# We specify `before: "load_config_initializers"` to ensure that the PT
|
|
11
11
|
# initializer happens before "app initializers" (those defined in
|
|
12
12
|
# the app's `config/initalizers`).
|
|
13
|
-
initializer "paper_trail", before: "load_config_initializers" do
|
|
13
|
+
initializer "paper_trail", before: "load_config_initializers" do |app|
|
|
14
14
|
# `on_load` is a "lazy load hook". It "declares a block that will be
|
|
15
15
|
# executed when a Rails component is fully loaded". (See
|
|
16
16
|
# `active_support/lazy_load_hooks.rb`)
|
|
@@ -25,6 +25,10 @@ module PaperTrail
|
|
|
25
25
|
ActiveSupport.on_load(:active_record) do
|
|
26
26
|
require "paper_trail/frameworks/active_record"
|
|
27
27
|
end
|
|
28
|
+
|
|
29
|
+
if Gem::Version.new(::Rails::VERSION::STRING) >= Gem::Version.new("7.1")
|
|
30
|
+
app.deprecators[:paper_trail] = PaperTrail.deprecator
|
|
31
|
+
end
|
|
28
32
|
end
|
|
29
33
|
end
|
|
30
34
|
end
|
|
@@ -5,24 +5,24 @@ require "rspec/matchers"
|
|
|
5
5
|
require "paper_trail/frameworks/rspec/helpers"
|
|
6
6
|
|
|
7
7
|
RSpec.configure do |config|
|
|
8
|
-
config.include
|
|
9
|
-
config.extend
|
|
8
|
+
config.include PaperTrail::RSpec::Helpers::InstanceMethods
|
|
9
|
+
config.extend PaperTrail::RSpec::Helpers::ClassMethods
|
|
10
10
|
|
|
11
11
|
config.before(:each) do
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
PaperTrail.enabled = false
|
|
13
|
+
PaperTrail.request.enabled = true
|
|
14
|
+
PaperTrail.request.whodunnit = nil
|
|
15
|
+
PaperTrail.request.controller_info = {} if defined?(Rails) && defined?(RSpec::Rails)
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
config.before(:each, versioning: true) do
|
|
19
|
-
|
|
19
|
+
PaperTrail.enabled = true
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
RSpec::Matchers.define :be_versioned do
|
|
24
24
|
# check to see if the model has `has_paper_trail` declared on it
|
|
25
|
-
match { |actual| actual.is_a?(
|
|
25
|
+
match { |actual| actual.is_a?(PaperTrail::Model::InstanceMethods) }
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
RSpec::Matchers.define :have_a_version_with do |attributes|
|
|
@@ -53,6 +53,10 @@ module PaperTrail
|
|
|
53
53
|
# - A Hash - options passed to `has_many`, plus `name:` and `scope:`.
|
|
54
54
|
# - :version - The name to use for the method which returns the version
|
|
55
55
|
# the instance was reified from. Default is `:version`.
|
|
56
|
+
# - :synchronize_version_creation_timestamp - By default, paper trail
|
|
57
|
+
# sets the `created_at` field for a new Version equal to the `updated_at`
|
|
58
|
+
# column of the model being updated. If you instead want `created_at` to
|
|
59
|
+
# populate with the current timestamp, set this option to `false`.
|
|
56
60
|
#
|
|
57
61
|
# Plugins like the experimental `paper_trail-association_tracking` gem
|
|
58
62
|
# may accept additional options.
|
|
@@ -64,6 +68,8 @@ module PaperTrail
|
|
|
64
68
|
#
|
|
65
69
|
# @api public
|
|
66
70
|
def has_paper_trail(options = {})
|
|
71
|
+
raise Error, "has_paper_trail must be called only once" if self < InstanceMethods
|
|
72
|
+
|
|
67
73
|
defaults = PaperTrail.config.has_paper_trail_defaults
|
|
68
74
|
paper_trail.setup(defaults.merge(options))
|
|
69
75
|
end
|
|
@@ -4,7 +4,7 @@ module PaperTrail
|
|
|
4
4
|
# Configures an ActiveRecord model, mostly at application boot time, but also
|
|
5
5
|
# sometimes mid-request, with methods like enable/disable.
|
|
6
6
|
class ModelConfig
|
|
7
|
-
E_CANNOT_RECORD_AFTER_DESTROY =
|
|
7
|
+
E_CANNOT_RECORD_AFTER_DESTROY = <<~STR
|
|
8
8
|
paper_trail.on_destroy(:after) is incompatible with ActiveRecord's
|
|
9
9
|
belongs_to_required_by_default. Use on_destroy(:before)
|
|
10
10
|
or disable belongs_to_required_by_default.
|
|
@@ -49,7 +49,7 @@ module PaperTrail
|
|
|
49
49
|
def on_destroy(recording_order = "before")
|
|
50
50
|
assert_valid_recording_order_for_on_destroy(recording_order)
|
|
51
51
|
@model_class.send(
|
|
52
|
-
"#{recording_order}_destroy",
|
|
52
|
+
:"#{recording_order}_destroy",
|
|
53
53
|
lambda do |r|
|
|
54
54
|
return unless r.paper_trail.save_version?
|
|
55
55
|
r.paper_trail.record_destroy(recording_order)
|
|
@@ -82,8 +82,9 @@ module PaperTrail
|
|
|
82
82
|
|
|
83
83
|
# Adds a callback that records a version after a "touch" event.
|
|
84
84
|
#
|
|
85
|
-
# Rails < 6.0
|
|
86
|
-
# a `touch`.
|
|
85
|
+
# Rails < 6.0 (no longer supported by PT) had a bug where dirty-tracking
|
|
86
|
+
# did not occur during a `touch`.
|
|
87
|
+
# (https://github.com/rails/rails/issues/33429) See also:
|
|
87
88
|
# https://github.com/paper-trail-gem/paper_trail/issues/1121
|
|
88
89
|
# https://github.com/paper-trail-gem/paper_trail/issues/1161
|
|
89
90
|
# https://github.com/paper-trail-gem/paper_trail/pull/1285
|
|
@@ -155,7 +156,7 @@ module PaperTrail
|
|
|
155
156
|
# @api private - `version_class_name`
|
|
156
157
|
@model_class.class_attribute :version_class_name
|
|
157
158
|
if options[:class_name]
|
|
158
|
-
|
|
159
|
+
PaperTrail.deprecator.warn(
|
|
159
160
|
format(
|
|
160
161
|
DPR_CLASS_NAME_OPTION,
|
|
161
162
|
class_name: options[:class_name].inspect
|
|
@@ -191,7 +192,7 @@ module PaperTrail
|
|
|
191
192
|
def ensure_versions_option_is_hash(options)
|
|
192
193
|
unless options[:versions].is_a?(Hash)
|
|
193
194
|
if options[:versions]
|
|
194
|
-
|
|
195
|
+
PaperTrail.deprecator.warn(
|
|
195
196
|
format(
|
|
196
197
|
DPR_PASSING_ASSOC_NAME_DIRECTLY_TO_VERSIONS_OPTION,
|
|
197
198
|
versions_name: options[:versions].inspect
|
|
@@ -235,7 +236,7 @@ module PaperTrail
|
|
|
235
236
|
|
|
236
237
|
def setup_callbacks_from_options(options_on = [])
|
|
237
238
|
options_on.each do |event|
|
|
238
|
-
public_send("on_#{event}")
|
|
239
|
+
public_send(:"on_#{event}")
|
|
239
240
|
end
|
|
240
241
|
end
|
|
241
242
|
|
|
@@ -39,7 +39,7 @@ module PaperTrail
|
|
|
39
39
|
values = []
|
|
40
40
|
@attributes.each do |field, value|
|
|
41
41
|
predicates.push "object->>? = ?"
|
|
42
|
-
values.
|
|
42
|
+
values.push(field, value.to_s)
|
|
43
43
|
end
|
|
44
44
|
sql = predicates.join(" and ")
|
|
45
45
|
@version_model_class.where(sql, *values)
|
|
@@ -53,7 +53,7 @@ module PaperTrail
|
|
|
53
53
|
predicates.push(
|
|
54
54
|
"((object_changes->>? ILIKE ?) OR (object_changes->>? ILIKE ?))"
|
|
55
55
|
)
|
|
56
|
-
values.
|
|
56
|
+
values.push(field, "[#{value.to_json},%", field, "[%,#{value.to_json}]%")
|
|
57
57
|
end
|
|
58
58
|
sql = predicates.join(" and ")
|
|
59
59
|
@version_model_class.where(sql, *values)
|
|
@@ -22,7 +22,7 @@ module PaperTrail
|
|
|
22
22
|
# Invoked via`after_update` callback for when a previous version is
|
|
23
23
|
# reified and then saved.
|
|
24
24
|
def clear_version_instance
|
|
25
|
-
@record.send("#{@record.class.version_association_name}=", nil)
|
|
25
|
+
@record.send(:"#{@record.class.version_association_name}=", nil)
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
# Returns true if this instance is the current, live one;
|
|
@@ -64,6 +64,8 @@ module PaperTrail
|
|
|
64
64
|
# of versions_assoc.build?, the association cache is unaware. So, we
|
|
65
65
|
# invalidate the `versions` association cache with `reset`.
|
|
66
66
|
versions.reset
|
|
67
|
+
rescue StandardError => e
|
|
68
|
+
handle_version_errors e, version, :create
|
|
67
69
|
end
|
|
68
70
|
end
|
|
69
71
|
|
|
@@ -81,12 +83,13 @@ module PaperTrail
|
|
|
81
83
|
# `data_for_destroy` but PT-AT still does.
|
|
82
84
|
data = event.data.merge(data_for_destroy)
|
|
83
85
|
|
|
84
|
-
version = @record.class.paper_trail.version_class.
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
else
|
|
86
|
+
version = @record.class.paper_trail.version_class.new(data)
|
|
87
|
+
begin
|
|
88
|
+
version.save!
|
|
88
89
|
assign_and_reset_version_association(version)
|
|
89
90
|
version
|
|
91
|
+
rescue StandardError => e
|
|
92
|
+
handle_version_errors e, version, :destroy
|
|
90
93
|
end
|
|
91
94
|
end
|
|
92
95
|
|
|
@@ -108,14 +111,15 @@ module PaperTrail
|
|
|
108
111
|
)
|
|
109
112
|
return unless version
|
|
110
113
|
|
|
111
|
-
|
|
114
|
+
begin
|
|
115
|
+
version.save!
|
|
112
116
|
# Because the version object was created using version_class.new instead
|
|
113
117
|
# of versions_assoc.build?, the association cache is unaware. So, we
|
|
114
118
|
# invalidate the `versions` association cache with `reset`.
|
|
115
119
|
versions.reset
|
|
116
120
|
version
|
|
117
|
-
|
|
118
|
-
|
|
121
|
+
rescue StandardError => e
|
|
122
|
+
handle_version_errors e, version, :update
|
|
119
123
|
end
|
|
120
124
|
end
|
|
121
125
|
|
|
@@ -124,7 +128,7 @@ module PaperTrail
|
|
|
124
128
|
def reset_timestamp_attrs_for_update_if_needed
|
|
125
129
|
return if live?
|
|
126
130
|
@record.send(:timestamp_attributes_for_update_in_model).each do |column|
|
|
127
|
-
@record.send("restore_#{column}!")
|
|
131
|
+
@record.send(:"restore_#{column}!")
|
|
128
132
|
end
|
|
129
133
|
end
|
|
130
134
|
|
|
@@ -198,7 +202,7 @@ module PaperTrail
|
|
|
198
202
|
|
|
199
203
|
# @api private
|
|
200
204
|
def assign_and_reset_version_association(version)
|
|
201
|
-
@record.send("#{@record.class.version_association_name}=", version)
|
|
205
|
+
@record.send(:"#{@record.class.version_association_name}=", version)
|
|
202
206
|
@record.send(@record.class.versions_association_name).reset
|
|
203
207
|
end
|
|
204
208
|
|
|
@@ -226,7 +230,8 @@ module PaperTrail
|
|
|
226
230
|
# unnatural to tamper with creation timestamps in this way. But, this
|
|
227
231
|
# feature has existed for a long time, almost a decade now, and some users
|
|
228
232
|
# may rely on it now.
|
|
229
|
-
if @record.respond_to?(:updated_at)
|
|
233
|
+
if @record.respond_to?(:updated_at) &&
|
|
234
|
+
@record.paper_trail_options[:synchronize_version_creation_timestamp] != false
|
|
230
235
|
data[:created_at] = @record.updated_at
|
|
231
236
|
end
|
|
232
237
|
|
|
@@ -285,6 +290,26 @@ module PaperTrail
|
|
|
285
290
|
)
|
|
286
291
|
end
|
|
287
292
|
|
|
293
|
+
# Centralized handler for version errors
|
|
294
|
+
# @api private
|
|
295
|
+
def handle_version_errors(e, version, action)
|
|
296
|
+
case PaperTrail.config.version_error_behavior
|
|
297
|
+
when :legacy
|
|
298
|
+
# legacy behavior was to raise on create and log on update/delete
|
|
299
|
+
if action == :create
|
|
300
|
+
raise e
|
|
301
|
+
else
|
|
302
|
+
log_version_errors(version, action)
|
|
303
|
+
end
|
|
304
|
+
when :log
|
|
305
|
+
log_version_errors(version, action)
|
|
306
|
+
when :exception
|
|
307
|
+
raise e
|
|
308
|
+
when :silent
|
|
309
|
+
# noop
|
|
310
|
+
end
|
|
311
|
+
end
|
|
312
|
+
|
|
288
313
|
# @api private
|
|
289
314
|
# @return - The created version object, so that plugins can use it, e.g.
|
|
290
315
|
# paper_trail-association_tracking
|
|
@@ -297,11 +322,12 @@ module PaperTrail
|
|
|
297
322
|
data.merge!(data_for_update_columns)
|
|
298
323
|
|
|
299
324
|
versions_assoc = @record.send(@record.class.versions_association_name)
|
|
300
|
-
version = versions_assoc.
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
else
|
|
325
|
+
version = versions_assoc.new(data)
|
|
326
|
+
begin
|
|
327
|
+
version.save!
|
|
304
328
|
version
|
|
329
|
+
rescue StandardError => e
|
|
330
|
+
handle_version_errors e, version, :update
|
|
305
331
|
end
|
|
306
332
|
end
|
|
307
333
|
|
data/lib/paper_trail/reifier.rb
CHANGED
|
@@ -14,7 +14,7 @@ module PaperTrail
|
|
|
14
14
|
attrs = version.object_deserialized
|
|
15
15
|
model = init_model(attrs, options, version)
|
|
16
16
|
reify_attributes(model, version, attrs)
|
|
17
|
-
model.send "#{model.class.version_association_name}=", version
|
|
17
|
+
model.send :"#{model.class.version_association_name}=", version
|
|
18
18
|
model
|
|
19
19
|
end
|
|
20
20
|
|
|
@@ -93,8 +93,8 @@ module PaperTrail
|
|
|
93
93
|
def reify_attribute(k, v, model, version)
|
|
94
94
|
if model.has_attribute?(k)
|
|
95
95
|
model[k.to_sym] = v
|
|
96
|
-
elsif model.respond_to?("#{k}=")
|
|
97
|
-
model.send("#{k}=", v)
|
|
96
|
+
elsif model.respond_to?(:"#{k}=")
|
|
97
|
+
model.send(:"#{k}=", v)
|
|
98
98
|
elsif version.logger
|
|
99
99
|
version.logger.warn(
|
|
100
100
|
"Attribute #{k} does not exist on #{version.item_type} (Version id: #{version.id})."
|
|
@@ -27,7 +27,7 @@ module PaperTrail
|
|
|
27
27
|
# recent [memory optimizations](https://github.com/paper-trail-gem/paper_trail/pull/1189),
|
|
28
28
|
# when coming from `recordable_object_changes`, it will be a `HashWithIndifferentAccess`.
|
|
29
29
|
def dump(object)
|
|
30
|
-
object = object.to_hash if object.is_a?(HashWithIndifferentAccess)
|
|
30
|
+
object = object.to_hash if object.is_a?(ActiveSupport::HashWithIndifferentAccess)
|
|
31
31
|
::YAML.dump object
|
|
32
32
|
end
|
|
33
33
|
|
|
@@ -320,7 +320,7 @@ module PaperTrail
|
|
|
320
320
|
end
|
|
321
321
|
|
|
322
322
|
# First, deserialize the `object_changes` column.
|
|
323
|
-
changes = HashWithIndifferentAccess.new(object_changes_deserialized)
|
|
323
|
+
changes = ActiveSupport::HashWithIndifferentAccess.new(object_changes_deserialized)
|
|
324
324
|
|
|
325
325
|
# The next step is, perhaps unfortunately, called "de-serialization",
|
|
326
326
|
# and appears to be responsible for custom attribute serializers. For an
|
data/lib/paper_trail.rb
CHANGED
metadata
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: paper_trail
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 17.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andy Stewart
|
|
8
8
|
- Ben Atkins
|
|
9
9
|
- Jared Beck
|
|
10
|
-
autorequire:
|
|
11
10
|
bindir: bin
|
|
12
11
|
cert_chain: []
|
|
13
|
-
date:
|
|
12
|
+
date: 2025-10-24 00:00:00.000000000 Z
|
|
14
13
|
dependencies:
|
|
15
14
|
- !ruby/object:Gem::Dependency
|
|
16
15
|
name: activerecord
|
|
@@ -18,14 +17,14 @@ dependencies:
|
|
|
18
17
|
requirements:
|
|
19
18
|
- - ">="
|
|
20
19
|
- !ruby/object:Gem::Version
|
|
21
|
-
version: '
|
|
20
|
+
version: '7.1'
|
|
22
21
|
type: :runtime
|
|
23
22
|
prerelease: false
|
|
24
23
|
version_requirements: !ruby/object:Gem::Requirement
|
|
25
24
|
requirements:
|
|
26
25
|
- - ">="
|
|
27
26
|
- !ruby/object:Gem::Version
|
|
28
|
-
version: '
|
|
27
|
+
version: '7.1'
|
|
29
28
|
- !ruby/object:Gem::Dependency
|
|
30
29
|
name: request_store
|
|
31
30
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -40,20 +39,90 @@ dependencies:
|
|
|
40
39
|
- - "~>"
|
|
41
40
|
- !ruby/object:Gem::Version
|
|
42
41
|
version: '1.4'
|
|
42
|
+
- !ruby/object:Gem::Dependency
|
|
43
|
+
name: benchmark
|
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
|
45
|
+
requirements:
|
|
46
|
+
- - "~>"
|
|
47
|
+
- !ruby/object:Gem::Version
|
|
48
|
+
version: 0.4.0
|
|
49
|
+
type: :development
|
|
50
|
+
prerelease: false
|
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
52
|
+
requirements:
|
|
53
|
+
- - "~>"
|
|
54
|
+
- !ruby/object:Gem::Version
|
|
55
|
+
version: 0.4.0
|
|
56
|
+
- !ruby/object:Gem::Dependency
|
|
57
|
+
name: bigdecimal
|
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
|
59
|
+
requirements:
|
|
60
|
+
- - "~>"
|
|
61
|
+
- !ruby/object:Gem::Version
|
|
62
|
+
version: '3.1'
|
|
63
|
+
type: :development
|
|
64
|
+
prerelease: false
|
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
66
|
+
requirements:
|
|
67
|
+
- - "~>"
|
|
68
|
+
- !ruby/object:Gem::Version
|
|
69
|
+
version: '3.1'
|
|
70
|
+
- !ruby/object:Gem::Dependency
|
|
71
|
+
name: drb
|
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
|
73
|
+
requirements:
|
|
74
|
+
- - "~>"
|
|
75
|
+
- !ruby/object:Gem::Version
|
|
76
|
+
version: '2.2'
|
|
77
|
+
type: :development
|
|
78
|
+
prerelease: false
|
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
80
|
+
requirements:
|
|
81
|
+
- - "~>"
|
|
82
|
+
- !ruby/object:Gem::Version
|
|
83
|
+
version: '2.2'
|
|
84
|
+
- !ruby/object:Gem::Dependency
|
|
85
|
+
name: logger
|
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
|
87
|
+
requirements:
|
|
88
|
+
- - "~>"
|
|
89
|
+
- !ruby/object:Gem::Version
|
|
90
|
+
version: '1.6'
|
|
91
|
+
type: :development
|
|
92
|
+
prerelease: false
|
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
94
|
+
requirements:
|
|
95
|
+
- - "~>"
|
|
96
|
+
- !ruby/object:Gem::Version
|
|
97
|
+
version: '1.6'
|
|
98
|
+
- !ruby/object:Gem::Dependency
|
|
99
|
+
name: mutex_m
|
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
|
101
|
+
requirements:
|
|
102
|
+
- - "~>"
|
|
103
|
+
- !ruby/object:Gem::Version
|
|
104
|
+
version: 0.3.0
|
|
105
|
+
type: :development
|
|
106
|
+
prerelease: false
|
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
108
|
+
requirements:
|
|
109
|
+
- - "~>"
|
|
110
|
+
- !ruby/object:Gem::Version
|
|
111
|
+
version: 0.3.0
|
|
43
112
|
- !ruby/object:Gem::Dependency
|
|
44
113
|
name: appraisal
|
|
45
114
|
requirement: !ruby/object:Gem::Requirement
|
|
46
115
|
requirements:
|
|
47
116
|
- - "~>"
|
|
48
117
|
- !ruby/object:Gem::Version
|
|
49
|
-
version: 2.
|
|
118
|
+
version: '2.5'
|
|
50
119
|
type: :development
|
|
51
120
|
prerelease: false
|
|
52
121
|
version_requirements: !ruby/object:Gem::Requirement
|
|
53
122
|
requirements:
|
|
54
123
|
- - "~>"
|
|
55
124
|
- !ruby/object:Gem::Version
|
|
56
|
-
version: 2.
|
|
125
|
+
version: '2.5'
|
|
57
126
|
- !ruby/object:Gem::Dependency
|
|
58
127
|
name: byebug
|
|
59
128
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -116,14 +185,28 @@ dependencies:
|
|
|
116
185
|
requirements:
|
|
117
186
|
- - ">="
|
|
118
187
|
- !ruby/object:Gem::Version
|
|
119
|
-
version: '
|
|
188
|
+
version: '7.1'
|
|
120
189
|
type: :development
|
|
121
190
|
prerelease: false
|
|
122
191
|
version_requirements: !ruby/object:Gem::Requirement
|
|
123
192
|
requirements:
|
|
124
193
|
- - ">="
|
|
125
194
|
- !ruby/object:Gem::Version
|
|
126
|
-
version: '
|
|
195
|
+
version: '7.1'
|
|
196
|
+
- !ruby/object:Gem::Dependency
|
|
197
|
+
name: rails-controller-testing
|
|
198
|
+
requirement: !ruby/object:Gem::Requirement
|
|
199
|
+
requirements:
|
|
200
|
+
- - "~>"
|
|
201
|
+
- !ruby/object:Gem::Version
|
|
202
|
+
version: 1.0.5
|
|
203
|
+
type: :development
|
|
204
|
+
prerelease: false
|
|
205
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
206
|
+
requirements:
|
|
207
|
+
- - "~>"
|
|
208
|
+
- !ruby/object:Gem::Version
|
|
209
|
+
version: 1.0.5
|
|
127
210
|
- !ruby/object:Gem::Dependency
|
|
128
211
|
name: rake
|
|
129
212
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -144,98 +227,98 @@ dependencies:
|
|
|
144
227
|
requirements:
|
|
145
228
|
- - "~>"
|
|
146
229
|
- !ruby/object:Gem::Version
|
|
147
|
-
version:
|
|
230
|
+
version: 7.1.1
|
|
148
231
|
type: :development
|
|
149
232
|
prerelease: false
|
|
150
233
|
version_requirements: !ruby/object:Gem::Requirement
|
|
151
234
|
requirements:
|
|
152
235
|
- - "~>"
|
|
153
236
|
- !ruby/object:Gem::Version
|
|
154
|
-
version:
|
|
237
|
+
version: 7.1.1
|
|
155
238
|
- !ruby/object:Gem::Dependency
|
|
156
239
|
name: rubocop
|
|
157
240
|
requirement: !ruby/object:Gem::Requirement
|
|
158
241
|
requirements:
|
|
159
242
|
- - "~>"
|
|
160
243
|
- !ruby/object:Gem::Version
|
|
161
|
-
version: 1.
|
|
244
|
+
version: '1.75'
|
|
162
245
|
type: :development
|
|
163
246
|
prerelease: false
|
|
164
247
|
version_requirements: !ruby/object:Gem::Requirement
|
|
165
248
|
requirements:
|
|
166
249
|
- - "~>"
|
|
167
250
|
- !ruby/object:Gem::Version
|
|
168
|
-
version: 1.
|
|
251
|
+
version: '1.75'
|
|
169
252
|
- !ruby/object:Gem::Dependency
|
|
170
253
|
name: rubocop-packaging
|
|
171
254
|
requirement: !ruby/object:Gem::Requirement
|
|
172
255
|
requirements:
|
|
173
256
|
- - "~>"
|
|
174
257
|
- !ruby/object:Gem::Version
|
|
175
|
-
version: 0.
|
|
258
|
+
version: 0.6.0
|
|
176
259
|
type: :development
|
|
177
260
|
prerelease: false
|
|
178
261
|
version_requirements: !ruby/object:Gem::Requirement
|
|
179
262
|
requirements:
|
|
180
263
|
- - "~>"
|
|
181
264
|
- !ruby/object:Gem::Version
|
|
182
|
-
version: 0.
|
|
265
|
+
version: 0.6.0
|
|
183
266
|
- !ruby/object:Gem::Dependency
|
|
184
267
|
name: rubocop-performance
|
|
185
268
|
requirement: !ruby/object:Gem::Requirement
|
|
186
269
|
requirements:
|
|
187
270
|
- - "~>"
|
|
188
271
|
- !ruby/object:Gem::Version
|
|
189
|
-
version: 1.
|
|
272
|
+
version: 1.24.0
|
|
190
273
|
type: :development
|
|
191
274
|
prerelease: false
|
|
192
275
|
version_requirements: !ruby/object:Gem::Requirement
|
|
193
276
|
requirements:
|
|
194
277
|
- - "~>"
|
|
195
278
|
- !ruby/object:Gem::Version
|
|
196
|
-
version: 1.
|
|
279
|
+
version: 1.24.0
|
|
197
280
|
- !ruby/object:Gem::Dependency
|
|
198
281
|
name: rubocop-rails
|
|
199
282
|
requirement: !ruby/object:Gem::Requirement
|
|
200
283
|
requirements:
|
|
201
284
|
- - "~>"
|
|
202
285
|
- !ruby/object:Gem::Version
|
|
203
|
-
version: 2.
|
|
286
|
+
version: 2.30.3
|
|
204
287
|
type: :development
|
|
205
288
|
prerelease: false
|
|
206
289
|
version_requirements: !ruby/object:Gem::Requirement
|
|
207
290
|
requirements:
|
|
208
291
|
- - "~>"
|
|
209
292
|
- !ruby/object:Gem::Version
|
|
210
|
-
version: 2.
|
|
293
|
+
version: 2.30.3
|
|
211
294
|
- !ruby/object:Gem::Dependency
|
|
212
295
|
name: rubocop-rake
|
|
213
296
|
requirement: !ruby/object:Gem::Requirement
|
|
214
297
|
requirements:
|
|
215
298
|
- - "~>"
|
|
216
299
|
- !ruby/object:Gem::Version
|
|
217
|
-
version: 0.
|
|
300
|
+
version: 0.7.1
|
|
218
301
|
type: :development
|
|
219
302
|
prerelease: false
|
|
220
303
|
version_requirements: !ruby/object:Gem::Requirement
|
|
221
304
|
requirements:
|
|
222
305
|
- - "~>"
|
|
223
306
|
- !ruby/object:Gem::Version
|
|
224
|
-
version: 0.
|
|
307
|
+
version: 0.7.1
|
|
225
308
|
- !ruby/object:Gem::Dependency
|
|
226
309
|
name: rubocop-rspec
|
|
227
310
|
requirement: !ruby/object:Gem::Requirement
|
|
228
311
|
requirements:
|
|
229
312
|
- - "~>"
|
|
230
313
|
- !ruby/object:Gem::Version
|
|
231
|
-
version:
|
|
314
|
+
version: 3.5.0
|
|
232
315
|
type: :development
|
|
233
316
|
prerelease: false
|
|
234
317
|
version_requirements: !ruby/object:Gem::Requirement
|
|
235
318
|
requirements:
|
|
236
319
|
- - "~>"
|
|
237
320
|
- !ruby/object:Gem::Version
|
|
238
|
-
version:
|
|
321
|
+
version: 3.5.0
|
|
239
322
|
- !ruby/object:Gem::Dependency
|
|
240
323
|
name: simplecov
|
|
241
324
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -351,8 +434,9 @@ files:
|
|
|
351
434
|
homepage: https://github.com/paper-trail-gem/paper_trail
|
|
352
435
|
licenses:
|
|
353
436
|
- MIT
|
|
354
|
-
metadata:
|
|
355
|
-
|
|
437
|
+
metadata:
|
|
438
|
+
changelog_uri: https://github.com/paper-trail-gem/paper_trail/blob/master/CHANGELOG.md
|
|
439
|
+
rubygems_mfa_required: 'true'
|
|
356
440
|
rdoc_options: []
|
|
357
441
|
require_paths:
|
|
358
442
|
- lib
|
|
@@ -360,15 +444,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
360
444
|
requirements:
|
|
361
445
|
- - ">="
|
|
362
446
|
- !ruby/object:Gem::Version
|
|
363
|
-
version: 2.
|
|
447
|
+
version: 3.2.0
|
|
364
448
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
365
449
|
requirements:
|
|
366
450
|
- - ">="
|
|
367
451
|
- !ruby/object:Gem::Version
|
|
368
452
|
version: 1.3.6
|
|
369
453
|
requirements: []
|
|
370
|
-
rubygems_version: 3.
|
|
371
|
-
signing_key:
|
|
454
|
+
rubygems_version: 3.6.2
|
|
372
455
|
specification_version: 4
|
|
373
456
|
summary: Track changes to your models.
|
|
374
457
|
test_files: []
|