second_level_cache 2.5.2 → 2.6.3

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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +24 -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/preloader.rb +34 -28
  12. data/lib/second_level_cache/adapter/paranoia.rb +24 -0
  13. data/lib/second_level_cache/config.rb +1 -0
  14. data/lib/second_level_cache/log_subscriber.rb +15 -0
  15. data/lib/second_level_cache/mixin.rb +0 -12
  16. data/lib/second_level_cache/record_marshal.rb +7 -40
  17. data/lib/second_level_cache/version.rb +1 -1
  18. data/second_level_cache.gemspec +23 -22
  19. data/test/active_record_test_case_helper.rb +11 -1
  20. data/test/fetch_by_uniq_key_test.rb +47 -4
  21. data/test/finder_methods_test.rb +39 -0
  22. data/test/has_one_association_test.rb +16 -4
  23. data/test/model/account.rb +2 -2
  24. data/test/model/animal.rb +1 -1
  25. data/test/model/application_record.rb +3 -0
  26. data/test/model/book.rb +6 -1
  27. data/test/model/contribution.rb +14 -0
  28. data/test/model/image.rb +1 -1
  29. data/test/model/order.rb +1 -1
  30. data/test/model/order_item.rb +1 -1
  31. data/test/model/paranoid.rb +10 -0
  32. data/test/model/post.rb +1 -1
  33. data/test/model/topic.rb +1 -1
  34. data/test/model/user.rb +7 -7
  35. data/test/paranoid_test.rb +18 -0
  36. data/test/{preloader_test.rb → preloader_belongs_to_test.rb} +17 -15
  37. data/test/preloader_has_many_test.rb +13 -0
  38. data/test/preloader_has_one_test.rb +69 -0
  39. data/test/record_marshal_test.rb +1 -1
  40. data/test/test_helper.rb +3 -5
  41. metadata +31 -17
@@ -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,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ class ParanoidTest < ActiveSupport::TestCase
6
+ def setup
7
+ skip unless defined?(Paranoi)
8
+ @paranoid = Paranoid.create
9
+ end
10
+
11
+ def test_should_expire_cache_when_destroy
12
+ skip unless defined(Paranoi)
13
+ @paranoid.destroy
14
+ assert_nil Paranoid.find_by(id: @paranoid.id)
15
+ assert_nil SecondLevelCache.cache_store.read(@paranoid.second_level_cache_key)
16
+ assert_nil User.read_second_level_cache(@paranoid.id)
17
+ end
18
+ 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
@@ -6,7 +6,6 @@ require "active_support/test_case"
6
6
  require "active_record_test_case_helper"
7
7
  require "database_cleaner"
8
8
  require "active_record"
9
- require "paranoia"
10
9
  require "pry"
11
10
  ActiveSupport.test_order = :sorted if ActiveSupport.respond_to?(:test_order=)
12
11
  # Force hook :active_record on_load event to make sure loader can work.
@@ -16,6 +15,7 @@ require "second_level_cache"
16
15
 
17
16
  ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
18
17
 
18
+ require "model/application_record"
19
19
  require "model/user"
20
20
  require "model/book"
21
21
  require "model/image"
@@ -25,6 +25,8 @@ require "model/order"
25
25
  require "model/order_item"
26
26
  require "model/account"
27
27
  require "model/animal"
28
+ require "model/contribution"
29
+ require "model/paranoid" if defined?(Paranoid)
28
30
 
29
31
  DatabaseCleaner[:active_record].strategy = :truncation
30
32
 
@@ -32,10 +34,6 @@ SecondLevelCache.configure do |config|
32
34
  config.cache_store = ActiveSupport::Cache::MemoryStore.new
33
35
  end
34
36
 
35
- SecondLevelCache.logger.level = Logger::ERROR
36
- ActiveSupport::Cache::MemoryStore.logger = SecondLevelCache.logger
37
- ActiveRecord::Base.logger = SecondLevelCache.logger
38
-
39
37
  module ActiveSupport
40
38
  class TestCase
41
39
  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.2
4
+ version: 2.6.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hooopo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-01-02 00:00:00.000000000 Z
11
+ date: 2020-07-17 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,19 +51,19 @@ dependencies:
51
51
  - !ruby/object:Gem::Version
52
52
  version: '7'
53
53
  - !ruby/object:Gem::Dependency
54
- name: sqlite3
54
+ name: database_cleaner
55
55
  requirement: !ruby/object:Gem::Requirement
56
56
  requirements:
57
- - - ">"
57
+ - - ">="
58
58
  - !ruby/object:Gem::Version
59
- version: '1.4'
59
+ version: '0'
60
60
  type: :development
61
61
  prerelease: false
62
62
  version_requirements: !ruby/object:Gem::Requirement
63
63
  requirements:
64
- - - ">"
64
+ - - ">="
65
65
  - !ruby/object:Gem::Version
66
- version: '1.4'
66
+ version: '0'
67
67
  - !ruby/object:Gem::Dependency
68
68
  name: rake
69
69
  requirement: !ruby/object:Gem::Requirement
@@ -79,7 +79,7 @@ dependencies:
79
79
  - !ruby/object:Gem::Version
80
80
  version: '0'
81
81
  - !ruby/object:Gem::Dependency
82
- name: database_cleaner
82
+ name: rubocop
83
83
  requirement: !ruby/object:Gem::Requirement
84
84
  requirements:
85
85
  - - ">="
@@ -93,19 +93,19 @@ dependencies:
93
93
  - !ruby/object:Gem::Version
94
94
  version: '0'
95
95
  - !ruby/object:Gem::Dependency
96
- name: rubocop
96
+ name: sqlite3
97
97
  requirement: !ruby/object:Gem::Requirement
98
98
  requirements:
99
- - - "~>"
99
+ - - ">"
100
100
  - !ruby/object:Gem::Version
101
- version: 0.52.0
101
+ version: '1.4'
102
102
  type: :development
103
103
  prerelease: false
104
104
  version_requirements: !ruby/object:Gem::Requirement
105
105
  requirements:
106
- - - "~>"
106
+ - - ">"
107
107
  - !ruby/object:Gem::Version
108
- version: 0.52.0
108
+ version: '1.4'
109
109
  description: Write Through and Read Through caching library inspired by CacheMoney
110
110
  and cache_fu, support ActiveRecord 4.
111
111
  email:
@@ -128,7 +128,9 @@ files:
128
128
  - lib/second_level_cache/active_record/has_one_association.rb
129
129
  - lib/second_level_cache/active_record/persistence.rb
130
130
  - lib/second_level_cache/active_record/preloader.rb
131
+ - lib/second_level_cache/adapter/paranoia.rb
131
132
  - lib/second_level_cache/config.rb
133
+ - lib/second_level_cache/log_subscriber.rb
132
134
  - lib/second_level_cache/mixin.rb
133
135
  - lib/second_level_cache/record_marshal.rb
134
136
  - lib/second_level_cache/record_relation.rb
@@ -143,17 +145,23 @@ files:
143
145
  - test/has_one_association_test.rb
144
146
  - test/model/account.rb
145
147
  - test/model/animal.rb
148
+ - test/model/application_record.rb
146
149
  - test/model/book.rb
150
+ - test/model/contribution.rb
147
151
  - test/model/image.rb
148
152
  - test/model/order.rb
149
153
  - test/model/order_item.rb
154
+ - test/model/paranoid.rb
150
155
  - test/model/post.rb
151
156
  - test/model/topic.rb
152
157
  - test/model/user.rb
158
+ - test/paranoid_test.rb
153
159
  - test/persistence_test.rb
154
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
155
164
  - test/preloader_non_integer_test.rb
156
- - test/preloader_test.rb
157
165
  - test/record_marshal_test.rb
158
166
  - test/require_test.rb
159
167
  - test/second_level_cache_test.rb
@@ -187,24 +195,30 @@ summary: 'SecondLevelCache is a write-through and read-through caching library i
187
195
  is a cache miss, it will populate the cache. Write-Through: As objects are created,
188
196
  updated, and deleted, all of the caches are automatically kept up-to-date and coherent.'
189
197
  test_files:
198
+ - test/preloader_belongs_to_test.rb
190
199
  - test/polymorphic_association_test.rb
191
200
  - test/require_test.rb
192
- - test/preloader_test.rb
201
+ - test/paranoid_test.rb
193
202
  - test/finder_methods_test.rb
203
+ - test/preloader_has_one_test.rb
194
204
  - test/preloader_non_integer_test.rb
195
205
  - test/belongs_to_association_test.rb
196
206
  - test/second_level_cache_test.rb
197
207
  - test/enum_attr_test.rb
198
208
  - test/record_marshal_test.rb
209
+ - test/preloader_has_many_test.rb
199
210
  - test/persistence_test.rb
200
211
  - test/single_table_inheritance_test.rb
201
212
  - test/model/image.rb
202
213
  - test/model/account.rb
203
214
  - test/model/order_item.rb
215
+ - test/model/contribution.rb
204
216
  - test/model/book.rb
205
217
  - test/model/topic.rb
206
218
  - test/model/animal.rb
207
219
  - test/model/order.rb
220
+ - test/model/paranoid.rb
221
+ - test/model/application_record.rb
208
222
  - test/model/post.rb
209
223
  - test/model/user.rb
210
224
  - test/fetch_by_uniq_key_test.rb