ar_cache 1.0.0 → 1.1.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/CHANGELOG.md +13 -0
- data/Gemfile.lock +3 -3
- data/README.md +18 -19
- data/lib/ar_cache.rb +27 -1
- data/lib/ar_cache/active_record.rb +3 -0
- data/lib/ar_cache/active_record/associations/association.rb +13 -0
- data/lib/ar_cache/active_record/associations/has_one_through_association.rb +6 -22
- data/lib/ar_cache/active_record/connection_adapters/abstract/database_statements.rb +34 -38
- data/lib/ar_cache/active_record/connection_adapters/abstract/transaction.rb +7 -7
- data/lib/ar_cache/active_record/insert_all.rb +2 -3
- data/lib/ar_cache/active_record/persistence.rb +21 -11
- data/lib/ar_cache/active_record/relation.rb +32 -30
- data/lib/ar_cache/query.rb +12 -1
- data/lib/ar_cache/table.rb +1 -1
- data/lib/ar_cache/version.rb +1 -1
- data/lib/ar_cache/where_clause.rb +3 -4
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '09eeda930c7263476f3b09e53747f9ec87ac070e65f18031856cdb05ad57a083'
|
4
|
+
data.tar.gz: 425c321debdcc05d81d4c0815abecb0d9e19fa417bb251265ba6dab420dd03e1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 827f0ecdf9e583870a454c16cfaa44c95b9d7b0ba4f3942097daf1c76fed218adfdafcd5733b68fa6476297c8b6d35c728e1a1b6f66db615d9fde834183ea4e8
|
7
|
+
data.tar.gz: 273bef3daea68391d681045c384488bf9266a1f75cd5ea7057b6aaf70928ebe97934cb65daadf3f6a3442177d948923116867be503f479c6ac8ab06ac23bb286
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# Change log
|
2
|
+
|
3
|
+
## main
|
4
|
+
|
5
|
+
## 1.0.0 (2021-03-02)
|
6
|
+
|
7
|
+
- Initial version.
|
8
|
+
|
9
|
+
## 1.1.0 (2021-03-11)
|
10
|
+
|
11
|
+
- Fully automatic delete cache when call delete_all/update_all method.
|
12
|
+
- Optimize has_one(through:) cache implementation.
|
13
|
+
- ActiveRecord::Relation#reload and ActiveRecord::Associations::Association#reload should skip read cache if associated target is already loaded.
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
ar_cache (1.
|
4
|
+
ar_cache (1.1.0)
|
5
5
|
activerecord (>= 6.1, < 7)
|
6
6
|
|
7
7
|
GEM
|
@@ -129,9 +129,9 @@ GEM
|
|
129
129
|
thor (~> 1.0)
|
130
130
|
rainbow (3.0.0)
|
131
131
|
rake (13.0.3)
|
132
|
-
regexp_parser (2.
|
132
|
+
regexp_parser (2.1.1)
|
133
133
|
rexml (3.2.4)
|
134
|
-
rubocop (1.
|
134
|
+
rubocop (1.11.0)
|
135
135
|
parallel (~> 1.10)
|
136
136
|
parser (>= 3.0.0.0)
|
137
137
|
rainbow (>= 2.2.2, < 4.0)
|
data/README.md
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
# ArCache
|
2
2
|
|
3
|
+

|
4
|
+
[](https://badge.fury.io/rb/ar_cache)
|
5
|
+
|
3
6
|
`ArCache` is an modern cacheing library for `ActiveRecord` inspired by cache-money and second_level_cache.
|
4
|
-
It works automatically by
|
7
|
+
It works automatically by overridden `ActiveRecord` related CURD code.
|
5
8
|
When executing standard `ActiveRecord` query, it will first query the cache, and if there is none in the cache,
|
6
9
|
then query the database and write the result to the cache.
|
7
10
|
|
@@ -82,41 +85,35 @@ For configuration information, please see [configuration](lib/generators/ar_cach
|
|
82
85
|
|
83
86
|
If all the following conditions are met, ArCache will try to read the cache:
|
84
87
|
|
85
|
-
- Use hash as `#where` parameter
|
88
|
+
- **Use hash as `#where` parameter**.
|
86
89
|
- Query condition contains unique index.
|
87
90
|
- Condition of unique index is only one array or no array.
|
88
91
|
- No call `#select` or select value is table column.
|
89
92
|
- No call `#order` or order value is table column and only one.
|
90
93
|
- No call `#limit` or value of the unique index isn't array.
|
91
|
-
- No call `#joins
|
92
|
-
- No call `#left_joins`.
|
93
|
-
- No call `#skip_query_cache!`.
|
94
|
-
- No call `#skip_ar_cache`.
|
95
|
-
- No call `#explain`.
|
96
|
-
- No call `#from`.
|
97
|
-
- No call `#group`.
|
98
|
-
- No call `value`.
|
94
|
+
- No call `#joins`, `#left_joins`, `#skip_query_cache!`, `#skip_ar_cache`, `#explain`, `#from`, `#group`, `#offset`, `#lock`
|
99
95
|
- ...
|
100
96
|
|
101
97
|
**Cacheable example:**
|
102
98
|
|
103
99
|
```ruby
|
104
|
-
User.find(1) # primary key cache
|
105
|
-
User.where(id: [1, 2]) #
|
106
|
-
User.where(email: 'foobar@gmail.com') # sigle-column unique index cache
|
107
|
-
User.where(name: 'foobar', status: :active) # multi-column unique index cache
|
108
|
-
User.includes(:account).where(id: [1, 2]) # association cache
|
109
|
-
User.first.account # association
|
100
|
+
User.find(1) # support primary key cache
|
101
|
+
User.where(id: [1, 2]) # support multi-value unique index cache
|
102
|
+
User.where(email: 'foobar@gmail.com') # support sigle-column unique index cache
|
103
|
+
User.where(name: 'foobar', status: :active) # support multi-column unique index cache
|
104
|
+
User.includes(:account).where(id: [1, 2]) # support association preload cache
|
105
|
+
User.first.account # support association reader cach
|
110
106
|
```
|
111
107
|
|
108
|
+
The association cache support belongs_to and has_one, small amount of complex has_one(scope, through:, as:) don't support, then has_many cache support, please watch to future version.
|
109
|
+
|
112
110
|
## Cache iteration
|
113
111
|
|
114
112
|
The following cases will cause cache iteration:
|
115
113
|
|
116
114
|
- Table field changes.
|
117
|
-
-
|
118
|
-
- `
|
119
|
-
- `ActiveRecord` update/delete join other tables.
|
115
|
+
- Turn on `ArCache` or turn off `ArCache`.
|
116
|
+
- Call `#upsert_all` method.
|
120
117
|
|
121
118
|
**Notice: After iteration, all existing caches of the table will be expired!**
|
122
119
|
|
@@ -130,6 +127,8 @@ The following cases will cause cache iteration:
|
|
130
127
|
- Prohibit use `ActiveRecord` other underlying methods to directly update/delete data! (You is a fake activerecord user if this code appears)
|
131
128
|
- Prohibit skip `ActiveRecord` directly update/delete data!
|
132
129
|
|
130
|
+
If you have to do this, please consider turning off ArCache.
|
131
|
+
|
133
132
|
## Alternatives
|
134
133
|
|
135
134
|
There are some other gems implementations for `ActiveRecord` cache such as:
|
data/lib/ar_cache.rb
CHANGED
@@ -18,5 +18,31 @@ require 'ar_cache/active_record'
|
|
18
18
|
require_relative './generators/ar_cache/install_generator' if defined?(Rails)
|
19
19
|
|
20
20
|
module ArCache
|
21
|
-
|
21
|
+
PRELOADER = ::ActiveRecord::Associations::Preloader.new
|
22
|
+
|
23
|
+
class << self
|
24
|
+
delegate :configure, to: Configuration
|
25
|
+
|
26
|
+
def skip_cache?
|
27
|
+
Thread.current[:ar_cache_skip_cache]
|
28
|
+
end
|
29
|
+
|
30
|
+
def skip_cache
|
31
|
+
Thread.current[:ar_cache_skip_cache] = true
|
32
|
+
yield
|
33
|
+
ensure
|
34
|
+
Thread.current[:ar_cache_skip_cache] = false
|
35
|
+
end
|
36
|
+
|
37
|
+
def pre_expire?
|
38
|
+
Thread.current[:ar_cache_pre_expire]
|
39
|
+
end
|
40
|
+
|
41
|
+
def pre_expire
|
42
|
+
Thread.current[:ar_cache_pre_expire] = true
|
43
|
+
yield
|
44
|
+
ensure
|
45
|
+
Thread.current[:ar_cache_pre_expire] = false
|
46
|
+
end
|
47
|
+
end
|
22
48
|
end
|
@@ -5,6 +5,7 @@ require 'ar_cache/active_record/relation'
|
|
5
5
|
require 'ar_cache/active_record/core'
|
6
6
|
require 'ar_cache/active_record/persistence'
|
7
7
|
require 'ar_cache/active_record/insert_all'
|
8
|
+
require 'ar_cache/active_record/associations/association'
|
8
9
|
require 'ar_cache/active_record/associations/singular_association'
|
9
10
|
require 'ar_cache/active_record/associations/has_one_through_association'
|
10
11
|
require 'ar_cache/active_record/connection_adapters/abstract/transaction'
|
@@ -18,11 +19,13 @@ ActiveSupport.on_load(:active_record, run_once: true) do
|
|
18
19
|
ActiveRecord::ModelSchema::ClassMethods.prepend(ArCache::ActiveRecord::ModelSchema::ClassMethods)
|
19
20
|
|
20
21
|
ActiveRecord::Persistence.prepend(ArCache::ActiveRecord::Persistence)
|
22
|
+
ActiveRecord::Persistence::ClassMethods.prepend(ArCache::ActiveRecord::Persistence::ClassMethods)
|
21
23
|
|
22
24
|
ActiveRecord::InsertAll.prepend(ArCache::ActiveRecord::InsertAll)
|
23
25
|
|
24
26
|
ActiveRecord::Relation.prepend(ArCache::ActiveRecord::Relation)
|
25
27
|
|
28
|
+
ActiveRecord::Associations::Association.prepend(ArCache::ActiveRecord::Associations::Association)
|
26
29
|
ActiveRecord::Associations::SingularAssociation.prepend(ArCache::ActiveRecord::Associations::SingularAssociation)
|
27
30
|
ActiveRecord::Associations::HasOneThroughAssociation.prepend(ArCache::ActiveRecord::Associations::HasOneThroughAssociation)
|
28
31
|
|
@@ -4,33 +4,17 @@ module ArCache
|
|
4
4
|
module ActiveRecord
|
5
5
|
module Associations
|
6
6
|
module HasOneThroughAssociation
|
7
|
-
private def find_target
|
7
|
+
private def find_target
|
8
8
|
return super if reflection.klass.ar_cache_table.disabled?
|
9
9
|
return super if reflection.through_reflection.klass.ar_cache_table.disabled?
|
10
10
|
|
11
|
-
if owner.strict_loading? && owner.validation_context.nil?
|
12
|
-
Base.strict_loading_violation!(owner: owner.class,
|
11
|
+
if (owner.strict_loading? || reflection.strict_loading?) && owner.validation_context.nil?
|
12
|
+
Base.strict_loading_violation!(owner: owner.class, reflection: reflection)
|
13
13
|
end
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
# TODO: Should not instantiate AR
|
20
|
-
through_record = if reflection.scope
|
21
|
-
owner.association(reflection.through_reflection.name).scope.merge(reflection.scope).first
|
22
|
-
else
|
23
|
-
owner.send(reflection.through_reflection.name)
|
24
|
-
end
|
25
|
-
return super if through_record.is_a?(::ActiveRecord::Associations::CollectionProxy)
|
26
|
-
return nil if !through_record || through_record.destroyed?
|
27
|
-
|
28
|
-
record = through_record.send(reflection.source_reflection.name)
|
29
|
-
record = record.first if record.is_a?(::ActiveRecord::Associations::CollectionProxy)
|
30
|
-
return nil unless record
|
31
|
-
|
32
|
-
record.tap { |r| set_inverse_instance(r) }
|
33
|
-
rescue StandardError # If scope depend on other table, will raise exception
|
15
|
+
ArCache::PRELOADER.preload(owner, reflection.name)
|
16
|
+
owner.send(reflection.name)
|
17
|
+
rescue StandardError
|
34
18
|
super
|
35
19
|
end
|
36
20
|
end
|
@@ -4,71 +4,67 @@ module ArCache
|
|
4
4
|
module ActiveRecord
|
5
5
|
module ConnectionAdapters
|
6
6
|
module DatabaseStatements
|
7
|
-
def insert(arel, ...)
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
end
|
20
|
-
alias create insert
|
7
|
+
# def insert(arel, ...)
|
8
|
+
# super.tap do
|
9
|
+
# if arel.is_a?(String)
|
10
|
+
# sql = arel.downcase
|
11
|
+
# ArCache::Table.all.each do |table|
|
12
|
+
# current_transaction.add_changed_table(table.name) if sql.include?(table.name)
|
13
|
+
# end
|
14
|
+
# else # is Arel::InsertManager
|
15
|
+
# klass = arel.ast.relation.instance_variable_get(:@klass)
|
16
|
+
# current_transaction.add_changed_table(klass.table_name)
|
17
|
+
# end
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
# alias create insert
|
21
21
|
|
22
22
|
def update(arel, ...)
|
23
|
-
super.tap { |num|
|
23
|
+
super.tap { |num| update_ar_cache(arel) unless num.zero? }
|
24
24
|
end
|
25
25
|
|
26
26
|
def delete(arel, ...)
|
27
|
-
super.tap { |num|
|
27
|
+
super.tap { |num| update_ar_cache(arel) unless num.zero? }
|
28
28
|
end
|
29
29
|
|
30
30
|
def truncate(table_name, ...)
|
31
|
-
super.tap {
|
31
|
+
super.tap { update_ar_cache_by_table(table_name) }
|
32
32
|
end
|
33
33
|
|
34
34
|
def truncate_tables(*table_names)
|
35
35
|
super.tap do
|
36
|
-
table_names.each { |table_name|
|
36
|
+
table_names.each { |table_name| update_ar_cache_by_table(table_name) }
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
-
private def
|
40
|
+
private def update_ar_cache(arel_or_sql_string)
|
41
41
|
if arel_or_sql_string.is_a?(String)
|
42
|
-
|
42
|
+
update_ar_cache_by_sql(arel_or_sql_string)
|
43
43
|
else # is Arel::TreeManager
|
44
|
-
|
44
|
+
update_ar_cache_by_arel(arel_or_sql_string)
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
-
private def
|
49
|
-
|
50
|
-
|
51
|
-
# - Arel::Table
|
48
|
+
private def update_ar_cache_by_arel(arel)
|
49
|
+
return if ArCache.pre_expire?
|
50
|
+
|
52
51
|
arel_table = arel.ast.relation.is_a?(Arel::Table) ? arel.ast.relation : arel.ast.relation.left
|
53
52
|
klass = arel_table.instance_variable_get(:@klass)
|
54
|
-
|
55
|
-
|
56
|
-
where_clause = ArCache::WhereClause.new(klass, arel.ast.wheres)
|
57
|
-
if where_clause.cacheable?
|
58
|
-
current_transaction.add_changed_table(klass.table_name)
|
59
|
-
current_transaction.add_ar_cache_keys(where_clause.cache_keys)
|
60
|
-
else
|
61
|
-
current_transaction.add_ar_cache_table(klass.ar_cache_table)
|
62
|
-
end
|
53
|
+
current_transaction.update_ar_cache_table(klass.ar_cache_table) if klass.ar_cache_table.enabled?
|
63
54
|
end
|
64
55
|
|
65
|
-
private def
|
56
|
+
private def update_ar_cache_by_sql(sql)
|
66
57
|
sql = sql.downcase
|
67
|
-
|
58
|
+
|
59
|
+
ArCache::Table.all.each do |table|
|
60
|
+
current_transaction.update_ar_cache_table(table) if table.enabled? && sql.include?(table.name)
|
61
|
+
end
|
68
62
|
end
|
69
63
|
|
70
|
-
private def
|
71
|
-
ArCache::Table.all.each
|
64
|
+
private def update_ar_cache_by_table(table_name)
|
65
|
+
ArCache::Table.all.each do |table|
|
66
|
+
current_transaction.update_ar_cache_table(table) if table.enabled? && table_name.casecmp?(table.name)
|
67
|
+
end
|
72
68
|
end
|
73
69
|
end
|
74
70
|
end
|
@@ -4,15 +4,15 @@ module ArCache
|
|
4
4
|
module ActiveRecord
|
5
5
|
module ConnectionAdapters
|
6
6
|
module NullTransaction
|
7
|
-
def
|
7
|
+
def delete_ar_cache_keys(keys, delay: false) # rubocop:disable Lint/UnusedMethodArgument
|
8
8
|
ArCache::Store.delete_multi(keys)
|
9
9
|
end
|
10
10
|
|
11
|
-
def
|
11
|
+
def update_ar_cache_table(table, delay: false) # rubocop:disable Lint/UnusedMethodArgument
|
12
12
|
table.update_version
|
13
13
|
end
|
14
14
|
|
15
|
-
def add_changed_table(
|
15
|
+
def add_changed_table(...); end
|
16
16
|
end
|
17
17
|
|
18
18
|
module Transaction
|
@@ -24,12 +24,12 @@ module ArCache
|
|
24
24
|
@ar_cache_tables = []
|
25
25
|
end
|
26
26
|
|
27
|
-
def
|
27
|
+
def delete_ar_cache_keys(keys, delay: false)
|
28
28
|
super if !delay && read_uncommitted?
|
29
29
|
@ar_cache_keys.push(*keys)
|
30
30
|
end
|
31
31
|
|
32
|
-
def
|
32
|
+
def update_ar_cache_table(table, delay: false)
|
33
33
|
add_changed_table(table.name) unless delay
|
34
34
|
|
35
35
|
super if !delay && read_uncommitted?
|
@@ -49,8 +49,8 @@ module ArCache
|
|
49
49
|
ArCache::Store.delete_multi(@ar_cache_keys.uniq) if @ar_cache_keys.any?
|
50
50
|
else
|
51
51
|
transaction = connection.current_transaction
|
52
|
-
@ar_cache_tables.each { |table| transaction.
|
53
|
-
transaction.
|
52
|
+
@ar_cache_tables.each { |table| transaction.update_ar_cache_table(table, delay: true) }
|
53
|
+
transaction.delete_ar_cache_keys(@ar_cache_keys, delay: true)
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
@@ -6,9 +6,8 @@ module ArCache
|
|
6
6
|
def execute
|
7
7
|
super.tap do
|
8
8
|
if on_duplicate == :update
|
9
|
-
connection.current_transaction.
|
10
|
-
|
11
|
-
connection.transaction_manager.add_changed_table(model.table_name)
|
9
|
+
connection.current_transaction.update_ar_cache_table(model.ar_cache_table)
|
10
|
+
connection.current_transaction.add_changed_table(model.table_name)
|
12
11
|
end
|
13
12
|
end
|
14
13
|
end
|
@@ -3,20 +3,30 @@
|
|
3
3
|
module ArCache
|
4
4
|
module ActiveRecord
|
5
5
|
module Persistence
|
6
|
-
|
7
|
-
|
6
|
+
module ClassMethods
|
7
|
+
def _update_record(_, constraints)
|
8
|
+
ArCache.pre_expire do
|
9
|
+
delete_ar_cache_key(constraints[@primary_key])
|
10
|
+
super
|
11
|
+
end
|
12
|
+
end
|
8
13
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
self.class.unscoped { self.class.skip_ar_cache.find(id) }
|
14
|
+
def _delete_record(constraints)
|
15
|
+
ArCache.pre_expire do
|
16
|
+
delete_ar_cache_key(constraints[@primary_key])
|
17
|
+
super
|
14
18
|
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private def delete_ar_cache_key(id)
|
22
|
+
key = ar_cache_table.primary_cache_key(id)
|
23
|
+
connection.current_transaction.delete_ar_cache_keys([key])
|
24
|
+
connection.current_transaction.add_changed_table(table_name)
|
25
|
+
end
|
26
|
+
end
|
15
27
|
|
16
|
-
|
17
|
-
|
18
|
-
@previously_new_record = false
|
19
|
-
self
|
28
|
+
def reload(...)
|
29
|
+
ArCache.skip_cache { super }
|
20
30
|
end
|
21
31
|
end
|
22
32
|
end
|
@@ -3,6 +3,11 @@
|
|
3
3
|
module ArCache
|
4
4
|
module ActiveRecord
|
5
5
|
module Relation
|
6
|
+
def reload
|
7
|
+
@skip_ar_cache = true if loaded?
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
6
11
|
def skip_ar_cache
|
7
12
|
tap { @skip_ar_cache = true }
|
8
13
|
end
|
@@ -12,36 +17,33 @@ module ArCache
|
|
12
17
|
super
|
13
18
|
end
|
14
19
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
records
|
44
|
-
end
|
20
|
+
def update_all(...)
|
21
|
+
ArCache.pre_expire { delete_ar_cache_keys ? super : 0 }
|
22
|
+
end
|
23
|
+
|
24
|
+
def delete_all
|
25
|
+
ArCache.pre_expire { delete_ar_cache_keys ? super : 0 }
|
26
|
+
end
|
27
|
+
|
28
|
+
private def delete_ar_cache_keys
|
29
|
+
return true if klass.ar_cache_table.disabled?
|
30
|
+
|
31
|
+
where_clause = ArCache::WhereClause.new(klass, arel.constraints)
|
32
|
+
keys = if where_clause.cacheable? && where_clause.primary_key_index?
|
33
|
+
where_clause.primary_cache_keys
|
34
|
+
else
|
35
|
+
pluck(primary_key).map { |item| klass.ar_cache_table.primary_cache_key(item) }
|
36
|
+
end
|
37
|
+
|
38
|
+
return false if keys.empty?
|
39
|
+
|
40
|
+
@klass.connection.current_transaction.delete_ar_cache_keys(keys)
|
41
|
+
@klass.connection.current_transaction.add_changed_table(@klass.table_name)
|
42
|
+
true
|
43
|
+
end
|
44
|
+
|
45
|
+
private def exec_queries(&block)
|
46
|
+
@skip_ar_cache ? super : ArCache::Query.new(self).exec_queries(&block).freeze
|
45
47
|
end
|
46
48
|
end
|
47
49
|
end
|
data/lib/ar_cache/query.rb
CHANGED
@@ -10,7 +10,8 @@ module ArCache
|
|
10
10
|
@where_clause = ArCache::WhereClause.new(@relation.klass, @relation.where_clause.send(:predicates))
|
11
11
|
end
|
12
12
|
|
13
|
-
def exec_queries(&block)
|
13
|
+
def exec_queries(&block) # rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
|
14
|
+
return [] if relation.where_clause.contradiction?
|
14
15
|
return relation.skip_ar_cache.send(:exec_queries, &block) unless exec_queries_cacheable?
|
15
16
|
|
16
17
|
records = table.read(where_clause, @select_values, &block)
|
@@ -29,15 +30,25 @@ module ArCache
|
|
29
30
|
end
|
30
31
|
|
31
32
|
records_order(records)
|
33
|
+
|
34
|
+
relation.preload_associations(records) unless relation.skip_preloading_value
|
35
|
+
|
36
|
+
records.each(&:readonly!) if relation.readonly_value
|
37
|
+
records.each(&:strict_loading!) if relation.strict_loading_value
|
38
|
+
|
39
|
+
records
|
32
40
|
end
|
33
41
|
|
34
42
|
private def exec_queries_cacheable? # rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
|
43
|
+
return false if relation.klass.ar_cache_table.disabled?
|
35
44
|
return false if relation.skip_query_cache_value
|
36
45
|
return false if relation.lock_value
|
37
46
|
return false if relation.group_values.any?
|
38
47
|
return false if relation.joins_values.any?
|
39
48
|
return false if relation.left_outer_joins_values.any?
|
40
49
|
return false if relation.offset_value
|
50
|
+
return false if relation.eager_loading?
|
51
|
+
return false if relation.connection.transaction_manager.changed_table?(table.name)
|
41
52
|
return false unless relation.from_clause.empty?
|
42
53
|
return false unless where_clause.cacheable?
|
43
54
|
return false unless select_values_cacheable?
|
data/lib/ar_cache/table.rb
CHANGED
data/lib/ar_cache/version.rb
CHANGED
@@ -66,11 +66,10 @@ module ArCache
|
|
66
66
|
@cache_hash
|
67
67
|
end
|
68
68
|
|
69
|
-
def
|
70
|
-
|
71
|
-
keys += cache_hash.values unless primary_key_index?
|
69
|
+
def primary_cache_keys
|
70
|
+
raise 'Does not detect primary key index' unless primary_key_index?
|
72
71
|
|
73
|
-
|
72
|
+
@primary_cache_keys ||= Array(where_values_hash[table.primary_key]).map { |v| table.primary_cache_key(v) }
|
74
73
|
end
|
75
74
|
|
76
75
|
def missed_hash
|
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.
|
4
|
+
version: 1.1.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-
|
11
|
+
date: 2021-03-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -41,6 +41,7 @@ files:
|
|
41
41
|
- ".github/workflows/main.yml"
|
42
42
|
- ".gitignore"
|
43
43
|
- ".rubocop.yml"
|
44
|
+
- CHANGELOG.md
|
44
45
|
- CODE_OF_CONDUCT.md
|
45
46
|
- Gemfile
|
46
47
|
- Gemfile.common
|
@@ -56,6 +57,7 @@ files:
|
|
56
57
|
- gemfiles/rails-edge
|
57
58
|
- lib/ar_cache.rb
|
58
59
|
- lib/ar_cache/active_record.rb
|
60
|
+
- lib/ar_cache/active_record/associations/association.rb
|
59
61
|
- lib/ar_cache/active_record/associations/has_one_through_association.rb
|
60
62
|
- lib/ar_cache/active_record/associations/singular_association.rb
|
61
63
|
- lib/ar_cache/active_record/connection_adapters/abstract/database_statements.rb
|