hoardable 0.18.1 → 0.19.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 36d1113a71b72492244fadc8172ef4a08f28bdff546b7344bb385ce38e82ecbd
4
- data.tar.gz: a4cee0c629c4c1d59f6c0b632c0499fc5e094e099c7e0dc4bf3e0d79271f6eb8
3
+ metadata.gz: 12ee4c5fbbd0b35bda5c9b7427015a1d60ca9cc919ac992caca386d4c3664163
4
+ data.tar.gz: 0020d7f28b85fb70efc3a1b80695f1e9c69f60c954b6aeccb71cedadccb97e0c
5
5
  SHA512:
6
- metadata.gz: 3cb288b7dbd5938056d3fd5fae396ad6d7caca20a98902ebb228a75d4c05d5e689807ea90f4e6f96dc5e1ac20bbb028fa12717676da3f60163ca4a362bf33db1
7
- data.tar.gz: 44bba102025a18563d29d76430d27f06299316d69b37e08fa3b216453dfe6c4890f82e6f065843c127cf26fb0da39f7ce76194d2e31dc2bd0021d9973e6c9748
6
+ metadata.gz: 2fe01feb0e5260d8072f4a45640517a5041a83c566db15b45cc32d141fa8883cf84a1bec16b8ec043a6b914b28e0e824d1e2820454756501941831613efe95a7
7
+ data.tar.gz: ceef85ede42a50189fb41de31fe0d4ab6882c2139d825569cd674fdf9611f89fd96721156cad5dee347359f67ecba68d8e9a794c2c6513710a39c2e599975668
data/CHANGELOG.md CHANGED
@@ -1,3 +1,19 @@
1
+ ## 0.19.0
2
+
3
+ - Ensure that stateful Hoardable class methods `with`, `travel_to` and `at` are thread-safe.
4
+
5
+ ## 0.18.2
6
+
7
+ - Fix for using `update_all` with Hoardable records.
8
+
9
+ ## 0.18.1
10
+
11
+ - Support for STI models.
12
+
13
+ ## 0.18.0
14
+
15
+ - Improved compatibilty with using `ActiveRecord` relationship caching when not using `Hoardable.at`.
16
+
1
17
  ## 0.17.0
2
18
 
3
19
  - Much improved performance of setting `hoardable_id` for versions.
@@ -0,0 +1,17 @@
1
+ module Hoardable
2
+ # Monkey-patches an internal Arel method to ensure that bulk UPDATE's always operate
3
+ # directly on the root table by injecting the ONLY keyword.
4
+ module ArelCrud
5
+ def compile_update(*args)
6
+ um = super(*args)
7
+
8
+ if source.left.instance_variable_get(:@klass).in?(Hoardable::REGISTRY)
9
+ return um.table(Arel.sql("ONLY #{source.left.name}"))
10
+ end
11
+
12
+ um
13
+ end
14
+ end
15
+ end
16
+
17
+ Arel::SelectManager.prepend Hoardable::ArelCrud
@@ -46,7 +46,7 @@ module Hoardable
46
46
  hoardable_maybe_add_only(left, collector)
47
47
  else
48
48
  return unless left.instance_variable_get("@klass").in?(Hoardable::REGISTRY)
49
- return if Hoardable.instance_variable_get("@at")
49
+ return if Thread.current[:hoardable_at]
50
50
 
51
51
  collector << "ONLY "
52
52
  end
@@ -56,7 +56,7 @@ module Hoardable
56
56
  end
57
57
 
58
58
  def has_one_at_timestamp
59
- Hoardable.instance_variable_get("@at") || source_record.updated_at
59
+ Thread.current[:hoardable_at] || source_record.updated_at
60
60
  rescue NameError
61
61
  raise(UpdatedAtColumnMissingError, source_record.class.table_name)
62
62
  end
@@ -93,7 +93,7 @@ module Hoardable
93
93
  end
94
94
 
95
95
  def initialize_temporal_range
96
- upper_bound = Hoardable.instance_variable_get("@travel_to") || Time.now.utc
96
+ upper_bound = Thread.current[:hoardable_travel_to] || Time.now.utc
97
97
  lower_bound = (previous_temporal_tsrange_end || hoardable_source_epoch)
98
98
 
99
99
  if upper_bound < lower_bound
@@ -44,13 +44,19 @@ module Hoardable
44
44
 
45
45
  class << self
46
46
  CONFIG_KEYS.each do |key|
47
- define_method(key) { @config[key] }
47
+ define_method(key) do
48
+ local_config = Thread.current[:hoardable_config] || @config
49
+ local_config[key]
50
+ end
48
51
 
49
52
  define_method("#{key}=") { |value| @config[key] = value }
50
53
  end
51
54
 
52
55
  DATA_KEYS.each do |key|
53
- define_method(key) { @context[key] }
56
+ define_method(key) do
57
+ local_context = Thread.current[:hoardable_context] || @context
58
+ local_context[key]
59
+ end
54
60
 
55
61
  define_method("#{key}=") { |value| @context[key] = value }
56
62
  end
@@ -60,14 +66,13 @@ module Hoardable
60
66
  #
61
67
  # @param hash [Hash] config and contextual data to set within a block
62
68
  def with(hash)
63
- current_config = @config
64
- current_context = @context
65
- @config = current_config.merge(hash.slice(*CONFIG_KEYS))
66
- @context = current_context.merge(hash.slice(*DATA_KEYS))
69
+ thread = Thread.current
70
+ thread[:hoardable_config] = @config.merge(hash.slice(*CONFIG_KEYS))
71
+ thread[:hoardable_context] = @context.merge(hash.slice(*DATA_KEYS))
67
72
  yield
68
73
  ensure
69
- @config = current_config
70
- @context = current_context
74
+ thread[:hoardable_config] = nil
75
+ thread[:hoardable_context] = nil
71
76
  end
72
77
 
73
78
  # Allows performing a query for record states at a certain time. Returned {SourceModel}
@@ -75,20 +80,22 @@ module Hoardable
75
80
  #
76
81
  # @param datetime [DateTime, Time] the datetime or time to temporally query records at
77
82
  def at(datetime)
78
- @at = datetime
83
+ thread = Thread.current
84
+ thread[:hoardable_at] = datetime
79
85
  yield
80
86
  ensure
81
- @at = nil
87
+ thread[:hoardable_at] = nil
82
88
  end
83
89
 
84
90
  # Allows calling code to set the upper bound for the temporal range for recorded audits.
85
91
  #
86
92
  # @param datetime [DateTime] the datetime to temporally record versions at
87
93
  def travel_to(datetime)
88
- @travel_to = datetime
94
+ thread = Thread.current
95
+ thread[:hoardable_travel_to] = datetime
89
96
  yield
90
97
  ensure
91
- @travel_to = nil
98
+ thread[:hoardable_travel_to] = nil
92
99
  end
93
100
 
94
101
  # @!visibility private
@@ -13,8 +13,8 @@ module Hoardable
13
13
  end
14
14
 
15
15
  private def hoardable_scope
16
- if Hoardable.instance_variable_get("@at") &&
17
- (hoardable_id = @association.owner.hoardable_id)
16
+ if Thread.current[:hoardable_at]
17
+ (hoardable_id = @association.owner.hoardable_id)
18
18
  @association.scope.rewhere(@association.reflection.foreign_key => hoardable_id)
19
19
  else
20
20
  @association.scope
@@ -36,7 +36,7 @@ module Hoardable
36
36
  # {HasManyExtension} scope is always used when using {Hoardable.at}.
37
37
  class_eval <<-RUBY, __FILE__, __LINE__ + 1
38
38
  def #{args.first}
39
- if Hoardable.instance_variable_get("@at")
39
+ if Thread.current[:hoardable_at]
40
40
  super.extending
41
41
  else
42
42
  super
@@ -14,7 +14,7 @@ module Hoardable
14
14
  default_scope do
15
15
  scope =
16
16
  (
17
- if (hoardable_at = Hoardable.instance_variable_get("@at"))
17
+ if (hoardable_at = Thread.current[:hoardable_at])
18
18
  at(hoardable_at)
19
19
  else
20
20
  exclude_versions
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Hoardable
4
- VERSION = "0.18.1"
4
+ VERSION = "0.19.0"
5
5
  end
data/lib/hoardable.rb CHANGED
@@ -4,6 +4,7 @@ require "active_record"
4
4
  require "fx"
5
5
  require_relative "hoardable/version"
6
6
  require_relative "hoardable/arel_visitors"
7
+ require_relative "hoardable/arel_crud"
7
8
  require_relative "hoardable/schema_statements"
8
9
  require_relative "hoardable/schema_dumper"
9
10
  require_relative "hoardable/engine"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hoardable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.18.1
4
+ version: 0.19.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - justin talbott
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-01-15 00:00:00.000000000 Z
11
+ date: 2025-01-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -17,6 +17,9 @@ dependencies:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '7'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '9'
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -24,6 +27,9 @@ dependencies:
24
27
  - - ">="
25
28
  - !ruby/object:Gem::Version
26
29
  version: '7'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '9'
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: activesupport
29
35
  requirement: !ruby/object:Gem::Requirement
@@ -31,6 +37,9 @@ dependencies:
31
37
  - - ">="
32
38
  - !ruby/object:Gem::Version
33
39
  version: '7'
40
+ - - "<"
41
+ - !ruby/object:Gem::Version
42
+ version: '9'
34
43
  type: :runtime
35
44
  prerelease: false
36
45
  version_requirements: !ruby/object:Gem::Requirement
@@ -38,6 +47,9 @@ dependencies:
38
47
  - - ">="
39
48
  - !ruby/object:Gem::Version
40
49
  version: '7'
50
+ - - "<"
51
+ - !ruby/object:Gem::Version
52
+ version: '9'
41
53
  - !ruby/object:Gem::Dependency
42
54
  name: railties
43
55
  requirement: !ruby/object:Gem::Requirement
@@ -45,6 +57,9 @@ dependencies:
45
57
  - - ">="
46
58
  - !ruby/object:Gem::Version
47
59
  version: '7'
60
+ - - "<"
61
+ - !ruby/object:Gem::Version
62
+ version: '9'
48
63
  type: :runtime
49
64
  prerelease: false
50
65
  version_requirements: !ruby/object:Gem::Requirement
@@ -52,6 +67,9 @@ dependencies:
52
67
  - - ">="
53
68
  - !ruby/object:Gem::Version
54
69
  version: '7'
70
+ - - "<"
71
+ - !ruby/object:Gem::Version
72
+ version: '9'
55
73
  - !ruby/object:Gem::Dependency
56
74
  name: fx
57
75
  requirement: !ruby/object:Gem::Requirement
@@ -116,6 +134,7 @@ files:
116
134
  - lib/generators/hoardable/triggers/set_hoardable_id.sql
117
135
  - lib/generators/hoardable/triggers/versions_prevent_update.sql
118
136
  - lib/hoardable.rb
137
+ - lib/hoardable/arel_crud.rb
119
138
  - lib/hoardable/arel_visitors.rb
120
139
  - lib/hoardable/associations.rb
121
140
  - lib/hoardable/belongs_to.rb