identity_cache 0.3.1 → 0.3.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.
@@ -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'