identity_cache 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  require "test_helper"
2
2
 
3
- class PrefetchNormalizedAssociationsTest < IdentityCache::TestCase
3
+ class PrefetchAssociationsTest < IdentityCache::TestCase
4
4
  NAMESPACE = IdentityCache.cache_namespace
5
5
 
6
6
  def setup
@@ -14,10 +14,120 @@ class PrefetchNormalizedAssociationsTest < IdentityCache::TestCase
14
14
  @tenth_blob_key = "#{NAMESPACE}blob:Item:#{cache_hash("created_at:datetime,id:integer,item_id:integer,title:string,updated_at:datetime")}:10"
15
15
  end
16
16
 
17
+ def test_prefetch_associations_on_fetched_records
18
+ Item.send(:cache_belongs_to, :item)
19
+ john = Item.create!(:title => 'john')
20
+ jim = Item.create!(:title => 'jim')
21
+ @bob.update_column(:item_id, john.id)
22
+ @joe.update_column(:item_id, jim.id)
23
+ items = Item.fetch_multi(@bob.id, @joe.id, @fred.id)
24
+
25
+ spy = Spy.on(Item, :fetch_multi).and_call_through
26
+
27
+ Item.prefetch_associations(:item, items)
28
+
29
+ assert spy.calls.one?{ |call| call.args == [[john.id, jim.id]] }
30
+ end
31
+
32
+ def test_prefetch_associations_on_db_records
33
+ Item.send(:cache_has_many, :associated_records, :embed => true)
34
+ AssociatedRecord.send(:cache_has_many, :deeply_associated_records, :embed => :ids)
35
+
36
+ setup_has_many_children_and_grandchildren(@bob)
37
+
38
+ item = Item.find(@bob.id)
39
+
40
+ assert_no_queries do
41
+ assert_memcache_operations(1) do
42
+ Item.prefetch_associations(:associated_records, [item])
43
+ end
44
+ assert_memcache_operations(0) do
45
+ item.fetch_associated_records.each(&:fetch_deeply_associated_record_ids)
46
+ end
47
+ assert_memcache_operations(1) do
48
+ Item.prefetch_associations({associated_records: :deeply_associated_records}, [item])
49
+ end
50
+ assert_memcache_operations(0) do
51
+ item.fetch_associated_records.each(&:fetch_deeply_associated_records)
52
+ end
53
+ end
54
+ end
55
+
56
+ def test_prefetch_associations_without_using_cache
57
+ Item.send(:cache_has_many, :associated_records, :embed => true)
58
+
59
+ associated1 = @bob.associated_records.create!(name: 'foo')
60
+ associated2 = @joe.associated_records.create!(name: 'bar')
61
+ items = [@bob, @joe].map(&:reload)
62
+
63
+ Item.transaction do
64
+ assert_memcache_operations(0) do
65
+ assert_queries(1) do
66
+ Item.prefetch_associations(:associated_records, items)
67
+ end
68
+ assert_no_queries do
69
+ assert_equal [[associated1], [associated2]], items.map(&:fetch_associated_records)
70
+ end
71
+ end
72
+ end
73
+ end
74
+
75
+ def test_prefetch_associations_cached_belongs_to
76
+ Item.send(:cache_belongs_to, :item)
77
+ @bob.update_attributes!(item_id: @joe.id)
78
+ @joe.update_attributes!(item_id: @fred.id)
79
+ @bob.fetch_item
80
+ @joe.fetch_item
81
+ items = [@bob, @joe].map(&:reload)
82
+
83
+ assert_no_queries do
84
+ assert_memcache_operations(1) do
85
+ Item.prefetch_associations(:item, items)
86
+ end
87
+ assert_memcache_operations(0) do
88
+ items.each { |item| item.fetch_item }
89
+ end
90
+ assert_memcache_operations(0) do
91
+ Item.prefetch_associations(:item, items)
92
+ end
93
+ end
94
+ end
95
+
96
+ def test_prefetch_associations_with_nil_cached_belongs_to
97
+ Item.send(:cache_belongs_to, :item)
98
+ @bob.update_attributes!(item_id: 1234)
99
+ assert_equal nil, @bob.fetch_item
100
+
101
+ assert_no_queries do
102
+ assert_memcache_operations(0) do
103
+ Item.prefetch_associations(:item, [@bob])
104
+ end
105
+ end
106
+ end
107
+
108
+ def test_prefetch_associations_on_association
109
+ AssociatedRecord.send(:cache_has_many, :deeply_associated_records, embed: true)
110
+
111
+ setup_has_many_children_and_grandchildren(@bob)
112
+
113
+ associated_records = @bob.associated_records
114
+
115
+ assert_queries(1) do
116
+ assert_memcache_operations(1) do
117
+ AssociatedRecord.prefetch_associations(:deeply_associated_records, associated_records)
118
+ end
119
+ end
120
+ assert_no_queries do
121
+ assert_memcache_operations(0) do
122
+ associated_records.each(&:fetch_deeply_associated_records)
123
+ end
124
+ end
125
+ end
126
+
17
127
  def test_fetch_with_includes_option
18
128
  Item.send(:cache_belongs_to, :item)
19
129
  john = Item.create!(title: 'john')
20
- @bob.update_column(:item_id, john)
130
+ @bob.update_column(:item_id, john.id)
21
131
 
22
132
  spy = Spy.on(Item, :fetch_multi).and_call_through
23
133
 
@@ -30,8 +140,8 @@ class PrefetchNormalizedAssociationsTest < IdentityCache::TestCase
30
140
  Item.send(:cache_belongs_to, :item)
31
141
  john = Item.create!(:title => 'john')
32
142
  jim = Item.create!(:title => 'jim')
33
- @bob.update_column(:item_id, john)
34
- @joe.update_column(:item_id, jim)
143
+ @bob.update_column(:item_id, john.id)
144
+ @joe.update_column(:item_id, jim.id)
35
145
 
36
146
  spy = Spy.on(Item, :fetch_multi).and_call_through
37
147
 
@@ -78,7 +188,6 @@ class PrefetchNormalizedAssociationsTest < IdentityCache::TestCase
78
188
  end
79
189
 
80
190
  def test_fetch_multi_batch_fetches_first_level_associations_who_dont_include_identity_cache
81
- Item.send(:has_many, :not_cached_records)
82
191
  Item.send(:cache_has_many, :not_cached_records, :embed => true)
83
192
 
84
193
  @bob_child = @bob.not_cached_records.create!(:name => "bob child")
@@ -96,7 +205,7 @@ class PrefetchNormalizedAssociationsTest < IdentityCache::TestCase
96
205
  Item.send(:cache_has_many, :associated_records, :embed => :ids)
97
206
  AssociatedRecord.send(:cache_has_many, :deeply_associated_records, :embed => :ids)
98
207
 
99
- child_records, grandchildren = setup_has_many_children_and_grandchildren(@bob, @joe)
208
+ _child_records, grandchildren = setup_has_many_children_and_grandchildren(@bob, @joe)
100
209
 
101
210
  assert_memcache_operations(3) do
102
211
  @cached_bob, @cached_joe = Item.fetch_multi(@bob.id, @joe.id, :includes => {:associated_records => :deeply_associated_records})
@@ -151,7 +260,7 @@ class PrefetchNormalizedAssociationsTest < IdentityCache::TestCase
151
260
  Item.send(:cache_has_many, :associated_records, :embed => true)
152
261
  AssociatedRecord.send(:cache_has_many, :deeply_associated_records, :embed => :ids)
153
262
 
154
- child_records, grandchildren = setup_has_many_children_and_grandchildren(@bob, @joe)
263
+ _child_records, grandchildren = setup_has_many_children_and_grandchildren(@bob, @joe)
155
264
 
156
265
  assert_memcache_operations(2) do
157
266
  @cached_bob, @cached_joe = Item.fetch_multi(@bob.id, @joe.id, :includes => {:associated_records => :deeply_associated_records})
@@ -200,7 +309,7 @@ class PrefetchNormalizedAssociationsTest < IdentityCache::TestCase
200
309
  Item.send(:cache_belongs_to, :item)
201
310
  Item.cache_index :title
202
311
  john = Item.create!(title: 'john')
203
- @bob.update_column(:item_id, john)
312
+ @bob.update_column(:item_id, john.id)
204
313
 
205
314
  spy = Spy.on(Item, :fetch_multi).and_call_through
206
315
 
@@ -213,7 +322,7 @@ class PrefetchNormalizedAssociationsTest < IdentityCache::TestCase
213
322
  Item.send(:cache_belongs_to, :item)
214
323
  Item.cache_index :title, :unique => true
215
324
  john = Item.create!(title: 'john')
216
- @bob.update_column(:item_id, john)
325
+ @bob.update_column(:item_id, john.id)
217
326
 
218
327
  spy = Spy.on(Item, :fetch_multi).and_call_through
219
328
 
@@ -61,7 +61,7 @@ class RecursiveDenormalizedHasManyTest < IdentityCache::TestCase
61
61
  # one for the mid level has_one association
62
62
  # one for the deep level level has_many on the mid level has_many association
63
63
  # one for the deep level level has_many on the mid level has_one association
64
- record_from_cache_miss = Item.fetch(@record.id)
64
+ Item.fetch(@record.id)
65
65
  end
66
66
  end
67
67
 
@@ -88,6 +88,22 @@ class RecursiveDenormalizedHasManyTest < IdentityCache::TestCase
88
88
  @deeply_associated_record.save!
89
89
  end
90
90
 
91
+ def test_set_inverse_associations
92
+ DeeplyAssociatedRecord.cache_belongs_to :associated_record
93
+ AssociatedRecord.cache_belongs_to :item
94
+ Item.fetch(@record.id) # warm cache
95
+
96
+ item = Item.fetch(@record.id)
97
+
98
+ assert_queries(0) do
99
+ assert_memcache_operations(0) do
100
+ associated_record = item.fetch_associated_records.to_a.first
101
+ deeply_associated_record = associated_record.fetch_deeply_associated_records.first
102
+ assert_equal item.id, deeply_associated_record.fetch_associated_record.fetch_item.id
103
+ end
104
+ end
105
+ end
106
+
91
107
  end
92
108
 
93
109
  class RecursiveNormalizedHasManyTest < IdentityCache::TestCase
@@ -103,7 +119,7 @@ class RecursiveNormalizedHasManyTest < IdentityCache::TestCase
103
119
 
104
120
  def test_cache_repopulation_should_not_fetch_non_embedded_associations
105
121
  Item.any_instance.expects(:fetch_associated_records).never
106
- record_from_cache_miss = Item.fetch(@record.id)
122
+ Item.fetch(@record.id) # cache miss
107
123
  end
108
124
  end
109
125
 
@@ -89,10 +89,12 @@ class SchemaChangeTest < IdentityCache::TestCase
89
89
 
90
90
  record = Item.fetch(@record.id)
91
91
 
92
+ teardown_models
93
+ setup_models
94
+
92
95
  Item.cache_has_many :polymorphic_records, :inverse_name => :owner, :embed => true
93
96
  read_new_schema
94
97
 
95
- Item.expects(:resolve_cache_miss).returns(@record)
96
98
  record = Item.fetch(@record.id)
97
99
  end
98
100
 
@@ -103,7 +105,6 @@ class SchemaChangeTest < IdentityCache::TestCase
103
105
  Item.cache_has_many :polymorphic_records, :inverse_name => :owner, :embed => :ids
104
106
  read_new_schema
105
107
 
106
- Item.expects(:resolve_cache_miss).returns(@record)
107
108
  record = Item.fetch(@record.id)
108
109
  end
109
110
  end
data/test/test_helper.rb CHANGED
@@ -11,7 +11,7 @@ require 'active_support/cache/memcached_store'
11
11
  require File.dirname(__FILE__) + '/../lib/identity_cache'
12
12
 
13
13
  DatabaseConnection.setup
14
- ActiveSupport::Cache::Store.instrument = true
14
+ ActiveSupport::Cache::Store.instrument = true if ActiveSupport.version < Gem::Version.new("4.2.0")
15
15
 
16
16
  # This patches AR::MemcacheStore to notify AS::Notifications upon read_multis like the rest of rails does
17
17
  class ActiveSupport::Cache::MemcachedStore
@@ -38,7 +38,9 @@ class IdentityCache::TestCase < Minitest::Test
38
38
  DatabaseConnection.create_tables
39
39
 
40
40
  IdentityCache.logger = Logger.new(nil)
41
- IdentityCache.cache_backend = @backend = ActiveSupport::Cache::MemcachedStore.new("localhost:11211", :support_cas => true)
41
+
42
+ memcached_host = ENV['MEMCACHED_HOST'] || "127.0.0.1"
43
+ IdentityCache.cache_backend = @backend = ActiveSupport::Cache::MemcachedStore.new("#{memcached_host}:11211", :support_cas => true)
42
44
 
43
45
  setup_models
44
46
  end
metadata CHANGED
@@ -1,20 +1,20 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: identity_cache
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Camilo Lopez
8
8
  - Tom Burns
9
9
  - Harry Brundage
10
- - Dylan Smith
10
+ - Dylan Thacker-Smith
11
11
  - Tobias Lutke
12
12
  - Arthur Neves
13
13
  - Francis Bogsanyi
14
14
  autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
- date: 2016-01-20 00:00:00.000000000 Z
17
+ date: 2016-08-10 00:00:00.000000000 Z
18
18
  dependencies:
19
19
  - !ruby/object:Gem::Dependency
20
20
  name: ar_transaction_changes
@@ -36,14 +36,14 @@ dependencies:
36
36
  requirements:
37
37
  - - ">="
38
38
  - !ruby/object:Gem::Version
39
- version: 4.0.4
39
+ version: 4.2.0
40
40
  type: :runtime
41
41
  prerelease: false
42
42
  version_requirements: !ruby/object:Gem::Requirement
43
43
  requirements:
44
44
  - - ">="
45
45
  - !ruby/object:Gem::Version
46
- version: 4.0.4
46
+ version: 4.2.0
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: memcached
49
49
  requirement: !ruby/object:Gem::Requirement
@@ -186,23 +186,22 @@ dependencies:
186
186
  version: '0'
187
187
  description: Opt in read through ActiveRecord caching.
188
188
  email:
189
- - harry.brundage@shopify.com
189
+ - gems@shopify.com
190
190
  executables: []
191
191
  extensions: []
192
192
  extra_rdoc_files: []
193
193
  files:
194
194
  - ".gitignore"
195
- - ".ruby-version"
196
195
  - ".travis.yml"
197
196
  - CHANGELOG.md
198
197
  - CONTRIBUTING.md
199
198
  - Gemfile
200
- - Gemfile.rails40
201
- - Gemfile.rails41
202
199
  - Gemfile.rails42
200
+ - Gemfile.rails50
203
201
  - LICENSE
204
202
  - README.md
205
203
  - Rakefile
204
+ - dev.yml
206
205
  - identity_cache.gemspec
207
206
  - lib/identity_cache.rb
208
207
  - lib/identity_cache/belongs_to_caching.rb
@@ -238,11 +237,12 @@ files:
238
237
  - test/helpers/update_serialization_format.rb
239
238
  - test/identity_cache_test.rb
240
239
  - test/index_cache_test.rb
240
+ - test/memoized_attributes_test.rb
241
241
  - test/memoized_cache_proxy_test.rb
242
242
  - test/normalized_belongs_to_test.rb
243
243
  - test/normalized_has_many_test.rb
244
244
  - test/normalized_has_one_test.rb
245
- - test/prefetch_normalized_associations_test.rb
245
+ - test/prefetch_associations_test.rb
246
246
  - test/readonly_test.rb
247
247
  - test/recursive_denormalized_has_many_test.rb
248
248
  - test/save_test.rb
@@ -268,7 +268,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
268
268
  version: '0'
269
269
  requirements: []
270
270
  rubyforge_project:
271
- rubygems_version: 2.2.3
271
+ rubygems_version: 2.5.1
272
272
  signing_key:
273
273
  specification_version: 4
274
274
  summary: IdentityCache lets you specify how you want to cache your model objects,
@@ -293,11 +293,12 @@ test_files:
293
293
  - test/helpers/update_serialization_format.rb
294
294
  - test/identity_cache_test.rb
295
295
  - test/index_cache_test.rb
296
+ - test/memoized_attributes_test.rb
296
297
  - test/memoized_cache_proxy_test.rb
297
298
  - test/normalized_belongs_to_test.rb
298
299
  - test/normalized_has_many_test.rb
299
300
  - test/normalized_has_one_test.rb
300
- - test/prefetch_normalized_associations_test.rb
301
+ - test/prefetch_associations_test.rb
301
302
  - test/readonly_test.rb
302
303
  - test/recursive_denormalized_has_many_test.rb
303
304
  - test/save_test.rb
data/.ruby-version DELETED
@@ -1 +0,0 @@
1
- 2.2.2
data/Gemfile.rails40 DELETED
@@ -1,6 +0,0 @@
1
- source 'https://rubygems.org'
2
- gemspec
3
-
4
- gem 'activerecord', '~> 4.0.4'
5
- gem 'activesupport', '~> 4.0.4'
6
- gem 'mysql2', '~> 0.3.13'
data/Gemfile.rails41 DELETED
@@ -1,6 +0,0 @@
1
- source 'https://rubygems.org'
2
- gemspec
3
-
4
- gem 'activerecord', '~> 4.1.0'
5
- gem 'activesupport', '~> 4.1.0'
6
- gem 'mysql2', '~> 0.3.13'