second_level_cache 2.5.0 → 2.6.2

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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +34 -0
  3. data/README.md +1 -1
  4. data/lib/second_level_cache.rb +1 -0
  5. data/lib/second_level_cache/active_record.rb +8 -2
  6. data/lib/second_level_cache/active_record/base.rb +1 -5
  7. data/lib/second_level_cache/active_record/belongs_to_association.rb +6 -4
  8. data/lib/second_level_cache/active_record/fetch_by_uniq_key.rb +24 -17
  9. data/lib/second_level_cache/active_record/finder_methods.rb +44 -42
  10. data/lib/second_level_cache/active_record/has_one_association.rb +14 -20
  11. data/lib/second_level_cache/active_record/persistence.rb +6 -2
  12. data/lib/second_level_cache/active_record/preloader.rb +34 -28
  13. data/lib/second_level_cache/adapter/paranoia.rb +24 -0
  14. data/lib/second_level_cache/config.rb +1 -0
  15. data/lib/second_level_cache/log_subscriber.rb +15 -0
  16. data/lib/second_level_cache/mixin.rb +0 -12
  17. data/lib/second_level_cache/record_marshal.rb +7 -40
  18. data/lib/second_level_cache/version.rb +1 -1
  19. data/second_level_cache.gemspec +23 -23
  20. data/test/active_record_test_case_helper.rb +11 -1
  21. data/test/fetch_by_uniq_key_test.rb +47 -4
  22. data/test/finder_methods_test.rb +39 -0
  23. data/test/has_one_association_test.rb +16 -4
  24. data/test/model/account.rb +2 -2
  25. data/test/model/animal.rb +1 -1
  26. data/test/model/application_record.rb +3 -0
  27. data/test/model/book.rb +6 -1
  28. data/test/model/contribution.rb +14 -0
  29. data/test/model/image.rb +1 -1
  30. data/test/model/order.rb +1 -1
  31. data/test/model/order_item.rb +1 -1
  32. data/test/model/paranoid.rb +10 -0
  33. data/test/model/post.rb +1 -1
  34. data/test/model/topic.rb +1 -1
  35. data/test/model/user.rb +7 -7
  36. data/test/paranoid_test.rb +16 -0
  37. data/test/{preloader_test.rb → preloader_belongs_to_test.rb} +17 -15
  38. data/test/preloader_has_many_test.rb +13 -0
  39. data/test/preloader_has_one_test.rb +69 -0
  40. data/test/record_marshal_test.rb +1 -1
  41. data/test/test_helper.rb +3 -4
  42. metadata +28 -28
@@ -7,7 +7,7 @@ ActiveRecord::Base.connection.create_table(:orders, force: true, id: :uuid) do |
7
7
  t.timestamps null: false
8
8
  end
9
9
 
10
- class Order < ActiveRecord::Base
10
+ class Order < ApplicationRecord
11
11
  second_level_cache
12
12
 
13
13
  has_many :order_items
@@ -6,7 +6,7 @@ ActiveRecord::Base.connection.create_table(:order_items, force: true, id: :uuid)
6
6
  t.string :order_id
7
7
  end
8
8
 
9
- class OrderItem < ActiveRecord::Base
9
+ class OrderItem < ApplicationRecord
10
10
  second_level_cache
11
11
  belongs_to :order, touch: true
12
12
  end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ ActiveRecord::Base.connection.create_table(:paranoids, force: true) do |t|
4
+ t.datetime :deleted_at
5
+ end
6
+
7
+ class Paranoid < ApplicationRecord
8
+ second_level_cache
9
+ acts_as_paranoid
10
+ end
@@ -6,7 +6,7 @@ ActiveRecord::Base.connection.create_table(:posts, force: true) do |t|
6
6
  t.integer :topic_id
7
7
  end
8
8
 
9
- class Post < ActiveRecord::Base
9
+ class Post < ApplicationRecord
10
10
  second_level_cache
11
11
  belongs_to :topic, touch: true
12
12
  end
@@ -7,7 +7,7 @@ ActiveRecord::Base.connection.create_table(:topics, force: true) do |t|
7
7
  t.timestamps null: false
8
8
  end
9
9
 
10
- class Topic < ActiveRecord::Base
10
+ class Topic < ApplicationRecord
11
11
  second_level_cache
12
12
 
13
13
  has_many :posts
@@ -9,8 +9,7 @@ ActiveRecord::Base.connection.create_table(:users, force: true) do |t|
9
9
  t.integer :status, default: 0
10
10
  t.integer :books_count, default: 0
11
11
  t.integer :images_count, default: 0
12
- t.datetime :deleted_at
13
- t.timestamps null: false
12
+ t.timestamps null: false, precision: 6
14
13
  end
15
14
 
16
15
  ActiveRecord::Base.connection.create_table(:forked_user_links, force: true) do |t|
@@ -26,16 +25,15 @@ ActiveRecord::Base.connection.create_table(:namespaces, force: true) do |t|
26
25
  t.timestamps null: false
27
26
  end
28
27
 
29
- class User < ActiveRecord::Base
28
+ class User < ApplicationRecord
30
29
  CACHE_VERSION = 3
31
30
  second_level_cache(version: CACHE_VERSION, expires_in: 3.days)
32
- acts_as_paranoid
33
31
 
34
32
  serialize :options, Array
35
33
  serialize :json_options, JSON if ::ActiveRecord::VERSION::STRING >= "4.1.0"
36
34
  store :extras, accessors: %i[tagline gender]
37
35
 
38
- has_one :account
36
+ has_one :account, inverse_of: :user
39
37
  has_one :forked_user_link, foreign_key: "forked_to_user_id"
40
38
  has_one :forked_from_user, through: :forked_user_link
41
39
  has_many :namespaces
@@ -46,13 +44,15 @@ class User < ActiveRecord::Base
46
44
  enum status: %i[active archived]
47
45
  end
48
46
 
49
- class Namespace < ActiveRecord::Base
47
+ class Namespace < ApplicationRecord
50
48
  second_level_cache version: 1, expires_in: 3.days
51
49
 
52
50
  belongs_to :user
53
51
  end
54
52
 
55
- class ForkedUserLink < ActiveRecord::Base
53
+ class ForkedUserLink < ApplicationRecord
54
+ second_level_cache version: 1, expires_in: 1.day
55
+
56
56
  belongs_to :forked_from_user, class_name: "User"
57
57
  belongs_to :forked_to_user, class_name: "User"
58
58
  end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ class ParanoidTest < ActiveSupport::TestCase
6
+ def setup
7
+ @paranoid = Paranoid.create
8
+ end
9
+
10
+ def test_should_expire_cache_when_destroy
11
+ @paranoid.destroy
12
+ assert_nil Paranoid.find_by(id: @paranoid.id)
13
+ assert_nil SecondLevelCache.cache_store.read(@paranoid.second_level_cache_key)
14
+ assert_nil User.read_second_level_cache(@paranoid.id)
15
+ end
16
+ end
@@ -2,8 +2,8 @@
2
2
 
3
3
  require "test_helper"
4
4
 
5
- class PreloaderTest < ActiveSupport::TestCase
6
- def test_belongs_to_preload_caches_includes
5
+ class PreloaderBelongsToTest < ActiveSupport::TestCase
6
+ def test_preload_caches_includes
7
7
  topics = [
8
8
  Topic.create(title: "title1", body: "body1"),
9
9
  Topic.create(title: "title2", body: "body2"),
@@ -18,7 +18,7 @@ class PreloaderTest < ActiveSupport::TestCase
18
18
  assert_equal topics, results.map(&:topic)
19
19
  end
20
20
 
21
- def test_belongs_to_when_read_multi_missed_from_cache_ar_will_fetch_missed_records_from_db
21
+ def test_when_read_multi_missed_from_cache_ar_will_fetch_missed_records_from_db
22
22
  topics = [
23
23
  Topic.create(title: "title1", body: "body1"),
24
24
  Topic.create(title: "title2", body: "body2"),
@@ -39,19 +39,21 @@ class PreloaderTest < ActiveSupport::TestCase
39
39
  assert_equal topics, results.map(&:topic)
40
40
  end
41
41
 
42
- def test_has_many_preloader_returns_correct_results
43
- topic = Topic.create(id: 1)
44
- Post.create(id: 1)
45
- post = topic.posts.create
46
-
47
- assert_equal [post], Topic.includes(:posts).find(1).posts
42
+ def test_preloader_caches_includes_tried_set_inverse_instance
43
+ user_id = Time.current.to_i
44
+ Account.create(site: "foobar", user_id: user_id)
45
+ User.create(id: user_id, name: "foobar", email: "foobar@test.com")
46
+ accounts = Account.includes(:user)
47
+ assert_equal accounts.first.object_id, accounts.first.user.account.object_id
48
48
  end
49
49
 
50
- def test_has_one_preloader_returns_correct_results
51
- user = User.create(id: 1)
52
- Account.create(id: 1)
53
- account = user.create_account
54
-
55
- assert_equal account, User.includes(:account).find(1).account
50
+ def test_preloader_from_db_when_exists_scope
51
+ user = User.create
52
+ book = user.books.create
53
+ image = book.images.create
54
+ book.toggle!(:normal)
55
+ assert_queries(:any) do
56
+ assert_nil Image.includes(:imagable).where(id: image.id).first.imagable
57
+ end
56
58
  end
57
59
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ class PreloaderHasManyTest < ActiveSupport::TestCase
6
+ def test_preloader_returns_correct_records
7
+ topic = Topic.create(id: 1)
8
+ Post.create(id: 1)
9
+ post = topic.posts.create
10
+
11
+ assert_equal [post], Topic.includes(:posts).find(1).posts
12
+ end
13
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ class PreloaderHasOneTest < ActiveSupport::TestCase
6
+ # def test_preload_caches_includes
7
+ # users = User.create([
8
+ # { name: "foobar1", email: "foobar1@test.com" },
9
+ # { name: "foobar2", email: "foobar2@test.com" },
10
+ # { name: "foobar3", email: "foobar3@test.com" }
11
+ # ])
12
+ # namespaces = users.map { |user| user.create_namespace(name: user.name) }
13
+
14
+ # assert_queries(2) { User.includes(:namespace).order(id: :asc).to_a } # Write cache
15
+ # assert_queries(1) do
16
+ # assert_equal namespaces, User.includes(:namespace).order(id: :asc).map(&:namespace)
17
+ # end
18
+ # end
19
+
20
+ # def test_when_read_multi_missed_from_cache_should_will_fetch_missed_records_from_db
21
+ # users = User.create([
22
+ # { name: "foobar1", email: "foobar1@test.com" },
23
+ # { name: "foobar2", email: "foobar2@test.com" },
24
+ # { name: "foobar3", email: "foobar3@test.com" }
25
+ # ])
26
+ # namespaces = users.map { |user| user.create_namespace(name: user.name) }
27
+ # assert_queries(2) { User.includes(:namespace).order(id: :asc).to_a } # Write cache
28
+ # expired_namespace = namespaces.first
29
+ # expired_namespace.expire_second_level_cache
30
+
31
+ # assert_queries(2) do
32
+ # assert_sql(/WHERE\s\"namespaces\".\"kind\"\sIS\sNULL\sAND\s\"namespaces\"\.\"user_id\"\s=\s?/m) do
33
+ # results = User.includes(:namespace).order(id: :asc).to_a
34
+ # assert_equal namespaces, results.map(&:namespace)
35
+ # assert_equal expired_namespace, results.first.namespace
36
+ # end
37
+ # end
38
+ # end
39
+
40
+ # def test_preloader_returns_correct_records_after_modify
41
+ # user = User.create(name: "foobar", email: "foobar@test.com")
42
+
43
+ # old_namespace = user.create_namespace(name: "old")
44
+ # assert_queries(2) { User.includes(:namespace).order(id: :asc).to_a } # Write cache
45
+ # assert_queries(1) do
46
+ # assert_equal old_namespace, User.includes(:namespace).first.namespace
47
+ # end
48
+
49
+ # new_namespace = user.create_namespace(name: "new")
50
+ # assert_queries(2) { User.includes(:namespace).order(id: :asc).to_a } # Write cache
51
+ # assert_queries(1) do
52
+ # assert_equal new_namespace, User.includes(:namespace).first.namespace
53
+ # end
54
+ # end
55
+
56
+ # def test_preloader_caches_includes_tried_set_inverse_instance
57
+ # User.create(name: "foobar", email: "foobar@test.com").create_account(site: "foobar")
58
+ # users = User.includes(:account)
59
+ # assert_equal users.first.object_id, users.first.account.user.object_id
60
+ # end
61
+
62
+ def test_has_one_preloader_returns_correct_results
63
+ user = User.create(id: 1)
64
+ Account.create(id: 1)
65
+ account = user.create_account
66
+
67
+ assert_equal account, User.includes(:account).find(1).account
68
+ end
69
+ end
@@ -25,7 +25,7 @@ class RecordMarshalTest < ActiveSupport::TestCase
25
25
  dumped = RecordMarshal.dump(@user)
26
26
  assert dumped.is_a?(Array)
27
27
  assert_equal "User", dumped[0]
28
- assert_equal @user.attributes, dumped[1]
28
+ assert_equal dumped[1], ActiveRecord::Base.connection.select_all(User.where(id: @user.id)).first
29
29
  end
30
30
 
31
31
  def test_should_load_active_record_object
@@ -16,6 +16,7 @@ require "second_level_cache"
16
16
 
17
17
  ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
18
18
 
19
+ require "model/application_record"
19
20
  require "model/user"
20
21
  require "model/book"
21
22
  require "model/image"
@@ -25,6 +26,8 @@ require "model/order"
25
26
  require "model/order_item"
26
27
  require "model/account"
27
28
  require "model/animal"
29
+ require "model/contribution"
30
+ require "model/paranoid"
28
31
 
29
32
  DatabaseCleaner[:active_record].strategy = :truncation
30
33
 
@@ -32,10 +35,6 @@ SecondLevelCache.configure do |config|
32
35
  config.cache_store = ActiveSupport::Cache::MemoryStore.new
33
36
  end
34
37
 
35
- SecondLevelCache.logger.level = Logger::ERROR
36
- ActiveSupport::Cache::MemoryStore.logger = SecondLevelCache.logger
37
- ActiveRecord::Base.logger = SecondLevelCache.logger
38
-
39
38
  module ActiveSupport
40
39
  class TestCase
41
40
  setup do
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: second_level_cache
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.0
4
+ version: 2.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hooopo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-08-19 00:00:00.000000000 Z
11
+ date: 2020-07-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: activesupport
14
+ name: activerecord
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
@@ -31,7 +31,7 @@ dependencies:
31
31
  - !ruby/object:Gem::Version
32
32
  version: '7'
33
33
  - !ruby/object:Gem::Dependency
34
- name: activerecord
34
+ name: activesupport
35
35
  requirement: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - ">="
@@ -51,21 +51,7 @@ dependencies:
51
51
  - !ruby/object:Gem::Version
52
52
  version: '7'
53
53
  - !ruby/object:Gem::Dependency
54
- name: sqlite3
55
- requirement: !ruby/object:Gem::Requirement
56
- requirements:
57
- - - ">"
58
- - !ruby/object:Gem::Version
59
- version: '1.4'
60
- type: :development
61
- prerelease: false
62
- version_requirements: !ruby/object:Gem::Requirement
63
- requirements:
64
- - - ">"
65
- - !ruby/object:Gem::Version
66
- version: '1.4'
67
- - !ruby/object:Gem::Dependency
68
- name: rake
54
+ name: database_cleaner
69
55
  requirement: !ruby/object:Gem::Requirement
70
56
  requirements:
71
57
  - - ">="
@@ -79,7 +65,7 @@ dependencies:
79
65
  - !ruby/object:Gem::Version
80
66
  version: '0'
81
67
  - !ruby/object:Gem::Dependency
82
- name: pry
68
+ name: rake
83
69
  requirement: !ruby/object:Gem::Requirement
84
70
  requirements:
85
71
  - - ">="
@@ -93,7 +79,7 @@ dependencies:
93
79
  - !ruby/object:Gem::Version
94
80
  version: '0'
95
81
  - !ruby/object:Gem::Dependency
96
- name: database_cleaner
82
+ name: rubocop
97
83
  requirement: !ruby/object:Gem::Requirement
98
84
  requirements:
99
85
  - - ">="
@@ -107,19 +93,19 @@ dependencies:
107
93
  - !ruby/object:Gem::Version
108
94
  version: '0'
109
95
  - !ruby/object:Gem::Dependency
110
- name: rubocop
96
+ name: sqlite3
111
97
  requirement: !ruby/object:Gem::Requirement
112
98
  requirements:
113
- - - "~>"
99
+ - - ">"
114
100
  - !ruby/object:Gem::Version
115
- version: 0.52.0
101
+ version: '1.4'
116
102
  type: :development
117
103
  prerelease: false
118
104
  version_requirements: !ruby/object:Gem::Requirement
119
105
  requirements:
120
- - - "~>"
106
+ - - ">"
121
107
  - !ruby/object:Gem::Version
122
- version: 0.52.0
108
+ version: '1.4'
123
109
  description: Write Through and Read Through caching library inspired by CacheMoney
124
110
  and cache_fu, support ActiveRecord 4.
125
111
  email:
@@ -142,7 +128,9 @@ files:
142
128
  - lib/second_level_cache/active_record/has_one_association.rb
143
129
  - lib/second_level_cache/active_record/persistence.rb
144
130
  - lib/second_level_cache/active_record/preloader.rb
131
+ - lib/second_level_cache/adapter/paranoia.rb
145
132
  - lib/second_level_cache/config.rb
133
+ - lib/second_level_cache/log_subscriber.rb
146
134
  - lib/second_level_cache/mixin.rb
147
135
  - lib/second_level_cache/record_marshal.rb
148
136
  - lib/second_level_cache/record_relation.rb
@@ -157,17 +145,23 @@ files:
157
145
  - test/has_one_association_test.rb
158
146
  - test/model/account.rb
159
147
  - test/model/animal.rb
148
+ - test/model/application_record.rb
160
149
  - test/model/book.rb
150
+ - test/model/contribution.rb
161
151
  - test/model/image.rb
162
152
  - test/model/order.rb
163
153
  - test/model/order_item.rb
154
+ - test/model/paranoid.rb
164
155
  - test/model/post.rb
165
156
  - test/model/topic.rb
166
157
  - test/model/user.rb
158
+ - test/paranoid_test.rb
167
159
  - test/persistence_test.rb
168
160
  - test/polymorphic_association_test.rb
161
+ - test/preloader_belongs_to_test.rb
162
+ - test/preloader_has_many_test.rb
163
+ - test/preloader_has_one_test.rb
169
164
  - test/preloader_non_integer_test.rb
170
- - test/preloader_test.rb
171
165
  - test/record_marshal_test.rb
172
166
  - test/require_test.rb
173
167
  - test/second_level_cache_test.rb
@@ -201,24 +195,30 @@ summary: 'SecondLevelCache is a write-through and read-through caching library i
201
195
  is a cache miss, it will populate the cache. Write-Through: As objects are created,
202
196
  updated, and deleted, all of the caches are automatically kept up-to-date and coherent.'
203
197
  test_files:
198
+ - test/preloader_belongs_to_test.rb
204
199
  - test/polymorphic_association_test.rb
205
200
  - test/require_test.rb
206
- - test/preloader_test.rb
201
+ - test/paranoid_test.rb
207
202
  - test/finder_methods_test.rb
203
+ - test/preloader_has_one_test.rb
208
204
  - test/preloader_non_integer_test.rb
209
205
  - test/belongs_to_association_test.rb
210
206
  - test/second_level_cache_test.rb
211
207
  - test/enum_attr_test.rb
212
208
  - test/record_marshal_test.rb
209
+ - test/preloader_has_many_test.rb
213
210
  - test/persistence_test.rb
214
211
  - test/single_table_inheritance_test.rb
215
212
  - test/model/image.rb
216
213
  - test/model/account.rb
217
214
  - test/model/order_item.rb
215
+ - test/model/contribution.rb
218
216
  - test/model/book.rb
219
217
  - test/model/topic.rb
220
218
  - test/model/animal.rb
221
219
  - test/model/order.rb
220
+ - test/model/paranoid.rb
221
+ - test/model/application_record.rb
222
222
  - test/model/post.rb
223
223
  - test/model/user.rb
224
224
  - test/fetch_by_uniq_key_test.rb