identity_cache 0.2.5 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -4
  3. data/CHANGELOG.md +22 -0
  4. data/Gemfile +2 -0
  5. data/Gemfile.rails40 +1 -0
  6. data/Gemfile.rails41 +1 -0
  7. data/Gemfile.rails42 +1 -0
  8. data/README.md +7 -0
  9. data/identity_cache.gemspec +1 -1
  10. data/lib/identity_cache.rb +5 -2
  11. data/lib/identity_cache/belongs_to_caching.rb +13 -5
  12. data/lib/identity_cache/cache_key_generation.rb +12 -19
  13. data/lib/identity_cache/configuration_dsl.rb +83 -84
  14. data/lib/identity_cache/parent_model_expiration.rb +4 -3
  15. data/lib/identity_cache/query_api.rb +93 -91
  16. data/lib/identity_cache/version.rb +2 -2
  17. data/test/attribute_cache_test.rb +42 -63
  18. data/test/deeply_nested_associated_record_test.rb +1 -0
  19. data/test/denormalized_has_many_test.rb +18 -0
  20. data/test/denormalized_has_one_test.rb +15 -5
  21. data/test/fetch_multi_test.rb +25 -3
  22. data/test/fetch_test.rb +20 -7
  23. data/test/fixtures/serialized_record.mysql2 +0 -0
  24. data/test/fixtures/serialized_record.postgresql +0 -0
  25. data/test/helpers/active_record_objects.rb +10 -0
  26. data/test/helpers/database_connection.rb +6 -1
  27. data/test/helpers/serialization_format.rb +1 -1
  28. data/test/index_cache_test.rb +50 -25
  29. data/test/normalized_belongs_to_test.rb +21 -6
  30. data/test/normalized_has_many_test.rb +44 -0
  31. data/test/{fetch_multi_with_batched_associations_test.rb → prefetch_normalized_associations_test.rb} +41 -3
  32. data/test/save_test.rb +14 -14
  33. data/test/schema_change_test.rb +2 -0
  34. data/test/test_helper.rb +4 -4
  35. metadata +11 -10
  36. data/Gemfile.rails32 +0 -5
  37. data/test/fixtures/serialized_record +0 -0
@@ -1,6 +1,6 @@
1
1
  require "test_helper"
2
2
 
3
- class FetchMultiWithBatchedAssociationsTest < IdentityCache::TestCase
3
+ class PrefetchNormalizedAssociationsTest < IdentityCache::TestCase
4
4
  NAMESPACE = IdentityCache.cache_namespace
5
5
 
6
6
  def setup
@@ -14,7 +14,19 @@ class FetchMultiWithBatchedAssociationsTest < 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_fetch_multi_with_includes_option_preloads_associations
17
+ def test_fetch_with_includes_option
18
+ Item.send(:cache_belongs_to, :item)
19
+ john = Item.create!(title: 'john')
20
+ @bob.update_column(:item_id, john)
21
+
22
+ spy = Spy.on(Item, :fetch_multi).and_call_through
23
+
24
+ assert_equal @bob, Item.fetch(@bob.id, includes: :item)
25
+
26
+ assert spy.calls.one?{ |call| call.args == [[john.id]] }
27
+ end
28
+
29
+ def test_fetch_multi_with_includes_option
18
30
  Item.send(:cache_belongs_to, :item)
19
31
  john = Item.create!(:title => 'john')
20
32
  jim = Item.create!(:title => 'jim')
@@ -23,7 +35,7 @@ class FetchMultiWithBatchedAssociationsTest < IdentityCache::TestCase
23
35
 
24
36
  spy = Spy.on(Item, :fetch_multi).and_call_through
25
37
 
26
- items = Item.fetch_multi(@bob.id, @joe.id, @fred.id, :includes => :item)
38
+ assert_equal [@bob, @joe, @fred], Item.fetch_multi(@bob.id, @joe.id, @fred.id, :includes => :item)
27
39
 
28
40
  assert spy.calls.one?{ |call| call.args == [[john.id, jim.id]] }
29
41
  end
@@ -184,6 +196,32 @@ class FetchMultiWithBatchedAssociationsTest < IdentityCache::TestCase
184
196
  Item.send(:find_batch, [@bob, @joe, @fred].map(&:id).map(&:to_s))
185
197
  end
186
198
 
199
+ def test_fetch_by_index_with_includes_option
200
+ Item.send(:cache_belongs_to, :item)
201
+ Item.cache_index :title
202
+ john = Item.create!(title: 'john')
203
+ @bob.update_column(:item_id, john)
204
+
205
+ spy = Spy.on(Item, :fetch_multi).and_call_through
206
+
207
+ assert_equal [@bob], Item.fetch_by_title('bob', includes: :item)
208
+
209
+ assert spy.calls.one?{ |call| call.args == [[john.id]] }
210
+ end
211
+
212
+ def test_fetch_by_unique_index_with_includes_option
213
+ Item.send(:cache_belongs_to, :item)
214
+ Item.cache_index :title, :unique => true
215
+ john = Item.create!(title: 'john')
216
+ @bob.update_column(:item_id, john)
217
+
218
+ spy = Spy.on(Item, :fetch_multi).and_call_through
219
+
220
+ assert_equal @bob, Item.fetch_by_title('bob', includes: :item)
221
+
222
+ assert spy.calls.one?{ |call| call.args == [[john.id]] }
223
+ end
224
+
187
225
  private
188
226
 
189
227
  def setup_has_many_children_and_grandchildren(*parents)
@@ -16,21 +16,21 @@ class SaveTest < IdentityCache::TestCase
16
16
  @record = Item.new
17
17
  @record.title = 'bob'
18
18
 
19
- expect_cache_delete("#{NAMESPACE}index:Item:id/title:#{cache_hash('2/bob')}")
20
- expect_cache_delete("#{NAMESPACE}index:Item:title:#{cache_hash('bob')}")
19
+ expect_cache_delete("#{NAMESPACE}attr:Item:id:id/title:#{cache_hash('2/bob')}")
20
+ expect_cache_delete("#{NAMESPACE}attr:Item:id:title:#{cache_hash('bob')}")
21
21
  expect_cache_delete("#{NAMESPACE}blob:Item:#{cache_hash("created_at:datetime,id:integer,item_id:integer,title:string,updated_at:datetime")}:2").once
22
22
  @record.save
23
23
  end
24
24
 
25
25
  def test_update
26
26
  # Regular flow, write index id, write index id/tile, delete data blob since Record has changed
27
- expect_cache_delete("#{NAMESPACE}index:Item:id/title:#{cache_hash('1/fred')}")
28
- expect_cache_delete("#{NAMESPACE}index:Item:title:#{cache_hash('fred')}")
27
+ expect_cache_delete("#{NAMESPACE}attr:Item:id:id/title:#{cache_hash('1/fred')}")
28
+ expect_cache_delete("#{NAMESPACE}attr:Item:id:title:#{cache_hash('fred')}")
29
29
  expect_cache_delete(@blob_key)
30
30
 
31
31
  # Delete index id, delete index id/title
32
- expect_cache_delete("#{NAMESPACE}index:Item:id/title:#{cache_hash('1/bob')}")
33
- expect_cache_delete("#{NAMESPACE}index:Item:title:#{cache_hash('bob')}")
32
+ expect_cache_delete("#{NAMESPACE}attr:Item:id:id/title:#{cache_hash('1/bob')}")
33
+ expect_cache_delete("#{NAMESPACE}attr:Item:id:title:#{cache_hash('bob')}")
34
34
 
35
35
  @record.title = 'fred'
36
36
  @record.save
@@ -38,8 +38,8 @@ class SaveTest < IdentityCache::TestCase
38
38
 
39
39
  def test_destroy
40
40
  # Regular flow: delete data blob, delete index id, delete index id/tile
41
- expect_cache_delete("#{NAMESPACE}index:Item:id/title:#{cache_hash('1/bob')}")
42
- expect_cache_delete("#{NAMESPACE}index:Item:title:#{cache_hash('bob')}")
41
+ expect_cache_delete("#{NAMESPACE}attr:Item:id:id/title:#{cache_hash('1/bob')}")
42
+ expect_cache_delete("#{NAMESPACE}attr:Item:id:title:#{cache_hash('bob')}")
43
43
  expect_cache_delete(@blob_key)
44
44
 
45
45
  @record.destroy
@@ -47,8 +47,8 @@ class SaveTest < IdentityCache::TestCase
47
47
 
48
48
  def test_destroy_with_changed_attributes
49
49
  # Make sure to delete the old cache index key, since the new title never ended up in an index
50
- expect_cache_delete("#{NAMESPACE}index:Item:id/title:#{cache_hash('1/bob')}")
51
- expect_cache_delete("#{NAMESPACE}index:Item:title:#{cache_hash('bob')}")
50
+ expect_cache_delete("#{NAMESPACE}attr:Item:id:id/title:#{cache_hash('1/bob')}")
51
+ expect_cache_delete("#{NAMESPACE}attr:Item:id:title:#{cache_hash('bob')}")
52
52
  expect_cache_delete(@blob_key)
53
53
 
54
54
  @record.title = 'fred'
@@ -57,16 +57,16 @@ class SaveTest < IdentityCache::TestCase
57
57
 
58
58
  def test_touch_will_expire_the_caches
59
59
  # Regular flow: delete data blob, delete index id, delete index id/tile
60
- expect_cache_delete("#{NAMESPACE}index:Item:id/title:#{cache_hash('1/bob')}")
61
- expect_cache_delete("#{NAMESPACE}index:Item:title:#{cache_hash('bob')}")
60
+ expect_cache_delete("#{NAMESPACE}attr:Item:id:id/title:#{cache_hash('1/bob')}")
61
+ expect_cache_delete("#{NAMESPACE}attr:Item:id:title:#{cache_hash('bob')}")
62
62
  expect_cache_delete(@blob_key)
63
63
 
64
64
  @record.touch
65
65
  end
66
66
 
67
67
  def test_expire_cache_works_in_a_transaction
68
- expect_cache_delete("#{NAMESPACE}index:Item:id/title:#{cache_hash('1/bob')}")
69
- expect_cache_delete("#{NAMESPACE}index:Item:title:#{cache_hash('bob')}")
68
+ expect_cache_delete("#{NAMESPACE}attr:Item:id:id/title:#{cache_hash('1/bob')}")
69
+ expect_cache_delete("#{NAMESPACE}attr:Item:id:title:#{cache_hash('bob')}")
70
70
  expect_cache_delete(@blob_key)
71
71
 
72
72
  ActiveRecord::Base.transaction do
@@ -83,6 +83,7 @@ class SchemaChangeTest < IdentityCache::TestCase
83
83
  end
84
84
 
85
85
  def test_embed_existing_cache_has_many
86
+ PolymorphicRecord.include(IdentityCache)
86
87
  Item.cache_has_many :polymorphic_records, :inverse_name => :owner, :embed => :ids
87
88
  read_new_schema
88
89
 
@@ -96,6 +97,7 @@ class SchemaChangeTest < IdentityCache::TestCase
96
97
  end
97
98
 
98
99
  def test_add_non_embedded_cache_has_many
100
+ PolymorphicRecord.include(IdentityCache)
99
101
  record = Item.fetch(@record.id)
100
102
 
101
103
  Item.cache_has_many :polymorphic_records, :inverse_name => :owner, :embed => :ids
@@ -59,7 +59,7 @@ class IdentityCache::TestCase < Minitest::Test
59
59
  end
60
60
 
61
61
  def assert_not_nil(*args)
62
- assert *args
62
+ assert(*args)
63
63
  end
64
64
 
65
65
  def assert_queries(num = 1)
@@ -67,7 +67,7 @@ class IdentityCache::TestCase < Minitest::Test
67
67
  subscriber = ActiveSupport::Notifications.subscribe('sql.active_record', counter)
68
68
  exception = false
69
69
  yield
70
- rescue => e
70
+ rescue
71
71
  exception = true
72
72
  raise
73
73
  ensure
@@ -80,7 +80,7 @@ class IdentityCache::TestCase < Minitest::Test
80
80
  subscriber = ActiveSupport::Notifications.subscribe(/cache_.*\.active_support/, counter)
81
81
  exception = false
82
82
  yield
83
- rescue => e
83
+ rescue
84
84
  exception = true
85
85
  raise
86
86
  ensure
@@ -101,7 +101,7 @@ end
101
101
 
102
102
  class SQLCounter
103
103
  cattr_accessor :ignored_sql
104
- self.ignored_sql = [/^PRAGMA (?!(table_info))/, /^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/, /^SELECT @@ROWCOUNT/, /^SAVEPOINT/, /^ROLLBACK TO SAVEPOINT/, /^RELEASE SAVEPOINT/, /^SHOW max_identifier_length/, /^BEGIN/, /^COMMIT/]
104
+ self.ignored_sql = [/^PRAGMA (?!(table_info))/, /^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/, /^SELECT @@ROWCOUNT/, /^SAVEPOINT/, /^ROLLBACK TO SAVEPOINT/, /^RELEASE SAVEPOINT/, /^SHOW max_identifier_length/, /^BEGIN/, /^COMMIT/, /^SHOW /]
105
105
 
106
106
  # FIXME: this needs to be refactored so specific database can add their own
107
107
  # ignored SQL. This ignored SQL is for Oracle.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: identity_cache
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.5
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Camilo Lopez
@@ -14,7 +14,7 @@ authors:
14
14
  autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
- date: 2015-05-29 00:00:00.000000000 Z
17
+ date: 2016-01-20 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: '3.2'
39
+ version: 4.0.4
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: '3.2'
46
+ version: 4.0.4
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: memcached
49
49
  requirement: !ruby/object:Gem::Requirement
@@ -197,7 +197,6 @@ files:
197
197
  - CHANGELOG.md
198
198
  - CONTRIBUTING.md
199
199
  - Gemfile
200
- - Gemfile.rails32
201
200
  - Gemfile.rails40
202
201
  - Gemfile.rails41
203
202
  - Gemfile.rails42
@@ -230,9 +229,9 @@ files:
230
229
  - test/denormalized_has_many_test.rb
231
230
  - test/denormalized_has_one_test.rb
232
231
  - test/fetch_multi_test.rb
233
- - test/fetch_multi_with_batched_associations_test.rb
234
232
  - test/fetch_test.rb
235
- - test/fixtures/serialized_record
233
+ - test/fixtures/serialized_record.mysql2
234
+ - test/fixtures/serialized_record.postgresql
236
235
  - test/helpers/active_record_objects.rb
237
236
  - test/helpers/database_connection.rb
238
237
  - test/helpers/serialization_format.rb
@@ -243,6 +242,7 @@ files:
243
242
  - test/normalized_belongs_to_test.rb
244
243
  - test/normalized_has_many_test.rb
245
244
  - test/normalized_has_one_test.rb
245
+ - test/prefetch_normalized_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.2.0
272
272
  signing_key:
273
273
  specification_version: 4
274
274
  summary: IdentityCache lets you specify how you want to cache your model objects,
@@ -284,9 +284,9 @@ test_files:
284
284
  - test/denormalized_has_many_test.rb
285
285
  - test/denormalized_has_one_test.rb
286
286
  - test/fetch_multi_test.rb
287
- - test/fetch_multi_with_batched_associations_test.rb
288
287
  - test/fetch_test.rb
289
- - test/fixtures/serialized_record
288
+ - test/fixtures/serialized_record.mysql2
289
+ - test/fixtures/serialized_record.postgresql
290
290
  - test/helpers/active_record_objects.rb
291
291
  - test/helpers/database_connection.rb
292
292
  - test/helpers/serialization_format.rb
@@ -297,6 +297,7 @@ test_files:
297
297
  - test/normalized_belongs_to_test.rb
298
298
  - test/normalized_has_many_test.rb
299
299
  - test/normalized_has_one_test.rb
300
+ - test/prefetch_normalized_associations_test.rb
300
301
  - test/readonly_test.rb
301
302
  - test/recursive_denormalized_has_many_test.rb
302
303
  - test/save_test.rb
@@ -1,5 +0,0 @@
1
- source 'https://rubygems.org'
2
- gemspec
3
-
4
- gem 'activerecord', '~> 3.2.16'
5
- gem 'activesupport', '~> 3.2.16'