iron_trail 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 205a181e1b361753b39576a57dbee4503b62573314c52d91044acbdcd60c26b0
4
- data.tar.gz: 41f13486979881ee2e23b5247f949c23bddca34f27d3aa5bbaf348f32e9a1673
3
+ metadata.gz: 4c4a5962c8262c61d0909615b33cf39567699f0feea5b54337818431bc8b6d7d
4
+ data.tar.gz: 75942627d8daef67d5fd92a0eb75a8a738bab22a317963f95a487e184d587f35
5
5
  SHA512:
6
- metadata.gz: df308cd9a427c4069178c7304c9b823070db8474d9556a45c9d4a1eb5d0c3edfef70a3d250cc564648c96ce44e57576fdb78e2b3fe30a9ce4682f6824b56497f
7
- data.tar.gz: 448ffb8f0440aa63a927b0e41925fd63a48ed1b2b50b68c7f2b205569c3e2de250cbc9f44ca5297bf06c3b8d9d53517796d16afe966fff589779f31c959c4189
6
+ metadata.gz: 90d7d85c0a098bceb555e40a6c513ae3cd3c5d7694cb71d579a719fbf80c7df6ed6a92dc9196648a80d6551d610d84da221d9dc4276089a67ab0c7578d616f75
7
+ data.tar.gz: 38e04491986b4d4c0929541c613ad522396c570f132beb289ed75385b7f4de3a168eea450623cb34495f8b4a12e8b668a21f19091da6460d23f0de7b59911730
@@ -4,13 +4,49 @@ module IronTrail
4
4
  module ChangeModelConcern
5
5
  extend ::ActiveSupport::Concern
6
6
 
7
+ def insert_operation? = (operation == 'i')
8
+ def update_operation? = (operation == 'u')
9
+ def delete_operation? = (operation == 'd')
10
+
7
11
  def reify
8
12
  Reifier.reify(self)
9
13
  end
10
14
 
11
- def insert_operation? = (operation == 'i')
12
- def update_operation? = (operation == 'u')
13
- def delete_operation? = (operation == 'd')
15
+ # We don't store the class name of the object, but we do store the rec_table.
16
+ # This method infers the class name from the rec_table and also the "type"
17
+ # attribute in the stored object in case it's a rails STI class.
18
+ #
19
+ # It returns the class instance. Raises an error in case the class couldn't
20
+ # be inferred.
21
+ def rec_class
22
+ source_attributes = (delete_operation? ? rec_old : rec_new)
23
+ Reifier.model_from_table_name(rec_table, source_attributes.fetch('type', nil))
24
+ end
25
+
26
+ # This mimics the method with the same name available in the papertrail gem.
27
+ # It is an extended rec_delta, where attributes values are properly deserialized
28
+ # as rails' ActiveRecord would do.
29
+ #
30
+ # For instance, timestamps are serialized as strings in JSON, so rec_delta
31
+ # would return strings for timestamps. Using this method, it'd return a proper
32
+ # timestamp deserialized from the string.
33
+ #
34
+ # This method doesn't do caching and always computes the full thing. It's
35
+ # up to the user to perform caching if wanted.
36
+ def compute_changeset
37
+ return nil unless update_operation?
38
+
39
+ klass = rec_class
40
+
41
+ HashWithIndifferentAccess.new.tap do |changes|
42
+ rec_delta.each do |col_name, in_delta|
43
+ type_class = klass.type_for_attribute(col_name)
44
+ out_delta = in_delta.map { |val| type_class.deserialize(val) }
45
+
46
+ changes[col_name] = out_delta
47
+ end
48
+ end
49
+ end
14
50
 
15
51
  module ClassMethods
16
52
  def where_object_changes_to(args = {})
@@ -21,6 +57,22 @@ module IronTrail
21
57
  _where_object_changes(0, args)
22
58
  end
23
59
 
60
+ # Allows filtering out updates that changed just a certain set of columns.
61
+ # This could be useful, for instance, to filter out updates made with
62
+ # ActiveRecord's #touch method, which changes only the updated_at column.
63
+ # In that case, calling `.with_delta_other_than(:updated_at)` would exclude
64
+ # such changes from the result.
65
+ #
66
+ # This works by inspecting whether there are any keys in the rec_delta column
67
+ # other than the columns specified in the `columns` parameter.
68
+ def with_delta_other_than(*columns)
69
+ quoted_columns = columns.map { |col_name| connection.quote(col_name) }
70
+ exclude_array = "ARRAY[#{quoted_columns.join(', ')}]::text[]"
71
+
72
+ sql = "rec_delta IS NULL OR (rec_delta - #{exclude_array}) <> '{}'::jsonb"
73
+ where(::Arel::Nodes::SqlLiteral.new(sql))
74
+ end
75
+
24
76
  private
25
77
 
26
78
  def _where_object_changes(ary_index, args)
@@ -10,6 +10,8 @@ module IronTrail
10
10
  end
11
11
 
12
12
  def self.merge_metadata(keys, merge_hash)
13
+ raise TypeError.new("value must be a Hash") unless merge_hash.is_a?(Hash)
14
+
13
15
  self.metadata ||= {}
14
16
  base = self.metadata
15
17
  keys.each do |key|
@@ -10,9 +10,8 @@ module IronTrail
10
10
 
11
11
  source_attributes.each do |name, value|
12
12
  if record.has_attribute?(name)
13
- record[name.to_sym] = value
14
- elsif record.respond_to?("#{name}=")
15
- record.send("#{name}=", value)
13
+ attr_type = record.type_for_attribute(name)
14
+ record[name] = attr_type.deserialize(value)
16
15
  else
17
16
  ghost = record.instance_variable_get(:@irontrail_reified_ghost_attributes)
18
17
  unless ghost
@@ -9,6 +9,20 @@ require 'iron_trail'
9
9
 
10
10
  module IronTrail
11
11
  module Testing
12
+ module InstanceMethods
13
+ def irontrail_set_actor(actor)
14
+ if actor.nil?
15
+ IronTrail::Current.metadata.delete(:_actor_type)
16
+ IronTrail::Current.metadata.delete(:_actor_id)
17
+ else
18
+ IronTrail::Current.merge_metadata([], {
19
+ _actor_type: actor.class.name,
20
+ _actor_id: actor.id
21
+ })
22
+ end
23
+ end
24
+ end
25
+
12
26
  class << self
13
27
  attr_accessor :enabled
14
28
 
@@ -56,11 +70,18 @@ module IronTrail
56
70
  end
57
71
 
58
72
  RSpec.configure do |config|
73
+ config.include ::IronTrail::Testing::InstanceMethods
74
+
59
75
  config.around(:each, iron_trail: true) do |example|
60
76
  IronTrail::Testing.with_iron_trail(want_enabled: true) { example.run }
61
77
  end
78
+
62
79
  config.around(:each, iron_trail: false) do |example|
63
80
  raise "Using iron_trail: false does not do what you might think it does. To disable iron_trail, " \
64
81
  "use IronTrail::Testing.with_iron_trail(want_enabled: false) { ... } instead."
65
82
  end
83
+
84
+ config.before(:each) do
85
+ IronTrail::Current.reset
86
+ end
66
87
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_literal_string: true
2
2
 
3
3
  module IronTrail
4
- VERSION = '0.1.4'
4
+ VERSION = '0.1.6'
5
5
  end
data/lib/iron_trail.rb CHANGED
@@ -30,7 +30,9 @@ module IronTrail
30
30
 
31
31
  module SchemaDumper
32
32
  def trailer(stream)
33
- stream.print "\n IronTrail.post_schema_load(self, missing_tracking: @irontrail_missing_track)\n"
33
+ if IronTrail.enabled?
34
+ stream.print "\n IronTrail.post_schema_load(self, missing_tracking: @irontrail_missing_track)\n"
35
+ end
34
36
 
35
37
  super(stream)
36
38
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: iron_trail
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - André Diego Piske
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-02-24 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: rails
@@ -160,7 +160,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
160
160
  - !ruby/object:Gem::Version
161
161
  version: '0'
162
162
  requirements: []
163
- rubygems_version: 3.6.2
163
+ rubygems_version: 3.6.9
164
164
  specification_version: 4
165
165
  summary: Creates a trail strong as iron
166
166
  test_files: []