identity_cache 0.0.3 → 0.0.4
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.
- checksums.yaml +13 -5
- data/.travis.yml +4 -2
- data/CHANGELOG +5 -0
- data/README.md +9 -1
- data/Rakefile +5 -1
- data/identity_cache.gemspec +14 -6
- data/lib/identity_cache.rb +17 -34
- data/lib/identity_cache/cache_hash.rb +36 -0
- data/lib/identity_cache/cache_key_generation.rb +34 -6
- data/lib/identity_cache/configuration_dsl.rb +4 -6
- data/lib/identity_cache/memoized_cache_proxy.rb +19 -17
- data/lib/identity_cache/query_api.rb +105 -11
- data/lib/identity_cache/version.rb +2 -1
- data/performance/cache_runner.rb +44 -15
- data/performance/cpu.rb +3 -0
- data/performance/externals.rb +4 -0
- data/performance/profile.rb +4 -0
- data/test/attribute_cache_test.rb +5 -3
- data/test/cache_hash_test.rb +16 -0
- data/test/fetch_multi_test.rb +32 -13
- data/test/fetch_multi_with_batched_associations_test.rb +6 -4
- data/test/fetch_test.rb +28 -7
- data/test/fixtures/serialized_record +0 -0
- data/test/helpers/active_record_objects.rb +25 -1
- data/test/helpers/database_connection.rb +7 -6
- data/test/helpers/serialization_format.rb +38 -0
- data/test/helpers/update_serialization_format.rb +28 -0
- data/test/index_cache_test.rb +5 -3
- data/test/normalized_has_many_test.rb +10 -0
- data/test/save_test.rb +16 -14
- data/test/schema_change_test.rb +16 -0
- data/test/serialization_format_change_test.rb +16 -0
- data/test/test_helper.rb +1 -1
- metadata +51 -40
@@ -1,15 +1,17 @@
|
|
1
1
|
require "test_helper"
|
2
2
|
|
3
3
|
class FetchMultiTest < IdentityCache::TestCase
|
4
|
+
NAMESPACE = IdentityCache::CacheKeyGeneration::DEFAULT_NAMESPACE unless const_defined?(:NAMESPACE)
|
5
|
+
|
4
6
|
def setup
|
5
7
|
super
|
6
8
|
@bob = Record.create!(:title => 'bob')
|
7
9
|
@joe = Record.create!(:title => 'joe')
|
8
10
|
@fred = Record.create!(:title => 'fred')
|
9
|
-
@bob_blob_key = "
|
10
|
-
@joe_blob_key = "
|
11
|
-
@fred_blob_key = "
|
12
|
-
@tenth_blob_key = "
|
11
|
+
@bob_blob_key = "#{NAMESPACE}blob:Record:#{cache_hash("created_at:datetime,id:integer,record_id:integer,title:string,updated_at:datetime")}:1"
|
12
|
+
@joe_blob_key = "#{NAMESPACE}blob:Record:#{cache_hash("created_at:datetime,id:integer,record_id:integer,title:string,updated_at:datetime")}:2"
|
13
|
+
@fred_blob_key = "#{NAMESPACE}blob:Record:#{cache_hash("created_at:datetime,id:integer,record_id:integer,title:string,updated_at:datetime")}:3"
|
14
|
+
@tenth_blob_key = "#{NAMESPACE}blob:Record:#{cache_hash("created_at:datetime,id:integer,record_id:integer,title:string,updated_at:datetime")}:10"
|
13
15
|
end
|
14
16
|
|
15
17
|
def test_fetch_multi_includes_cached_associations_in_the_database_find
|
data/test/fetch_test.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require "test_helper"
|
2
2
|
|
3
3
|
class FetchTest < IdentityCache::TestCase
|
4
|
+
NAMESPACE = IdentityCache::CacheKeyGeneration::DEFAULT_NAMESPACE
|
5
|
+
|
4
6
|
def setup
|
5
7
|
super
|
6
8
|
Record.cache_index :title, :unique => true
|
@@ -9,19 +11,30 @@ class FetchTest < IdentityCache::TestCase
|
|
9
11
|
@record = Record.new
|
10
12
|
@record.id = 1
|
11
13
|
@record.title = 'bob'
|
12
|
-
@
|
13
|
-
@
|
14
|
+
@cached_value = {:class => @record.class}
|
15
|
+
@record.encode_with(@cached_value)
|
16
|
+
@blob_key = "#{NAMESPACE}blob:Record:#{cache_hash("created_at:datetime,id:integer,record_id:integer,title:string,updated_at:datetime")}:1"
|
17
|
+
@index_key = "#{NAMESPACE}index:Record:title:#{cache_hash('bob')}"
|
14
18
|
end
|
15
19
|
|
16
|
-
|
17
20
|
def test_fetch_cache_hit
|
18
|
-
IdentityCache.cache.expects(:read).with(@blob_key).returns(@
|
21
|
+
IdentityCache.cache.expects(:read).with(@blob_key).returns(@cached_value)
|
22
|
+
|
23
|
+
assert_equal @record, Record.fetch(1)
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_fetch_hit_cache_namespace
|
27
|
+
Record.send(:include, SwitchNamespace)
|
28
|
+
Record.namespace = 'test_namespace'
|
29
|
+
|
30
|
+
new_blob_key = "test_namespace:#{@blob_key}"
|
31
|
+
IdentityCache.cache.expects(:read).with(new_blob_key).returns(@cached_value)
|
19
32
|
|
20
33
|
assert_equal @record, Record.fetch(1)
|
21
34
|
end
|
22
35
|
|
23
36
|
def test_exists_with_identity_cache_when_cache_hit
|
24
|
-
IdentityCache.cache.expects(:read).with(@blob_key).returns(@
|
37
|
+
IdentityCache.cache.expects(:read).with(@blob_key).returns(@cached_value)
|
25
38
|
|
26
39
|
assert Record.exists_with_identity_cache?(1)
|
27
40
|
end
|
@@ -44,7 +57,7 @@ class FetchTest < IdentityCache::TestCase
|
|
44
57
|
Record.expects(:find_by_id).with(1, :include => []).returns(@record)
|
45
58
|
|
46
59
|
IdentityCache.cache.expects(:read).with(@blob_key).returns(nil)
|
47
|
-
IdentityCache.cache.expects(:write).with(@blob_key, @
|
60
|
+
IdentityCache.cache.expects(:write).with(@blob_key, @cached_value)
|
48
61
|
|
49
62
|
assert_equal @record, Record.fetch(1)
|
50
63
|
end
|
@@ -84,7 +97,15 @@ class FetchTest < IdentityCache::TestCase
|
|
84
97
|
IdentityCache.cache.expects(:write).with(@index_key, 1)
|
85
98
|
|
86
99
|
# got id, do memcache lookup on that, hit -> done
|
87
|
-
IdentityCache.cache.expects(:read).with(@blob_key).returns(@
|
100
|
+
IdentityCache.cache.expects(:read).with(@blob_key).returns(@cached_value)
|
101
|
+
|
102
|
+
assert_equal @record, Record.fetch_by_title('bob')
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_fetch_by_title_cache_namespace
|
106
|
+
Record.send(:include, SwitchNamespace)
|
107
|
+
IdentityCache.cache.expects(:read).with("ns:#{@index_key}").returns(1)
|
108
|
+
IdentityCache.cache.expects(:read).with("ns:#{@blob_key}").returns(@cached_value)
|
88
109
|
|
89
110
|
assert_equal @record, Record.fetch_by_title('bob')
|
90
111
|
end
|
Binary file
|
@@ -1,4 +1,22 @@
|
|
1
|
+
module SwitchNamespace
|
2
|
+
|
3
|
+
module ClassMethods
|
4
|
+
def rails_cache_key_namespace
|
5
|
+
"#{self.namespace}:#{super}"
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.included(base)
|
10
|
+
base.extend ClassMethods
|
11
|
+
base.class_eval do
|
12
|
+
class_attribute :namespace
|
13
|
+
self.namespace = 'ns'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
1
18
|
module ActiveRecordObjects
|
19
|
+
|
2
20
|
def setup_models(base = ActiveRecord::Base)
|
3
21
|
Object.send :const_set, 'DeeplyAssociatedRecord', Class.new(base).tap {|klass|
|
4
22
|
klass.send :include, IdentityCache
|
@@ -11,6 +29,11 @@ module ActiveRecordObjects
|
|
11
29
|
klass.has_many :deeply_associated_records, :order => "name DESC"
|
12
30
|
}
|
13
31
|
|
32
|
+
Object.send :const_set, 'NormalizedAssociatedRecord', Class.new(base).tap {|klass|
|
33
|
+
klass.send :include, IdentityCache
|
34
|
+
klass.belongs_to :record
|
35
|
+
}
|
36
|
+
|
14
37
|
Object.send :const_set, 'NotCachedRecord', Class.new(base).tap {|klass|
|
15
38
|
klass.belongs_to :record, :touch => true
|
16
39
|
}
|
@@ -23,6 +46,7 @@ module ActiveRecordObjects
|
|
23
46
|
klass.send :include, IdentityCache
|
24
47
|
klass.belongs_to :record
|
25
48
|
klass.has_many :associated_records, :order => "id DESC"
|
49
|
+
klass.has_many :normalized_associated_records, :order => "id DESC"
|
26
50
|
klass.has_many :not_cached_records, :order => "id DESC"
|
27
51
|
klass.has_many :polymorphic_records, :as => 'owner'
|
28
52
|
klass.has_one :polymorphic_record, :as => 'owner'
|
@@ -35,9 +59,9 @@ module ActiveRecordObjects
|
|
35
59
|
ActiveSupport::Dependencies.clear
|
36
60
|
Object.send :remove_const, 'DeeplyAssociatedRecord'
|
37
61
|
Object.send :remove_const, 'PolymorphicRecord'
|
62
|
+
Object.send :remove_const, 'NormalizedAssociatedRecord'
|
38
63
|
Object.send :remove_const, 'AssociatedRecord'
|
39
64
|
Object.send :remove_const, 'NotCachedRecord'
|
40
65
|
Object.send :remove_const, 'Record'
|
41
66
|
end
|
42
67
|
end
|
43
|
-
|
@@ -26,12 +26,13 @@ module DatabaseConnection
|
|
26
26
|
end
|
27
27
|
|
28
28
|
TABLES = {
|
29
|
-
:polymorphic_records
|
30
|
-
:deeply_associated_records
|
31
|
-
:associated_records
|
32
|
-
:
|
33
|
-
:
|
34
|
-
:
|
29
|
+
:polymorphic_records => [[:string, :owner_type], [:integer, :owner_id], [:timestamps]],
|
30
|
+
:deeply_associated_records => [[:string, :name], [:integer, :associated_record_id]],
|
31
|
+
:associated_records => [[:string, :name], [:integer, :record_id]],
|
32
|
+
:normalized_associated_records => [[:string, :name], [:integer, :record_id]],
|
33
|
+
:not_cached_records => [[:string, :name], [:integer, :record_id]],
|
34
|
+
:records => [[:integer, :record_id], [:string, :title], [:timestamps]],
|
35
|
+
:records2 => [[:integer, :record_id], [:string, :title], [:timestamps]]
|
35
36
|
}
|
36
37
|
|
37
38
|
DATABASE_CONFIG = {
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module SerializationFormat
|
2
|
+
def serialized_record
|
3
|
+
AssociatedRecord.cache_has_many :deeply_associated_records, :embed => true
|
4
|
+
AssociatedRecord.cache_belongs_to :record, :embed => false
|
5
|
+
Record.cache_has_many :associated_records, :embed => true
|
6
|
+
Record.cache_has_one :associated
|
7
|
+
|
8
|
+
record = Record.new(:title => 'foo')
|
9
|
+
record.associated_records << AssociatedRecord.new(:name => 'bar')
|
10
|
+
record.associated_records << AssociatedRecord.new(:name => 'baz')
|
11
|
+
record.associated = AssociatedRecord.new(:name => 'bork')
|
12
|
+
record.not_cached_records << NotCachedRecord.new(:name => 'NoCache')
|
13
|
+
record.associated.deeply_associated_records << DeeplyAssociatedRecord.new(:name => "corge")
|
14
|
+
record.associated.deeply_associated_records << DeeplyAssociatedRecord.new(:name => "qux")
|
15
|
+
record.created_at = DateTime.new
|
16
|
+
record.save
|
17
|
+
Record.update_all("updated_at='#{record.created_at}'", "id='#{record.id}'")
|
18
|
+
record.reload
|
19
|
+
Record.fetch(record.id)
|
20
|
+
IdentityCache.fetch(record.primary_cache_index_key)
|
21
|
+
end
|
22
|
+
|
23
|
+
def serialized_record_file
|
24
|
+
File.expand_path("../../fixtures/serialized_record", __FILE__)
|
25
|
+
end
|
26
|
+
|
27
|
+
def serialize(record, anIO = nil)
|
28
|
+
hash = {
|
29
|
+
:version => IdentityCache::CACHE_VERSION,
|
30
|
+
:record => record
|
31
|
+
}
|
32
|
+
if anIO
|
33
|
+
Marshal.dump(hash, anIO)
|
34
|
+
else
|
35
|
+
Marshal.dump(hash)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path("../../../lib", __FILE__)
|
2
|
+
|
3
|
+
require 'active_record'
|
4
|
+
require_relative 'serialization_format'
|
5
|
+
require_relative 'cache'
|
6
|
+
require_relative 'database_connection'
|
7
|
+
require_relative 'active_record_objects'
|
8
|
+
require 'identity_cache'
|
9
|
+
|
10
|
+
if ENV['BOXEN_HOME'].present?
|
11
|
+
$memcached_port = 21211
|
12
|
+
$mysql_port = 13306
|
13
|
+
else
|
14
|
+
$memcached_port = 11211
|
15
|
+
$mysql_port = 3306
|
16
|
+
end
|
17
|
+
|
18
|
+
include SerializationFormat
|
19
|
+
include ActiveRecordObjects
|
20
|
+
|
21
|
+
DatabaseConnection.setup
|
22
|
+
DatabaseConnection.drop_tables
|
23
|
+
DatabaseConnection.create_tables
|
24
|
+
setup_models
|
25
|
+
File.open(serialized_record_file, 'w') {|file| serialize(serialized_record, file) }
|
26
|
+
puts "Serialized record to #{serialized_record_file}"
|
27
|
+
IdentityCache.cache.clear
|
28
|
+
teardown_models
|
data/test/index_cache_test.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
require "test_helper"
|
2
2
|
|
3
3
|
class ExpirationTest < IdentityCache::TestCase
|
4
|
+
NAMESPACE = IdentityCache::CacheKeyGeneration::DEFAULT_NAMESPACE
|
5
|
+
|
4
6
|
def setup
|
5
7
|
super
|
6
8
|
@record = Record.new
|
7
9
|
@record.id = 1
|
8
10
|
@record.title = 'bob'
|
9
|
-
@cache_key = "
|
11
|
+
@cache_key = "#{NAMESPACE}index:Record:title:#{cache_hash(@record.title)}"
|
10
12
|
end
|
11
13
|
|
12
14
|
def test_unique_index_caches_nil
|
@@ -35,7 +37,7 @@ class ExpirationTest < IdentityCache::TestCase
|
|
35
37
|
IdentityCache.cache.write(@cache_key, @record.id)
|
36
38
|
|
37
39
|
@record.title = 'robert'
|
38
|
-
new_cache_key = "
|
40
|
+
new_cache_key = "#{NAMESPACE}index:Record:title:#{cache_hash(@record.title)}"
|
39
41
|
IdentityCache.cache.write(new_cache_key, IdentityCache::CACHED_NIL)
|
40
42
|
@record.save!
|
41
43
|
assert_equal nil, IdentityCache.cache.read(@cache_key)
|
@@ -78,7 +80,7 @@ class ExpirationTest < IdentityCache::TestCase
|
|
78
80
|
IdentityCache.cache.write(@cache_key, [@record.id])
|
79
81
|
|
80
82
|
@record.title = 'robert'
|
81
|
-
new_cache_key = "
|
83
|
+
new_cache_key = "#{NAMESPACE}index:Record:title:#{cache_hash(@record.title)}"
|
82
84
|
IdentityCache.cache.write(new_cache_key, [])
|
83
85
|
@record.save!
|
84
86
|
assert_equal nil, IdentityCache.cache.read(@cache_key)
|
@@ -48,6 +48,16 @@ class NormalizedHasManyTest < IdentityCache::TestCase
|
|
48
48
|
assert_equal [@baz, @bar], @record.fetch_associated_records
|
49
49
|
end
|
50
50
|
|
51
|
+
def test_fetching_the_association_from_a_record_on_a_cache_hit_should_not_issue_any_queries
|
52
|
+
# Populate the cache
|
53
|
+
@record = Record.fetch(@record.id)
|
54
|
+
@record.fetch_associated_records
|
55
|
+
assert_queries(0) do
|
56
|
+
@record = Record.fetch(@record.id)
|
57
|
+
assert_equal [@baz, @bar], @record.fetch_associated_records
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
51
61
|
def test_fetching_the_association_from_a_identity_cached_record_should_not_re_fetch_the_association_ids
|
52
62
|
@record = Record.fetch(@record.id)
|
53
63
|
@record.expects(:associated_record_ids).never
|
data/test/save_test.rb
CHANGED
@@ -1,34 +1,36 @@
|
|
1
1
|
require "test_helper"
|
2
2
|
|
3
3
|
class SaveTest < IdentityCache::TestCase
|
4
|
+
NAMESPACE = IdentityCache::CacheKeyGeneration::DEFAULT_NAMESPACE
|
5
|
+
|
4
6
|
def setup
|
5
7
|
super
|
6
8
|
Record.cache_index :title, :unique => true
|
7
9
|
Record.cache_index :id, :title, :unique => true
|
8
10
|
|
9
11
|
@record = Record.create(:title => 'bob')
|
10
|
-
@blob_key = "
|
12
|
+
@blob_key = "#{NAMESPACE}blob:Record:#{cache_hash("created_at:datetime,id:integer,record_id:integer,title:string,updated_at:datetime")}:1"
|
11
13
|
end
|
12
14
|
|
13
15
|
def test_create
|
14
16
|
@record = Record.new
|
15
17
|
@record.title = 'bob'
|
16
18
|
|
17
|
-
IdentityCache.cache.expects(:delete).with("
|
18
|
-
IdentityCache.cache.expects(:delete).with("
|
19
|
-
IdentityCache.cache.expects(:delete).with("
|
19
|
+
IdentityCache.cache.expects(:delete).with("#{NAMESPACE}index:Record:id/title:#{cache_hash('2/bob')}")
|
20
|
+
IdentityCache.cache.expects(:delete).with("#{NAMESPACE}index:Record:title:#{cache_hash('bob')}")
|
21
|
+
IdentityCache.cache.expects(:delete).with("#{NAMESPACE}blob:Record:#{cache_hash("created_at:datetime,id:integer,record_id:integer,title:string,updated_at:datetime")}:2").once
|
20
22
|
@record.save
|
21
23
|
end
|
22
24
|
|
23
25
|
def test_update
|
24
26
|
# Regular flow, write index id, write index id/tile, delete data blob since Record has changed
|
25
|
-
IdentityCache.cache.expects(:delete).with("
|
26
|
-
IdentityCache.cache.expects(:delete).with("
|
27
|
+
IdentityCache.cache.expects(:delete).with("#{NAMESPACE}index:Record:id/title:#{cache_hash('1/fred')}")
|
28
|
+
IdentityCache.cache.expects(:delete).with("#{NAMESPACE}index:Record:title:#{cache_hash('fred')}")
|
27
29
|
IdentityCache.cache.expects(:delete).with(@blob_key)
|
28
30
|
|
29
31
|
# Delete index id, delete index id/title
|
30
|
-
IdentityCache.cache.expects(:delete).with("
|
31
|
-
IdentityCache.cache.expects(:delete).with("
|
32
|
+
IdentityCache.cache.expects(:delete).with("#{NAMESPACE}index:Record:id/title:#{cache_hash('1/bob')}")
|
33
|
+
IdentityCache.cache.expects(:delete).with("#{NAMESPACE}index:Record:title:#{cache_hash('bob')}")
|
32
34
|
|
33
35
|
@record.title = 'fred'
|
34
36
|
@record.save
|
@@ -36,8 +38,8 @@ class SaveTest < IdentityCache::TestCase
|
|
36
38
|
|
37
39
|
def test_destroy
|
38
40
|
# Regular flow: delete data blob, delete index id, delete index id/tile
|
39
|
-
IdentityCache.cache.expects(:delete).with("
|
40
|
-
IdentityCache.cache.expects(:delete).with("
|
41
|
+
IdentityCache.cache.expects(:delete).with("#{NAMESPACE}index:Record:id/title:#{cache_hash('1/bob')}")
|
42
|
+
IdentityCache.cache.expects(:delete).with("#{NAMESPACE}index:Record:title:#{cache_hash('bob')}")
|
41
43
|
IdentityCache.cache.expects(:delete).with(@blob_key)
|
42
44
|
|
43
45
|
@record.destroy
|
@@ -45,8 +47,8 @@ class SaveTest < IdentityCache::TestCase
|
|
45
47
|
|
46
48
|
def test_destroy_with_changed_attributes
|
47
49
|
# Make sure to delete the old cache index key, since the new title never ended up in an index
|
48
|
-
IdentityCache.cache.expects(:delete).with("
|
49
|
-
IdentityCache.cache.expects(:delete).with("
|
50
|
+
IdentityCache.cache.expects(:delete).with("#{NAMESPACE}index:Record:id/title:#{cache_hash('1/bob')}")
|
51
|
+
IdentityCache.cache.expects(:delete).with("#{NAMESPACE}index:Record:title:#{cache_hash('bob')}")
|
50
52
|
IdentityCache.cache.expects(:delete).with(@blob_key)
|
51
53
|
|
52
54
|
@record.title = 'fred'
|
@@ -55,8 +57,8 @@ class SaveTest < IdentityCache::TestCase
|
|
55
57
|
|
56
58
|
def test_touch_will_expire_the_caches
|
57
59
|
# Regular flow: delete data blob, delete index id, delete index id/tile
|
58
|
-
IdentityCache.cache.expects(:delete).with("
|
59
|
-
IdentityCache.cache.expects(:delete).with("
|
60
|
+
IdentityCache.cache.expects(:delete).with("#{NAMESPACE}index:Record:id/title:#{cache_hash('1/bob')}")
|
61
|
+
IdentityCache.cache.expects(:delete).with("#{NAMESPACE}index:Record:title:#{cache_hash('bob')}")
|
60
62
|
IdentityCache.cache.expects(:delete).with(@blob_key)
|
61
63
|
|
62
64
|
@record.touch
|
data/test/schema_change_test.rb
CHANGED
@@ -34,6 +34,12 @@ class SchemaChangeTest < IdentityCache::TestCase
|
|
34
34
|
@record.reload
|
35
35
|
end
|
36
36
|
|
37
|
+
def teardown
|
38
|
+
active_records = [AssociatedRecord, DeeplyAssociatedRecord]
|
39
|
+
super
|
40
|
+
active_records.each {|ar| ar.reset_column_information }
|
41
|
+
end
|
42
|
+
|
37
43
|
# This helper simulates the models being reloaded
|
38
44
|
def read_new_schema
|
39
45
|
AssociatedRecord.reset_column_information
|
@@ -65,4 +71,14 @@ class SchemaChangeTest < IdentityCache::TestCase
|
|
65
71
|
Record.expects(:resolve_cache_miss).returns(@record)
|
66
72
|
record = Record.fetch(@record.id)
|
67
73
|
end
|
74
|
+
|
75
|
+
def test_schema_changes_on_new_cached_child_association
|
76
|
+
record = Record.fetch(@record.id)
|
77
|
+
|
78
|
+
Record.cache_has_many :polymorphic_records, :inverse_name => :owner, :embed => true
|
79
|
+
read_new_schema
|
80
|
+
|
81
|
+
Record.expects(:resolve_cache_miss).returns(@record)
|
82
|
+
record = Record.fetch(@record.id)
|
83
|
+
end
|
68
84
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
require "helpers/serialization_format"
|
3
|
+
|
4
|
+
class SerializationFormatChangeTest < IdentityCache::TestCase
|
5
|
+
include SerializationFormat
|
6
|
+
|
7
|
+
MESSAGE = "serialization format changed => increment IdentityCache.CACHE_VERSION and run rake update_serialization_format"
|
8
|
+
|
9
|
+
def test_serialization_format_has_not_changed
|
10
|
+
serialization = Marshal.load(serialize(serialized_record))
|
11
|
+
preserialization = Marshal.load(File.binread(serialized_record_file))
|
12
|
+
assert_equal(preserialization, serialization, MESSAGE)
|
13
|
+
rescue SystemCallError
|
14
|
+
assert(false, MESSAGE)
|
15
|
+
end
|
16
|
+
end
|
data/test/test_helper.rb
CHANGED
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.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Camilo Lopez
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2013-
|
15
|
+
date: 2013-09-16 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: ar_transaction_changes
|
@@ -32,70 +32,56 @@ dependencies:
|
|
32
32
|
name: activerecord
|
33
33
|
requirement: !ruby/object:Gem::Requirement
|
34
34
|
requirements:
|
35
|
-
- -
|
35
|
+
- - ~>
|
36
36
|
- !ruby/object:Gem::Version
|
37
|
-
version: 3.2.
|
37
|
+
version: 3.2.12
|
38
38
|
type: :runtime
|
39
39
|
prerelease: false
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
41
41
|
requirements:
|
42
|
-
- -
|
42
|
+
- - ~>
|
43
43
|
- !ruby/object:Gem::Version
|
44
|
-
version: 3.2.
|
44
|
+
version: 3.2.12
|
45
45
|
- !ruby/object:Gem::Dependency
|
46
46
|
name: activesupport
|
47
47
|
requirement: !ruby/object:Gem::Requirement
|
48
48
|
requirements:
|
49
|
-
- -
|
49
|
+
- - ~>
|
50
50
|
- !ruby/object:Gem::Version
|
51
|
-
version: 3.2.
|
51
|
+
version: 3.2.12
|
52
52
|
type: :runtime
|
53
53
|
prerelease: false
|
54
54
|
version_requirements: !ruby/object:Gem::Requirement
|
55
55
|
requirements:
|
56
|
-
- -
|
56
|
+
- - ~>
|
57
57
|
- !ruby/object:Gem::Version
|
58
|
-
version: 3.2.
|
59
|
-
- !ruby/object:Gem::Dependency
|
60
|
-
name: cityhash
|
61
|
-
requirement: !ruby/object:Gem::Requirement
|
62
|
-
requirements:
|
63
|
-
- - '='
|
64
|
-
- !ruby/object:Gem::Version
|
65
|
-
version: 0.6.0
|
66
|
-
type: :runtime
|
67
|
-
prerelease: false
|
68
|
-
version_requirements: !ruby/object:Gem::Requirement
|
69
|
-
requirements:
|
70
|
-
- - '='
|
71
|
-
- !ruby/object:Gem::Version
|
72
|
-
version: 0.6.0
|
58
|
+
version: 3.2.12
|
73
59
|
- !ruby/object:Gem::Dependency
|
74
60
|
name: memcache-client
|
75
61
|
requirement: !ruby/object:Gem::Requirement
|
76
62
|
requirements:
|
77
|
-
- - '>='
|
63
|
+
- - ! '>='
|
78
64
|
- !ruby/object:Gem::Version
|
79
65
|
version: '0'
|
80
66
|
type: :development
|
81
67
|
prerelease: false
|
82
68
|
version_requirements: !ruby/object:Gem::Requirement
|
83
69
|
requirements:
|
84
|
-
- - '>='
|
70
|
+
- - ! '>='
|
85
71
|
- !ruby/object:Gem::Version
|
86
72
|
version: '0'
|
87
73
|
- !ruby/object:Gem::Dependency
|
88
74
|
name: rake
|
89
75
|
requirement: !ruby/object:Gem::Requirement
|
90
76
|
requirements:
|
91
|
-
- - '>='
|
77
|
+
- - ! '>='
|
92
78
|
- !ruby/object:Gem::Version
|
93
79
|
version: '0'
|
94
80
|
type: :development
|
95
81
|
prerelease: false
|
96
82
|
version_requirements: !ruby/object:Gem::Requirement
|
97
83
|
requirements:
|
98
|
-
- - '>='
|
84
|
+
- - ! '>='
|
99
85
|
- !ruby/object:Gem::Version
|
100
86
|
version: '0'
|
101
87
|
- !ruby/object:Gem::Dependency
|
@@ -113,45 +99,59 @@ dependencies:
|
|
113
99
|
- !ruby/object:Gem::Version
|
114
100
|
version: 0.14.0
|
115
101
|
- !ruby/object:Gem::Dependency
|
116
|
-
name:
|
102
|
+
name: debugger
|
117
103
|
requirement: !ruby/object:Gem::Requirement
|
118
104
|
requirements:
|
119
|
-
- - '>='
|
105
|
+
- - ! '>='
|
120
106
|
- !ruby/object:Gem::Version
|
121
107
|
version: '0'
|
122
108
|
type: :development
|
123
109
|
prerelease: false
|
124
110
|
version_requirements: !ruby/object:Gem::Requirement
|
125
111
|
requirements:
|
126
|
-
- - '>='
|
112
|
+
- - ! '>='
|
127
113
|
- !ruby/object:Gem::Version
|
128
114
|
version: '0'
|
129
115
|
- !ruby/object:Gem::Dependency
|
130
|
-
name:
|
116
|
+
name: ruby-prof
|
131
117
|
requirement: !ruby/object:Gem::Requirement
|
132
118
|
requirements:
|
133
|
-
- - '>='
|
119
|
+
- - ! '>='
|
134
120
|
- !ruby/object:Gem::Version
|
135
121
|
version: '0'
|
136
122
|
type: :development
|
137
123
|
prerelease: false
|
138
124
|
version_requirements: !ruby/object:Gem::Requirement
|
139
125
|
requirements:
|
140
|
-
- - '>='
|
126
|
+
- - ! '>='
|
141
127
|
- !ruby/object:Gem::Version
|
142
128
|
version: '0'
|
143
129
|
- !ruby/object:Gem::Dependency
|
144
|
-
name:
|
130
|
+
name: cityhash
|
131
|
+
requirement: !ruby/object:Gem::Requirement
|
132
|
+
requirements:
|
133
|
+
- - '='
|
134
|
+
- !ruby/object:Gem::Version
|
135
|
+
version: 0.6.0
|
136
|
+
type: :development
|
137
|
+
prerelease: false
|
138
|
+
version_requirements: !ruby/object:Gem::Requirement
|
139
|
+
requirements:
|
140
|
+
- - '='
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: 0.6.0
|
143
|
+
- !ruby/object:Gem::Dependency
|
144
|
+
name: mysql2
|
145
145
|
requirement: !ruby/object:Gem::Requirement
|
146
146
|
requirements:
|
147
|
-
- - '>='
|
147
|
+
- - ! '>='
|
148
148
|
- !ruby/object:Gem::Version
|
149
149
|
version: '0'
|
150
150
|
type: :development
|
151
151
|
prerelease: false
|
152
152
|
version_requirements: !ruby/object:Gem::Requirement
|
153
153
|
requirements:
|
154
|
-
- - '>='
|
154
|
+
- - ! '>='
|
155
155
|
- !ruby/object:Gem::Version
|
156
156
|
version: '0'
|
157
157
|
description: Opt in read through ActiveRecord caching.
|
@@ -171,6 +171,7 @@ files:
|
|
171
171
|
- identity_cache.gemspec
|
172
172
|
- lib/identity_cache.rb
|
173
173
|
- lib/identity_cache/belongs_to_caching.rb
|
174
|
+
- lib/identity_cache/cache_hash.rb
|
174
175
|
- lib/identity_cache/cache_key_generation.rb
|
175
176
|
- lib/identity_cache/configuration_dsl.rb
|
176
177
|
- lib/identity_cache/memoized_cache_proxy.rb
|
@@ -183,14 +184,18 @@ files:
|
|
183
184
|
- performance/profile.rb
|
184
185
|
- test/attribute_cache_test.rb
|
185
186
|
- test/cache_fetch_includes_test.rb
|
187
|
+
- test/cache_hash_test.rb
|
186
188
|
- test/denormalized_has_many_test.rb
|
187
189
|
- test/denormalized_has_one_test.rb
|
188
190
|
- test/fetch_multi_test.rb
|
189
191
|
- test/fetch_multi_with_batched_associations_test.rb
|
190
192
|
- test/fetch_test.rb
|
193
|
+
- test/fixtures/serialized_record
|
191
194
|
- test/helpers/active_record_objects.rb
|
192
195
|
- test/helpers/cache.rb
|
193
196
|
- test/helpers/database_connection.rb
|
197
|
+
- test/helpers/serialization_format.rb
|
198
|
+
- test/helpers/update_serialization_format.rb
|
194
199
|
- test/identity_cache_test.rb
|
195
200
|
- test/index_cache_test.rb
|
196
201
|
- test/memoized_cache_proxy_test.rb
|
@@ -199,6 +204,7 @@ files:
|
|
199
204
|
- test/recursive_denormalized_has_many_test.rb
|
200
205
|
- test/save_test.rb
|
201
206
|
- test/schema_change_test.rb
|
207
|
+
- test/serialization_format_change_test.rb
|
202
208
|
- test/test_helper.rb
|
203
209
|
homepage: https://github.com/Shopify/identity_cache
|
204
210
|
licenses: []
|
@@ -209,17 +215,17 @@ require_paths:
|
|
209
215
|
- lib
|
210
216
|
required_ruby_version: !ruby/object:Gem::Requirement
|
211
217
|
requirements:
|
212
|
-
- - '>='
|
218
|
+
- - ! '>='
|
213
219
|
- !ruby/object:Gem::Version
|
214
220
|
version: '0'
|
215
221
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
216
222
|
requirements:
|
217
|
-
- - '>='
|
223
|
+
- - ! '>='
|
218
224
|
- !ruby/object:Gem::Version
|
219
225
|
version: '0'
|
220
226
|
requirements: []
|
221
227
|
rubyforge_project:
|
222
|
-
rubygems_version: 2.
|
228
|
+
rubygems_version: 2.1.0
|
223
229
|
signing_key:
|
224
230
|
specification_version: 4
|
225
231
|
summary: IdentityCache lets you specify how you want to cache your model objects,
|
@@ -229,14 +235,18 @@ summary: IdentityCache lets you specify how you want to cache your model objects
|
|
229
235
|
test_files:
|
230
236
|
- test/attribute_cache_test.rb
|
231
237
|
- test/cache_fetch_includes_test.rb
|
238
|
+
- test/cache_hash_test.rb
|
232
239
|
- test/denormalized_has_many_test.rb
|
233
240
|
- test/denormalized_has_one_test.rb
|
234
241
|
- test/fetch_multi_test.rb
|
235
242
|
- test/fetch_multi_with_batched_associations_test.rb
|
236
243
|
- test/fetch_test.rb
|
244
|
+
- test/fixtures/serialized_record
|
237
245
|
- test/helpers/active_record_objects.rb
|
238
246
|
- test/helpers/cache.rb
|
239
247
|
- test/helpers/database_connection.rb
|
248
|
+
- test/helpers/serialization_format.rb
|
249
|
+
- test/helpers/update_serialization_format.rb
|
240
250
|
- test/identity_cache_test.rb
|
241
251
|
- test/index_cache_test.rb
|
242
252
|
- test/memoized_cache_proxy_test.rb
|
@@ -245,4 +255,5 @@ test_files:
|
|
245
255
|
- test/recursive_denormalized_has_many_test.rb
|
246
256
|
- test/save_test.rb
|
247
257
|
- test/schema_change_test.rb
|
258
|
+
- test/serialization_format_change_test.rb
|
248
259
|
- test/test_helper.rb
|