ar_cache 1.2.0 → 1.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a01b3342ccad3bf06ce4438f714f00ffc467efc32f58809ab940163ebaf440d7
4
- data.tar.gz: 453c9232cbc03dee8572b1133972f01d6dd1c2501df0c9279a32a5e4243ebeb0
3
+ metadata.gz: 1771642ffaabd7ea8a7fc41c1ffc3cef4be12bbeaaca3ef40aa40c2f01ea291a
4
+ data.tar.gz: 4b3513827e1f33d3823e0345de4e266b0312e014d1d50fbdedf52eafaa97a02c
5
5
  SHA512:
6
- metadata.gz: 7d6a3bb90d4ac0eb3384650fd17fbed43be74da2ca0a57b55c9d19b9c68722b2d23785fd42e00cbdec8a4563cc10c6c44ac7609a8b4a09d9b4a813f47c3f2ae1
7
- data.tar.gz: 2105bf0e6e89c3d438f30b43bef1dd64b66b511968fec5c393068043ddb52ee833762f0508a4a84d25940ddac36c686c8b5fd4e6ef73d75802de878645ac265b
6
+ metadata.gz: c80c2bdc655f64409c1f9263415ed8fbd70aa71cb851275a7c31d8f9a459d51d46ee2fb0707c14839a37418c076e4251c55226adf7bf9aaef233d1b89faef7d0
7
+ data.tar.gz: 2ad58b8a624d9e3fe559be94076b1593b54fc2f52d5f88a111d31d2c5223d4fdba6ddb9f562270fe92af99199c1aeda624e3cbfb8c97701b2b3e17f2559c184a
data/CHANGELOG.md CHANGED
@@ -2,7 +2,12 @@
2
2
 
3
3
  ## main
4
4
 
5
- ## 1.2.0 (2021-03-12)
5
+ ## 1.3.0 (2021-03-13 UTC)
6
+
7
+ - [Commit [#4ec14e9](https://github.com/OuYangJinTing/ar_cache/commit/4ec14e9e762abb57a8ff18aa8c93a514db49c552)]:
8
+ Optimize association cache, only cacheable association use ArCache query now.
9
+
10
+ ## 1.2.0 (2021-03-12 UTC)
6
11
 
7
12
  [Commit [#c830907](https://github.com/OuYangJinTing/ar_cache/commit/c830907595b7d1d46a2f29204ee6051ecc3ff30c)]:
8
13
 
@@ -10,12 +15,12 @@
10
15
  - Rename methods: `ArCache#skip_cache? => ArCache#skip?`, `ArCache#skip_cache => ArCache#skip`, `ArCache#pre_expire? => ArCache#expire?`, `ArCache#pre_expire => ArCache#expire`.
11
16
  - Now, `ArCache#skip` method only skip read cache, but still try delete cache.
12
17
 
13
- ## 1.1.0 (2021-03-11)
18
+ ## 1.1.0 (2021-03-10 UTC)
14
19
 
15
20
  - [Commit [#92965d2](https://github.com/OuYangJinTing/ar_cache/commit/92965d26e130da9a13bd52ea31f3f668851f6f12)] Fully automatic delete cache when call delete_all/update_all method.
16
21
  - [Commit [#231cfd3](https://github.com/OuYangJinTing/ar_cache/commit/231cfd35c2c197bf41628f4f914ba39fb8debd81)] Optimize has_one(through:) cache implementation.
17
22
  - [Commit [#ce5444c](https://github.com/OuYangJinTing/ar_cache/commit/ce5444c8c4ec0a61bec5e07d694295d3cc5decf8)] ActiveRecord::Relation#reload and ActiveRecord::Associations::Association#reload should skip read cache if associated target is already loaded.
18
23
 
19
- ## 1.0.0 (2021-03-02)
24
+ ## 1.0.0 (2021-03-02 UTC)
20
25
 
21
26
  - Initial version.
data/Gemfile.lock CHANGED
@@ -1,66 +1,66 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ar_cache (1.2.0)
4
+ ar_cache (1.3.0)
5
5
  activerecord (>= 6.1, < 7)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- actioncable (6.1.1)
11
- actionpack (= 6.1.1)
12
- activesupport (= 6.1.1)
10
+ actioncable (6.1.3)
11
+ actionpack (= 6.1.3)
12
+ activesupport (= 6.1.3)
13
13
  nio4r (~> 2.0)
14
14
  websocket-driver (>= 0.6.1)
15
- actionmailbox (6.1.1)
16
- actionpack (= 6.1.1)
17
- activejob (= 6.1.1)
18
- activerecord (= 6.1.1)
19
- activestorage (= 6.1.1)
20
- activesupport (= 6.1.1)
15
+ actionmailbox (6.1.3)
16
+ actionpack (= 6.1.3)
17
+ activejob (= 6.1.3)
18
+ activerecord (= 6.1.3)
19
+ activestorage (= 6.1.3)
20
+ activesupport (= 6.1.3)
21
21
  mail (>= 2.7.1)
22
- actionmailer (6.1.1)
23
- actionpack (= 6.1.1)
24
- actionview (= 6.1.1)
25
- activejob (= 6.1.1)
26
- activesupport (= 6.1.1)
22
+ actionmailer (6.1.3)
23
+ actionpack (= 6.1.3)
24
+ actionview (= 6.1.3)
25
+ activejob (= 6.1.3)
26
+ activesupport (= 6.1.3)
27
27
  mail (~> 2.5, >= 2.5.4)
28
28
  rails-dom-testing (~> 2.0)
29
- actionpack (6.1.1)
30
- actionview (= 6.1.1)
31
- activesupport (= 6.1.1)
29
+ actionpack (6.1.3)
30
+ actionview (= 6.1.3)
31
+ activesupport (= 6.1.3)
32
32
  rack (~> 2.0, >= 2.0.9)
33
33
  rack-test (>= 0.6.3)
34
34
  rails-dom-testing (~> 2.0)
35
35
  rails-html-sanitizer (~> 1.0, >= 1.2.0)
36
- actiontext (6.1.1)
37
- actionpack (= 6.1.1)
38
- activerecord (= 6.1.1)
39
- activestorage (= 6.1.1)
40
- activesupport (= 6.1.1)
36
+ actiontext (6.1.3)
37
+ actionpack (= 6.1.3)
38
+ activerecord (= 6.1.3)
39
+ activestorage (= 6.1.3)
40
+ activesupport (= 6.1.3)
41
41
  nokogiri (>= 1.8.5)
42
- actionview (6.1.1)
43
- activesupport (= 6.1.1)
42
+ actionview (6.1.3)
43
+ activesupport (= 6.1.3)
44
44
  builder (~> 3.1)
45
45
  erubi (~> 1.4)
46
46
  rails-dom-testing (~> 2.0)
47
47
  rails-html-sanitizer (~> 1.1, >= 1.2.0)
48
- activejob (6.1.1)
49
- activesupport (= 6.1.1)
48
+ activejob (6.1.3)
49
+ activesupport (= 6.1.3)
50
50
  globalid (>= 0.3.6)
51
- activemodel (6.1.1)
52
- activesupport (= 6.1.1)
53
- activerecord (6.1.1)
54
- activemodel (= 6.1.1)
55
- activesupport (= 6.1.1)
56
- activestorage (6.1.1)
57
- actionpack (= 6.1.1)
58
- activejob (= 6.1.1)
59
- activerecord (= 6.1.1)
60
- activesupport (= 6.1.1)
51
+ activemodel (6.1.3)
52
+ activesupport (= 6.1.3)
53
+ activerecord (6.1.3)
54
+ activemodel (= 6.1.3)
55
+ activesupport (= 6.1.3)
56
+ activestorage (6.1.3)
57
+ actionpack (= 6.1.3)
58
+ activejob (= 6.1.3)
59
+ activerecord (= 6.1.3)
60
+ activesupport (= 6.1.3)
61
61
  marcel (~> 0.3.1)
62
62
  mimemagic (~> 0.3.2)
63
- activesupport (6.1.1)
63
+ activesupport (6.1.3)
64
64
  concurrent-ruby (~> 1.0, >= 1.0.2)
65
65
  i18n (>= 1.6, < 2)
66
66
  minitest (>= 5.1)
@@ -71,11 +71,16 @@ GEM
71
71
  coderay (1.1.3)
72
72
  concurrent-ruby (1.1.8)
73
73
  crass (1.0.6)
74
- database_cleaner (1.8.5)
74
+ database_cleaner (2.0.1)
75
+ database_cleaner-active_record (~> 2.0.0)
76
+ database_cleaner-active_record (2.0.0)
77
+ activerecord (>= 5.a)
78
+ database_cleaner-core (~> 2.0.0)
79
+ database_cleaner-core (2.0.1)
75
80
  erubi (1.10.0)
76
81
  globalid (0.4.2)
77
82
  activesupport (>= 4.2.0)
78
- i18n (1.8.7)
83
+ i18n (1.8.9)
79
84
  concurrent-ruby (~> 1.0)
80
85
  loofah (2.9.0)
81
86
  crass (~> 1.0.2)
@@ -87,43 +92,43 @@ GEM
87
92
  method_source (1.0.0)
88
93
  mimemagic (0.3.5)
89
94
  mini_mime (1.0.2)
90
- minitest (5.14.3)
91
- nio4r (2.5.4)
92
- nokogiri (1.11.1-x86_64-linux)
95
+ minitest (5.14.4)
96
+ nio4r (2.5.7)
97
+ nokogiri (1.11.2-x86_64-linux)
93
98
  racc (~> 1.4)
94
99
  parallel (1.20.1)
95
100
  parser (3.0.0.0)
96
101
  ast (~> 2.4.1)
97
- pry (0.13.1)
102
+ pry (0.14.0)
98
103
  coderay (~> 1.1)
99
104
  method_source (~> 1.0)
100
105
  racc (1.5.2)
101
106
  rack (2.2.3)
102
107
  rack-test (1.1.0)
103
108
  rack (>= 1.0, < 3)
104
- rails (6.1.1)
105
- actioncable (= 6.1.1)
106
- actionmailbox (= 6.1.1)
107
- actionmailer (= 6.1.1)
108
- actionpack (= 6.1.1)
109
- actiontext (= 6.1.1)
110
- actionview (= 6.1.1)
111
- activejob (= 6.1.1)
112
- activemodel (= 6.1.1)
113
- activerecord (= 6.1.1)
114
- activestorage (= 6.1.1)
115
- activesupport (= 6.1.1)
109
+ rails (6.1.3)
110
+ actioncable (= 6.1.3)
111
+ actionmailbox (= 6.1.3)
112
+ actionmailer (= 6.1.3)
113
+ actionpack (= 6.1.3)
114
+ actiontext (= 6.1.3)
115
+ actionview (= 6.1.3)
116
+ activejob (= 6.1.3)
117
+ activemodel (= 6.1.3)
118
+ activerecord (= 6.1.3)
119
+ activestorage (= 6.1.3)
120
+ activesupport (= 6.1.3)
116
121
  bundler (>= 1.15.0)
117
- railties (= 6.1.1)
122
+ railties (= 6.1.3)
118
123
  sprockets-rails (>= 2.0.0)
119
124
  rails-dom-testing (2.0.3)
120
125
  activesupport (>= 4.2.0)
121
126
  nokogiri (>= 1.6)
122
127
  rails-html-sanitizer (1.3.0)
123
128
  loofah (~> 2.3)
124
- railties (6.1.1)
125
- actionpack (= 6.1.1)
126
- activesupport (= 6.1.1)
129
+ railties (6.1.3)
130
+ actionpack (= 6.1.3)
131
+ activesupport (= 6.1.3)
127
132
  method_source
128
133
  rake (>= 0.8.7)
129
134
  thor (~> 1.0)
@@ -144,7 +149,7 @@ GEM
144
149
  parser (>= 2.7.1.5)
145
150
  rubocop-minitest (0.10.3)
146
151
  rubocop (>= 0.87, < 2.0)
147
- rubocop-performance (1.9.2)
152
+ rubocop-performance (1.10.1)
148
153
  rubocop (>= 0.90.0, < 2.0)
149
154
  rubocop-ast (>= 0.4.0)
150
155
  rubocop-rails (2.9.1)
data/lib/ar_cache.rb CHANGED
@@ -18,7 +18,7 @@ require 'ar_cache/active_record'
18
18
  require_relative './generators/ar_cache/install_generator' if defined?(Rails)
19
19
 
20
20
  module ArCache
21
- PRELOADER = ::ActiveRecord::Associations::Preloader.new
21
+ @cache_reflection = {}
22
22
 
23
23
  class << self
24
24
  delegate :configure, to: Configuration
@@ -28,10 +28,14 @@ module ArCache
28
28
  end
29
29
 
30
30
  def skip
31
- Thread.current[:ar_cache_skip] = true
32
- yield
33
- ensure
34
- Thread.current[:ar_cache_skip] = false
31
+ return yield if skip?
32
+
33
+ begin
34
+ Thread.current[:ar_cache_skip] = true
35
+ yield
36
+ ensure
37
+ Thread.current[:ar_cache_skip] = false
38
+ end
35
39
  end
36
40
 
37
41
  def expire?
@@ -39,10 +43,18 @@ module ArCache
39
43
  end
40
44
 
41
45
  def expire
42
- Thread.current[:ar_cache_expire] = true
43
- yield
44
- ensure
45
- Thread.current[:ar_cache_expire] = false
46
+ return yield if expire?
47
+
48
+ begin
49
+ Thread.current[:ar_cache_expire] = true
50
+ yield
51
+ ensure
52
+ Thread.current[:ar_cache_expire] = false
53
+ end
54
+ end
55
+
56
+ def cache_reflection?(reflection)
57
+ @cache_reflection.fetch(reflection) { @cache_reflection[reflection] = yield }
46
58
  end
47
59
  end
48
60
  end
@@ -6,8 +6,6 @@ require 'ar_cache/active_record/core'
6
6
  require 'ar_cache/active_record/persistence'
7
7
  require 'ar_cache/active_record/insert_all'
8
8
  require 'ar_cache/active_record/associations/association'
9
- require 'ar_cache/active_record/associations/singular_association'
10
- require 'ar_cache/active_record/associations/has_one_through_association'
11
9
  require 'ar_cache/active_record/connection_adapters/abstract/transaction'
12
10
  require 'ar_cache/active_record/connection_adapters/abstract/database_statements'
13
11
 
@@ -26,8 +24,6 @@ ActiveSupport.on_load(:active_record, run_once: true) do
26
24
  ActiveRecord::Relation.prepend(ArCache::ActiveRecord::Relation)
27
25
 
28
26
  ActiveRecord::Associations::Association.prepend(ArCache::ActiveRecord::Associations::Association)
29
- ActiveRecord::Associations::SingularAssociation.prepend(ArCache::ActiveRecord::Associations::SingularAssociation)
30
- ActiveRecord::Associations::HasOneThroughAssociation.prepend(ArCache::ActiveRecord::Associations::HasOneThroughAssociation)
31
27
 
32
28
  ActiveRecord::ConnectionAdapters::NullTransaction.prepend(ArCache::ActiveRecord::ConnectionAdapters::NullTransaction)
33
29
  ActiveRecord::ConnectionAdapters::RealTransaction.prepend(ArCache::ActiveRecord::ConnectionAdapters::Transaction)
@@ -4,9 +4,32 @@ module ArCache
4
4
  module ActiveRecord
5
5
  module Associations
6
6
  module Association
7
+ PRELOADER = ::ActiveRecord::Associations::Preloader.new
8
+
7
9
  def reload(...)
8
10
  loaded? ? ArCache.skip { super } : super
9
11
  end
12
+
13
+ # TODO: Implement CollectionAssociation cache
14
+ private def find_target # rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
15
+ return super if ArCache.skip? || reflection.collection?
16
+ return super unless ArCache.cache_reflection?(reflection) do
17
+ if reflection.is_a?(::ActiveRecord::Reflection::ThroughReflection)
18
+ ArCache::Query.new(owner.association(through_reflection.name).scope).exec_queries_cacheable? &&
19
+ ArCache::Query.new(through_reflection.klass.new.association(reflection.source_reflection_name).scope)
20
+ .exec_queries_cacheable?
21
+ else
22
+ ArCache::Query.new(scope).exec_queries_cacheable?
23
+ end
24
+ end
25
+
26
+ if (owner.strict_loading? || reflection.strict_loading?) && owner.validation_context.nil?
27
+ ::ActiveRecord::Base.strict_loading_violation!(owner: owner.class, reflection: reflection)
28
+ end
29
+
30
+ PRELOADER.preload(owner, reflection.name)
31
+ Array.wrap(owner.association(reflection.name).target)
32
+ end
10
33
  end
11
34
  end
12
35
  end
@@ -39,7 +39,7 @@ module ArCache
39
39
  records
40
40
  end
41
41
 
42
- private def exec_queries_cacheable? # rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
42
+ def exec_queries_cacheable? # rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
43
43
  return false if relation.klass.ar_cache_table.disabled?
44
44
  return false if relation.skip_query_cache_value
45
45
  return false if relation.lock_value
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ArCache
4
- VERSION = '1.2.0'
4
+ VERSION = '1.3.0'
5
5
  end
@@ -24,8 +24,8 @@ module ArCache
24
24
  count = 0
25
25
 
26
26
  bool = index.all? do |column|
27
- where_values_hash[column].tap do |value|
28
- if value.is_a?(Array)
27
+ where_values_hash.key?(column).tap do
28
+ if where_values_hash[column].is_a?(Array)
29
29
  @multi_values_key = column
30
30
  count += 1
31
31
  end
@@ -52,7 +52,7 @@ module ArCache
52
52
  @cache_hash = {}
53
53
  multi_values_key = @multi_values_key || @index.first
54
54
 
55
- Array(where_values_hash[multi_values_key]).each do |v|
55
+ Array.wrap(where_values_hash[multi_values_key]).each do |v|
56
56
  @cache_hash[table.cache_key(where_values_hash, @index, multi_values_key, v)] = v
57
57
  end
58
58
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ar_cache
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - OuYangJinTing
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-03-12 00:00:00.000000000 Z
11
+ date: 2021-03-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -58,8 +58,6 @@ files:
58
58
  - lib/ar_cache.rb
59
59
  - lib/ar_cache/active_record.rb
60
60
  - lib/ar_cache/active_record/associations/association.rb
61
- - lib/ar_cache/active_record/associations/has_one_through_association.rb
62
- - lib/ar_cache/active_record/associations/singular_association.rb
63
61
  - lib/ar_cache/active_record/connection_adapters/abstract/database_statements.rb
64
62
  - lib/ar_cache/active_record/connection_adapters/abstract/transaction.rb
65
63
  - lib/ar_cache/active_record/core.rb
@@ -1,24 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ArCache
4
- module ActiveRecord
5
- module Associations
6
- module HasOneThroughAssociation
7
- private def find_target # rubocop:disable Metrics/CyclomaticComplexity
8
- return super if ArCache.skip?
9
- return super if reflection.klass.ar_cache_table.disabled?
10
- return super if reflection.through_reflection.klass.ar_cache_table.disabled?
11
-
12
- if (owner.strict_loading? || reflection.strict_loading?) && owner.validation_context.nil?
13
- Base.strict_loading_violation!(owner: owner.class, reflection: reflection)
14
- end
15
-
16
- ArCache::PRELOADER.preload(owner, reflection.name)
17
- owner.send(reflection.name)
18
- rescue StandardError
19
- super
20
- end
21
- end
22
- end
23
- end
24
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ArCache
4
- module ActiveRecord
5
- module Associations
6
- module SingularAssociation
7
- private def skip_statement_cache?(...)
8
- return super if ArCache.skip?
9
-
10
- # Polymorphic associations do not support computing the class, so can't judge ArCache status.
11
- # But SingularAssociation query usually can hit the unique index, so here return true directly.
12
- return true if is_a?(::ActiveRecord::Associations::BelongsToPolymorphicAssociation)
13
- return true unless reflection.klass.ar_cache_table.disabled?
14
-
15
- super
16
- end
17
- end
18
- end
19
- end
20
- end