second_level_cache 2.1.0.rc2 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +2 -2
- data/README.md +1 -1
- data/lib/second_level_cache/active_record.rb +1 -1
- data/lib/second_level_cache/active_record/has_one_association.rb +5 -1
- data/lib/second_level_cache/active_record/persistence.rb +2 -1
- data/lib/second_level_cache/active_record/preloader.rb +5 -7
- data/lib/second_level_cache/version.rb +1 -1
- data/second_level_cache.gemspec +1 -1
- data/test/active_record_test_case_helper.rb +120 -0
- data/test/{active_record/base_test.rb → base_test.rb} +2 -2
- data/test/{active_record/belongs_to_association_test.rb → belongs_to_association_test.rb} +3 -3
- data/test/{active_record/fetch_by_uniq_key_test.rb → fetch_by_uniq_key_test.rb} +9 -9
- data/test/{active_record/finder_methods_test.rb → finder_methods_test.rb} +4 -4
- data/test/{active_record/has_one_association_test.rb → has_one_association_test.rb} +3 -3
- data/test/{active_record/model → model}/account.rb +0 -0
- data/test/{active_record/model → model}/book.rb +0 -0
- data/test/{active_record/model → model}/image.rb +0 -0
- data/test/{active_record/model → model}/post.rb +0 -0
- data/test/{active_record/model → model}/topic.rb +0 -0
- data/test/{active_record/model → model}/user.rb +0 -0
- data/test/{active_record/persistence_test.rb → persistence_test.rb} +7 -2
- data/test/{active_record/polymorphic_association_test.rb → polymorphic_association_test.rb} +3 -4
- data/test/preloader_test.rb +55 -0
- data/test/record_marshal_test.rb +2 -2
- data/test/require_test.rb +2 -2
- data/test/{active_record/second_level_cache_test.rb → second_level_cache_test.rb} +2 -2
- data/test/test_helper.rb +29 -4
- metadata +63 -75
- data/test/active_record/preloader_test.rb +0 -28
- data/test/active_record/test_helper.rb +0 -55
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 06b57d2d883c83e10d5b5b927b1666e92a84c6b1
|
4
|
+
data.tar.gz: 80c99a97b2b2753f98b886a6f4d50de61e6352ba
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: eec1e049ea36e70c0d9c707efdb1aeda373c327b6b2be1082076619373c5d6b9bc782797dedd2cec2d4c52e947363282d4f1d3f3a43d12de7f2e2b96aff418f3
|
7
|
+
data.tar.gz: 9dd02f79e8312da7af052282a89ddca1328209ffe5b6b68f2815fd394bd6cbd9820fc6c4d862d89009324e5ccf2c748bdbc362726cabeb304daa9c0000ccc0ac
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -14,4 +14,4 @@ ActiveRecord::Base.send(:extend, SecondLevelCache::ActiveRecord::FetchByUniqKey)
|
|
14
14
|
ActiveRecord::Base.send(:include, SecondLevelCache::ActiveRecord::Persistence)
|
15
15
|
ActiveRecord::Associations::BelongsToAssociation.send(:include, SecondLevelCache::ActiveRecord::Associations::BelongsToAssociation)
|
16
16
|
ActiveRecord::Associations::HasOneAssociation.send(:include, SecondLevelCache::ActiveRecord::Associations::HasOneAssociation)
|
17
|
-
ActiveRecord::Associations::Preloader::
|
17
|
+
ActiveRecord::Associations::Preloader::BelongsTo.send(:include, SecondLevelCache::ActiveRecord::Associations::Preloader::BelongsTo)
|
@@ -12,7 +12,11 @@ module SecondLevelCache
|
|
12
12
|
|
13
13
|
def find_target_with_second_level_cache
|
14
14
|
return find_target_without_second_level_cache unless klass.second_level_cache_enabled?
|
15
|
-
|
15
|
+
if reflection.options[:as]
|
16
|
+
cache_record = klass.fetch_by_uniq_keys({reflection.foreign_key => owner[reflection.active_record_primary_key], reflection.type => owner.class.base_class.name})
|
17
|
+
else
|
18
|
+
cache_record = klass.fetch_by_uniq_key(owner[reflection.active_record_primary_key], reflection.foreign_key)
|
19
|
+
end
|
16
20
|
return cache_record.tap{|record| set_inverse_instance(record)} if cache_record
|
17
21
|
|
18
22
|
record = find_target_without_second_level_cache
|
@@ -17,7 +17,8 @@ module SecondLevelCache
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def reload_with_second_level_cache(options = nil)
|
20
|
-
|
20
|
+
expire_second_level_cache
|
21
|
+
reload_without_second_level_cache(options)
|
21
22
|
end
|
22
23
|
|
23
24
|
def touch_with_second_level_cache(name = nil)
|
@@ -3,13 +3,11 @@ module SecondLevelCache
|
|
3
3
|
module ActiveRecord
|
4
4
|
module Associations
|
5
5
|
class Preloader
|
6
|
-
module
|
6
|
+
module BelongsTo
|
7
7
|
extend ActiveSupport::Concern
|
8
8
|
|
9
9
|
included do
|
10
|
-
|
11
|
-
alias_method_chain :records_for, :second_level_cache
|
12
|
-
end
|
10
|
+
alias_method_chain :records_for, :second_level_cache
|
13
11
|
end
|
14
12
|
|
15
13
|
def records_for_with_second_level_cache(ids)
|
@@ -17,9 +15,9 @@ module SecondLevelCache
|
|
17
15
|
|
18
16
|
map_cache_keys = ids.map{|id| klass.second_level_cache_key(id)}
|
19
17
|
records_from_cache = ::SecondLevelCache.cache_store.read_multi(*map_cache_keys)
|
20
|
-
# NOTICE
|
18
|
+
# NOTICE
|
21
19
|
# Rails.cache.read_multi return hash that has keys only hitted.
|
22
|
-
# eg. Rails.cache.read_multi(1,2,3) => {2 => hit_value, 3 => hit_value}
|
20
|
+
# eg. Rails.cache.read_multi(1,2,3) => {2 => hit_value, 3 => hit_value}
|
23
21
|
hitted_ids = records_from_cache.map{|key, _| key.split("/")[2].to_i}
|
24
22
|
missed_ids = ids.map{|x| x.to_i} - hitted_ids
|
25
23
|
|
@@ -40,6 +38,6 @@ module SecondLevelCache
|
|
40
38
|
end
|
41
39
|
end
|
42
40
|
end
|
43
|
-
end
|
41
|
+
end
|
44
42
|
end
|
45
43
|
end
|
data/second_level_cache.gemspec
CHANGED
@@ -35,5 +35,5 @@ Gem::Specification.new do |gem|
|
|
35
35
|
gem.add_runtime_dependency "activerecord", ["> 4.0.0", "< 5.0"]
|
36
36
|
gem.add_development_dependency "sqlite3"
|
37
37
|
gem.add_development_dependency "rake"
|
38
|
-
gem.add_development_dependency "database_cleaner", "~> 1.
|
38
|
+
gem.add_development_dependency "database_cleaner", "~> 1.3.0"
|
39
39
|
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'active_support/test_case'
|
2
|
+
|
3
|
+
module ActiveRecordTestCaseHelper
|
4
|
+
def teardown
|
5
|
+
SQLCounter.clear_log
|
6
|
+
end
|
7
|
+
|
8
|
+
def assert_date_from_db(expected, actual, message = nil)
|
9
|
+
assert_equal expected.to_s, actual.to_s, message
|
10
|
+
end
|
11
|
+
|
12
|
+
def capture(stream)
|
13
|
+
stream = stream.to_s
|
14
|
+
captured_stream = Tempfile.new(stream)
|
15
|
+
stream_io = eval("$#{stream}")
|
16
|
+
origin_stream = stream_io.dup
|
17
|
+
stream_io.reopen(captured_stream)
|
18
|
+
|
19
|
+
yield
|
20
|
+
|
21
|
+
stream_io.rewind
|
22
|
+
return captured_stream.read
|
23
|
+
ensure
|
24
|
+
captured_stream.close
|
25
|
+
captured_stream.unlink
|
26
|
+
stream_io.reopen(origin_stream)
|
27
|
+
end
|
28
|
+
|
29
|
+
def capture_sql
|
30
|
+
SQLCounter.clear_log
|
31
|
+
yield
|
32
|
+
SQLCounter.log_all.dup
|
33
|
+
end
|
34
|
+
|
35
|
+
def assert_sql(*patterns_to_match)
|
36
|
+
capture_sql { yield }
|
37
|
+
ensure
|
38
|
+
failed_patterns = []
|
39
|
+
patterns_to_match.each do |pattern|
|
40
|
+
failed_patterns << pattern unless SQLCounter.log_all.any?{ |sql| pattern === sql }
|
41
|
+
end
|
42
|
+
assert failed_patterns.empty?, "Query pattern(s) #{failed_patterns.map{ |p| p.inspect }.join(', ')} not found.#{SQLCounter.log.size == 0 ? '' : "\nQueries:\n#{SQLCounter.log.join("\n")}"}"
|
43
|
+
end
|
44
|
+
|
45
|
+
def assert_queries(num = 1, options = {})
|
46
|
+
ignore_none = options.fetch(:ignore_none) { num == :any }
|
47
|
+
SQLCounter.clear_log
|
48
|
+
x = yield
|
49
|
+
the_log = ignore_none ? SQLCounter.log_all : SQLCounter.log
|
50
|
+
if num == :any
|
51
|
+
assert_operator the_log.size, :>=, 1, "1 or more queries expected, but none were executed."
|
52
|
+
else
|
53
|
+
mesg = "#{the_log.size} instead of #{num} queries were executed.#{the_log.size == 0 ? '' : "\nQueries:\n#{the_log.join("\n")}"}"
|
54
|
+
assert_equal num, the_log.size, mesg
|
55
|
+
end
|
56
|
+
x
|
57
|
+
end
|
58
|
+
|
59
|
+
def assert_no_queries(options = {}, &block)
|
60
|
+
options.reverse_merge! ignore_none: true
|
61
|
+
assert_queries(0, options, &block)
|
62
|
+
end
|
63
|
+
|
64
|
+
def assert_column(model, column_name, msg=nil)
|
65
|
+
assert has_column?(model, column_name), msg
|
66
|
+
end
|
67
|
+
|
68
|
+
def assert_no_column(model, column_name, msg=nil)
|
69
|
+
assert_not has_column?(model, column_name), msg
|
70
|
+
end
|
71
|
+
|
72
|
+
def has_column?(model, column_name)
|
73
|
+
model.reset_column_information
|
74
|
+
model.column_names.include?(column_name.to_s)
|
75
|
+
end
|
76
|
+
|
77
|
+
class SQLCounter
|
78
|
+
class << self
|
79
|
+
attr_accessor :ignored_sql, :log, :log_all
|
80
|
+
def clear_log; self.log = []; self.log_all = []; end
|
81
|
+
end
|
82
|
+
|
83
|
+
self.clear_log
|
84
|
+
|
85
|
+
self.ignored_sql = [/^PRAGMA/, /^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/, /^SELECT @@ROWCOUNT/, /^SAVEPOINT/, /^ROLLBACK TO SAVEPOINT/, /^RELEASE SAVEPOINT/, /^SHOW max_identifier_length/, /^BEGIN/, /^COMMIT/]
|
86
|
+
|
87
|
+
# FIXME: this needs to be refactored so specific database can add their own
|
88
|
+
# ignored SQL, or better yet, use a different notification for the queries
|
89
|
+
# instead examining the SQL content.
|
90
|
+
oracle_ignored = [/^select .*nextval/i, /^SAVEPOINT/, /^ROLLBACK TO/, /^\s*select .* from all_triggers/im, /^\s*select .* from all_constraints/im, /^\s*select .* from all_tab_cols/im]
|
91
|
+
mysql_ignored = [/^SHOW TABLES/i, /^SHOW FULL FIELDS/, /^SHOW CREATE TABLE /i, /^SHOW VARIABLES /]
|
92
|
+
postgresql_ignored = [/^\s*select\b.*\bfrom\b.*pg_namespace\b/im, /^\s*select tablename\b.*from pg_tables\b/im, /^\s*select\b.*\battname\b.*\bfrom\b.*\bpg_attribute\b/im, /^SHOW search_path/i]
|
93
|
+
sqlite3_ignored = [/^\s*SELECT name\b.*\bFROM sqlite_master/im]
|
94
|
+
|
95
|
+
[oracle_ignored, mysql_ignored, postgresql_ignored, sqlite3_ignored].each do |db_ignored_sql|
|
96
|
+
ignored_sql.concat db_ignored_sql
|
97
|
+
end
|
98
|
+
|
99
|
+
attr_reader :ignore
|
100
|
+
|
101
|
+
def initialize(ignore = Regexp.union(self.class.ignored_sql))
|
102
|
+
@ignore = ignore
|
103
|
+
end
|
104
|
+
|
105
|
+
def call(name, start, finish, message_id, values)
|
106
|
+
sql = values[:sql]
|
107
|
+
|
108
|
+
# FIXME: this seems bad. we should probably have a better way to indicate
|
109
|
+
# the query was cached
|
110
|
+
return if 'CACHE' == values[:name]
|
111
|
+
|
112
|
+
self.class.log_all << sql
|
113
|
+
self.class.log << sql unless ignore =~ sql
|
114
|
+
end
|
115
|
+
|
116
|
+
ActiveSupport::Notifications.subscribe('sql.active_record', SQLCounter.new)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
ActiveSupport::TestCase.send(:include, ActiveRecordTestCaseHelper)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
|
-
require '
|
2
|
+
require 'test_helper'
|
3
3
|
|
4
|
-
class
|
4
|
+
class BaseTest < ActiveSupport::TestCase
|
5
5
|
def setup
|
6
6
|
@user = User.create :name => 'csdn', :email => 'test@csdn.com'
|
7
7
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
|
-
require '
|
2
|
+
require 'test_helper'
|
3
3
|
|
4
|
-
class
|
4
|
+
class BelongsToAssociationTest < ActiveSupport::TestCase
|
5
5
|
def setup
|
6
6
|
@user = User.create :name => 'csdn', :email => 'test@csdn.com'
|
7
7
|
end
|
@@ -11,7 +11,7 @@ class ActiveRecord::BelongsToAssociationTest < Minitest::Test
|
|
11
11
|
|
12
12
|
@user.write_second_level_cache
|
13
13
|
book.clear_association_cache
|
14
|
-
|
14
|
+
assert_no_queries do
|
15
15
|
assert_equal @user, book.user
|
16
16
|
end
|
17
17
|
end
|
@@ -1,9 +1,8 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
|
-
require '
|
2
|
+
require 'test_helper'
|
3
3
|
|
4
|
-
class
|
4
|
+
class FetchByUinqKeyTest < ActiveSupport::TestCase
|
5
5
|
def setup
|
6
|
-
DatabaseCleaner[:active_record].start
|
7
6
|
@user = User.create :name => 'hooopo', :email => 'hoooopo@gmail.com'
|
8
7
|
@post = Post.create :slug => "foobar", :topic_id => 2
|
9
8
|
end
|
@@ -17,15 +16,16 @@ class ActiveRecord::FetchByUinqKeyTest < Minitest::Test
|
|
17
16
|
|
18
17
|
def test_should_query_from_db_using_primary_key
|
19
18
|
Post.fetch_by_uniq_keys(:topic_id => 2, :slug => "foobar")
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
@post.expire_second_level_cache
|
20
|
+
assert_sql 'SELECT "posts".* FROM "posts" WHERE "posts"."id" = ? LIMIT 1' do
|
21
|
+
Post.fetch_by_uniq_keys(:topic_id => 2, :slug => "foobar")
|
22
|
+
end
|
23
23
|
end
|
24
24
|
|
25
25
|
def test_should_not_hit_db_using_fetch_by_uniq_key_twice
|
26
26
|
post = Post.fetch_by_uniq_keys(:topic_id => 2, :slug => "foobar")
|
27
27
|
assert_equal post, @post
|
28
|
-
|
28
|
+
assert_no_queries do
|
29
29
|
Post.fetch_by_uniq_keys(:topic_id => 2, :slug => "foobar")
|
30
30
|
end
|
31
31
|
end
|
@@ -34,12 +34,12 @@ class ActiveRecord::FetchByUinqKeyTest < Minitest::Test
|
|
34
34
|
assert_raises(ActiveRecord::RecordNotFound) do
|
35
35
|
Post.fetch_by_uniq_keys!(:topic_id => 2, :slug => "foobar1")
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
38
|
assert_raises(ActiveRecord::RecordNotFound) do
|
39
39
|
User.fetch_by_uniq_key!("xxxxx", :name)
|
40
40
|
end
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
def test_should_work_with_fetch_by_uniq_key
|
44
44
|
user = User.fetch_by_uniq_key(@user.name, :name)
|
45
45
|
assert_equal user, @user
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
|
-
require '
|
2
|
+
require 'test_helper'
|
3
3
|
|
4
|
-
class
|
4
|
+
class FinderMethodsTest < ActiveSupport::TestCase
|
5
5
|
def setup
|
6
6
|
@user = User.create :name => 'csdn', :email => 'test@csdn.com'
|
7
7
|
end
|
@@ -13,14 +13,14 @@ class ActiveRecord::FinderMethodsTest < Minitest::Test
|
|
13
13
|
|
14
14
|
def test_should_find_with_cache
|
15
15
|
@user.write_second_level_cache
|
16
|
-
|
16
|
+
assert_no_queries do
|
17
17
|
assert_equal @user, User.find(@user.id)
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
21
|
def test_should_find_with_condition
|
22
22
|
@user.write_second_level_cache
|
23
|
-
|
23
|
+
assert_no_queries do
|
24
24
|
assert_equal @user, User.where(:name => @user.name).find(@user.id)
|
25
25
|
end
|
26
26
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
|
-
require '
|
2
|
+
require 'test_helper'
|
3
3
|
|
4
|
-
class
|
4
|
+
class HasOneAssociationTest < ActiveSupport::TestCase
|
5
5
|
def setup
|
6
6
|
@user = User.create :name => 'hooopo', :email => 'hoooopo@gmail.com'
|
7
7
|
@account = @user.create_account
|
@@ -9,7 +9,7 @@ class ActiveRecord::HasOneAssociationTest < Minitest::Test
|
|
9
9
|
|
10
10
|
def test_should_fetch_account_from_cache
|
11
11
|
clean_user = @user.reload
|
12
|
-
|
12
|
+
assert_no_queries do
|
13
13
|
clean_user.account
|
14
14
|
end
|
15
15
|
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -1,13 +1,18 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
|
-
require '
|
2
|
+
require 'test_helper'
|
3
3
|
|
4
|
-
class
|
4
|
+
class PersistenceTest < ActiveSupport::TestCase
|
5
5
|
def setup
|
6
6
|
@user = User.create :name => 'csdn', :email => 'test@csdn.com'
|
7
7
|
@topic = Topic.create :title => "csdn"
|
8
8
|
end
|
9
9
|
|
10
10
|
def test_should_reload_object
|
11
|
+
User.where(id: @user.id).update_all(email: 'different@csdn.com')
|
12
|
+
assert_equal 'different@csdn.com', @user.reload.email
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_should_reload_object_associations
|
11
16
|
User.increment_counter :books_count, @user.id
|
12
17
|
assert_equal 0, @user.books_count
|
13
18
|
assert_equal 1, @user.reload.books_count
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
|
-
require '
|
2
|
+
require 'test_helper'
|
3
3
|
|
4
|
-
class
|
4
|
+
class PolymorphicAssociationTest < ActiveSupport::TestCase
|
5
5
|
def setup
|
6
6
|
@user = User.create :name => 'csdn', :email => 'test@csdn.com'
|
7
7
|
end
|
@@ -10,7 +10,7 @@ class ActiveRecord::PolymorphicAssociationTest < Minitest::Test
|
|
10
10
|
image = @user.images.create
|
11
11
|
|
12
12
|
@user.write_second_level_cache
|
13
|
-
|
13
|
+
assert_no_queries do
|
14
14
|
assert_equal @user, image.imagable
|
15
15
|
end
|
16
16
|
end
|
@@ -21,4 +21,3 @@ class ActiveRecord::PolymorphicAssociationTest < Minitest::Test
|
|
21
21
|
assert_equal @user, image.imagable
|
22
22
|
end
|
23
23
|
end
|
24
|
-
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'test_helper'
|
3
|
+
|
4
|
+
class PreloaderTest < ActiveSupport::TestCase
|
5
|
+
def test_belongs_to_preload_caches_includes
|
6
|
+
topics = [
|
7
|
+
Topic.create(title: 'title1', body: 'body1'),
|
8
|
+
Topic.create(title: 'title2', body: 'body2'),
|
9
|
+
Topic.create(title: 'title3', body: 'body3')
|
10
|
+
]
|
11
|
+
topics.each { |topic| topic.posts.create(body: "post#{topic.id}") }
|
12
|
+
|
13
|
+
results = nil
|
14
|
+
assert_queries(1) do
|
15
|
+
results = Post.includes(:topic).order('id ASC').to_a
|
16
|
+
end
|
17
|
+
assert_equal topics, results.map(&:topic)
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_belongs_to_when_read_multi_missed_from_cache_AR_will_fetch_missed_records_from_db
|
21
|
+
topics = [
|
22
|
+
Topic.create(title: 'title1', body: 'body1'),
|
23
|
+
Topic.create(title: 'title2', body: 'body2'),
|
24
|
+
Topic.create(title: 'title3', body: 'body3')
|
25
|
+
]
|
26
|
+
topics.each { |topic| topic.posts.create(body: "post#{topic.id}") }
|
27
|
+
expired_topic = topics.first
|
28
|
+
expired_topic.expire_second_level_cache
|
29
|
+
|
30
|
+
results = nil
|
31
|
+
assert_queries(2) do
|
32
|
+
assert_sql(/IN\s+\(#{expired_topic.id}\)/m) do
|
33
|
+
results = Post.includes(:topic).order('id ASC').to_a
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
assert_equal topics, results.map(&:topic)
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_has_many_preloader_returns_correct_results
|
41
|
+
topic = Topic.create(id: 1)
|
42
|
+
Post.create(id: 1)
|
43
|
+
post = topic.posts.create
|
44
|
+
|
45
|
+
assert_equal [post], Topic.includes(:posts).find(1).posts
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_has_one_preloader_returns_correct_results
|
49
|
+
user = User.create(id: 1)
|
50
|
+
Account.create(id: 1)
|
51
|
+
account = user.create_account
|
52
|
+
|
53
|
+
assert_equal account, User.includes(:account).find(1).account
|
54
|
+
end
|
55
|
+
end
|
data/test/record_marshal_test.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
|
-
require '
|
2
|
+
require 'test_helper'
|
3
3
|
|
4
|
-
class RecordMarshalTest <
|
4
|
+
class RecordMarshalTest < ActiveSupport::TestCase
|
5
5
|
def setup
|
6
6
|
@user = User.create :name => 'csdn', :email => 'test@csdn.com'
|
7
7
|
end
|
data/test/require_test.rb
CHANGED
@@ -2,10 +2,10 @@
|
|
2
2
|
require 'test_helper'
|
3
3
|
require 'active_record'
|
4
4
|
|
5
|
-
class RequireTest <
|
5
|
+
class RequireTest < ActiveSupport::TestCase
|
6
6
|
def setup
|
7
7
|
ActiveRecord::Relation
|
8
|
-
require '
|
8
|
+
require 'test_helper'
|
9
9
|
@user = User.create :name => 'Dingding Ye', :email => 'yedingding@gmail.com'
|
10
10
|
end
|
11
11
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
|
-
require '
|
2
|
+
require 'test_helper'
|
3
3
|
|
4
|
-
class
|
4
|
+
class SecondLevelCacheTest < ActiveSupport::TestCase
|
5
5
|
def setup
|
6
6
|
@user = User.create :name => 'csdn', :email => 'test@csdn.com'
|
7
7
|
end
|
data/test/test_helper.rb
CHANGED
@@ -1,14 +1,39 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
|
-
require 'rubygems'
|
3
2
|
require 'bundler/setup'
|
4
|
-
require 'second_level_cache'
|
5
3
|
require 'minitest/autorun'
|
4
|
+
require 'active_support/test_case'
|
5
|
+
require 'active_record_test_case_helper'
|
6
6
|
require 'database_cleaner'
|
7
7
|
|
8
|
-
|
8
|
+
require 'active_record'
|
9
|
+
require 'second_level_cache'
|
10
|
+
|
11
|
+
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
|
12
|
+
|
13
|
+
require 'model/user'
|
14
|
+
require 'model/book'
|
15
|
+
require 'model/image'
|
16
|
+
require 'model/topic'
|
17
|
+
require 'model/post'
|
18
|
+
require 'model/account'
|
19
|
+
|
20
|
+
DatabaseCleaner[:active_record].strategy = :truncation
|
9
21
|
|
10
22
|
SecondLevelCache.configure do |config|
|
11
23
|
config.cache_store = ActiveSupport::Cache::MemoryStore.new
|
12
24
|
end
|
13
25
|
|
14
|
-
SecondLevelCache.logger.level = Logger::
|
26
|
+
SecondLevelCache.logger.level = Logger::ERROR
|
27
|
+
ActiveSupport::Cache::MemoryStore.logger = SecondLevelCache::Config.logger
|
28
|
+
ActiveRecord::Base.logger = SecondLevelCache::Config.logger
|
29
|
+
|
30
|
+
class ActiveSupport::TestCase
|
31
|
+
setup do
|
32
|
+
SecondLevelCache.cache_store.clear
|
33
|
+
DatabaseCleaner.start
|
34
|
+
end
|
35
|
+
|
36
|
+
teardown do
|
37
|
+
DatabaseCleaner.clean
|
38
|
+
end
|
39
|
+
end
|
metadata
CHANGED
@@ -1,108 +1,97 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: second_level_cache
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.0
|
5
|
-
prerelease: 6
|
4
|
+
version: 2.1.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Hooopo
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2014-
|
11
|
+
date: 2014-09-23 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: activesupport
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - ">"
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: 4.0.0
|
22
|
-
- - <
|
20
|
+
- - "<"
|
23
21
|
- !ruby/object:Gem::Version
|
24
22
|
version: '5.0'
|
25
23
|
type: :runtime
|
26
24
|
prerelease: false
|
27
25
|
version_requirements: !ruby/object:Gem::Requirement
|
28
|
-
none: false
|
29
26
|
requirements:
|
30
|
-
- -
|
27
|
+
- - ">"
|
31
28
|
- !ruby/object:Gem::Version
|
32
29
|
version: 4.0.0
|
33
|
-
- - <
|
30
|
+
- - "<"
|
34
31
|
- !ruby/object:Gem::Version
|
35
32
|
version: '5.0'
|
36
33
|
- !ruby/object:Gem::Dependency
|
37
34
|
name: activerecord
|
38
35
|
requirement: !ruby/object:Gem::Requirement
|
39
|
-
none: false
|
40
36
|
requirements:
|
41
|
-
- -
|
37
|
+
- - ">"
|
42
38
|
- !ruby/object:Gem::Version
|
43
39
|
version: 4.0.0
|
44
|
-
- - <
|
40
|
+
- - "<"
|
45
41
|
- !ruby/object:Gem::Version
|
46
42
|
version: '5.0'
|
47
43
|
type: :runtime
|
48
44
|
prerelease: false
|
49
45
|
version_requirements: !ruby/object:Gem::Requirement
|
50
|
-
none: false
|
51
46
|
requirements:
|
52
|
-
- -
|
47
|
+
- - ">"
|
53
48
|
- !ruby/object:Gem::Version
|
54
49
|
version: 4.0.0
|
55
|
-
- - <
|
50
|
+
- - "<"
|
56
51
|
- !ruby/object:Gem::Version
|
57
52
|
version: '5.0'
|
58
53
|
- !ruby/object:Gem::Dependency
|
59
54
|
name: sqlite3
|
60
55
|
requirement: !ruby/object:Gem::Requirement
|
61
|
-
none: false
|
62
56
|
requirements:
|
63
|
-
- -
|
57
|
+
- - ">="
|
64
58
|
- !ruby/object:Gem::Version
|
65
59
|
version: '0'
|
66
60
|
type: :development
|
67
61
|
prerelease: false
|
68
62
|
version_requirements: !ruby/object:Gem::Requirement
|
69
|
-
none: false
|
70
63
|
requirements:
|
71
|
-
- -
|
64
|
+
- - ">="
|
72
65
|
- !ruby/object:Gem::Version
|
73
66
|
version: '0'
|
74
67
|
- !ruby/object:Gem::Dependency
|
75
68
|
name: rake
|
76
69
|
requirement: !ruby/object:Gem::Requirement
|
77
|
-
none: false
|
78
70
|
requirements:
|
79
|
-
- -
|
71
|
+
- - ">="
|
80
72
|
- !ruby/object:Gem::Version
|
81
73
|
version: '0'
|
82
74
|
type: :development
|
83
75
|
prerelease: false
|
84
76
|
version_requirements: !ruby/object:Gem::Requirement
|
85
|
-
none: false
|
86
77
|
requirements:
|
87
|
-
- -
|
78
|
+
- - ">="
|
88
79
|
- !ruby/object:Gem::Version
|
89
80
|
version: '0'
|
90
81
|
- !ruby/object:Gem::Dependency
|
91
82
|
name: database_cleaner
|
92
83
|
requirement: !ruby/object:Gem::Requirement
|
93
|
-
none: false
|
94
84
|
requirements:
|
95
|
-
- - ~>
|
85
|
+
- - "~>"
|
96
86
|
- !ruby/object:Gem::Version
|
97
|
-
version: 1.
|
87
|
+
version: 1.3.0
|
98
88
|
type: :development
|
99
89
|
prerelease: false
|
100
90
|
version_requirements: !ruby/object:Gem::Requirement
|
101
|
-
none: false
|
102
91
|
requirements:
|
103
|
-
- - ~>
|
92
|
+
- - "~>"
|
104
93
|
- !ruby/object:Gem::Version
|
105
|
-
version: 1.
|
94
|
+
version: 1.3.0
|
106
95
|
description: Write Through and Read Through caching library inspired by CacheMoney
|
107
96
|
and cache_fu, support ActiveRecord 4.
|
108
97
|
email:
|
@@ -111,6 +100,12 @@ executables: []
|
|
111
100
|
extensions: []
|
112
101
|
extra_rdoc_files: []
|
113
102
|
files:
|
103
|
+
- CHANGELOG.md
|
104
|
+
- Gemfile
|
105
|
+
- README.md
|
106
|
+
- Rakefile
|
107
|
+
- lib/second_level_cache.rb
|
108
|
+
- lib/second_level_cache/active_record.rb
|
114
109
|
- lib/second_level_cache/active_record/base.rb
|
115
110
|
- lib/second_level_cache/active_record/belongs_to_association.rb
|
116
111
|
- lib/second_level_cache/active_record/fetch_by_uniq_key.rb
|
@@ -118,82 +113,75 @@ files:
|
|
118
113
|
- lib/second_level_cache/active_record/has_one_association.rb
|
119
114
|
- lib/second_level_cache/active_record/persistence.rb
|
120
115
|
- lib/second_level_cache/active_record/preloader.rb
|
121
|
-
- lib/second_level_cache/active_record.rb
|
122
116
|
- lib/second_level_cache/arel/wheres.rb
|
123
117
|
- lib/second_level_cache/config.rb
|
124
118
|
- lib/second_level_cache/record_marshal.rb
|
125
119
|
- lib/second_level_cache/version.rb
|
126
|
-
- lib/second_level_cache.rb
|
127
|
-
- README.md
|
128
|
-
- Rakefile
|
129
|
-
- Gemfile
|
130
|
-
- CHANGELOG.md
|
131
120
|
- second_level_cache.gemspec
|
132
|
-
- test/
|
133
|
-
- test/
|
134
|
-
- test/
|
135
|
-
- test/
|
136
|
-
- test/
|
137
|
-
- test/
|
138
|
-
- test/
|
139
|
-
- test/
|
140
|
-
- test/
|
141
|
-
- test/
|
142
|
-
- test/
|
143
|
-
- test/
|
144
|
-
- test/
|
145
|
-
- test/
|
146
|
-
- test/
|
147
|
-
- test/active_record/test_helper.rb
|
121
|
+
- test/active_record_test_case_helper.rb
|
122
|
+
- test/base_test.rb
|
123
|
+
- test/belongs_to_association_test.rb
|
124
|
+
- test/fetch_by_uniq_key_test.rb
|
125
|
+
- test/finder_methods_test.rb
|
126
|
+
- test/has_one_association_test.rb
|
127
|
+
- test/model/account.rb
|
128
|
+
- test/model/book.rb
|
129
|
+
- test/model/image.rb
|
130
|
+
- test/model/post.rb
|
131
|
+
- test/model/topic.rb
|
132
|
+
- test/model/user.rb
|
133
|
+
- test/persistence_test.rb
|
134
|
+
- test/polymorphic_association_test.rb
|
135
|
+
- test/preloader_test.rb
|
148
136
|
- test/record_marshal_test.rb
|
149
137
|
- test/require_test.rb
|
138
|
+
- test/second_level_cache_test.rb
|
150
139
|
- test/test_helper.rb
|
151
140
|
homepage: https://github.com/csdn-dev/second_level_cache
|
152
141
|
licenses: []
|
142
|
+
metadata: {}
|
153
143
|
post_install_message:
|
154
144
|
rdoc_options: []
|
155
145
|
require_paths:
|
156
146
|
- lib
|
157
147
|
required_ruby_version: !ruby/object:Gem::Requirement
|
158
|
-
none: false
|
159
148
|
requirements:
|
160
|
-
- -
|
149
|
+
- - ">="
|
161
150
|
- !ruby/object:Gem::Version
|
162
151
|
version: '0'
|
163
152
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
164
|
-
none: false
|
165
153
|
requirements:
|
166
|
-
- -
|
154
|
+
- - ">="
|
167
155
|
- !ruby/object:Gem::Version
|
168
|
-
version:
|
156
|
+
version: '0'
|
169
157
|
requirements: []
|
170
158
|
rubyforge_project:
|
171
|
-
rubygems_version:
|
159
|
+
rubygems_version: 2.2.2
|
172
160
|
signing_key:
|
173
|
-
specification_version:
|
174
|
-
summary:
|
161
|
+
specification_version: 4
|
162
|
+
summary: 'SecondLevelCache is a write-through and read-through caching library inspired
|
175
163
|
by Cache Money and cache_fu, support only Rails3 and ActiveRecord. Read-Through:
|
176
164
|
Queries by ID, like current_user.articles.find(params[:id]), will first look in
|
177
165
|
cache store and then look in the database for the results of that query. If there
|
178
166
|
is a cache miss, it will populate the cache. Write-Through: As objects are created,
|
179
167
|
updated, and deleted, all of the caches are automatically kept up-to-date and coherent.'
|
180
168
|
test_files:
|
181
|
-
- test/
|
182
|
-
- test/
|
183
|
-
- test/
|
184
|
-
- test/
|
185
|
-
- test/
|
186
|
-
- test/
|
187
|
-
- test/
|
188
|
-
- test/
|
189
|
-
- test/
|
190
|
-
- test/
|
191
|
-
- test/
|
192
|
-
- test/
|
193
|
-
- test/
|
194
|
-
- test/
|
195
|
-
- test/
|
196
|
-
- test/active_record/test_helper.rb
|
169
|
+
- test/active_record_test_case_helper.rb
|
170
|
+
- test/base_test.rb
|
171
|
+
- test/belongs_to_association_test.rb
|
172
|
+
- test/fetch_by_uniq_key_test.rb
|
173
|
+
- test/finder_methods_test.rb
|
174
|
+
- test/has_one_association_test.rb
|
175
|
+
- test/model/account.rb
|
176
|
+
- test/model/book.rb
|
177
|
+
- test/model/image.rb
|
178
|
+
- test/model/post.rb
|
179
|
+
- test/model/topic.rb
|
180
|
+
- test/model/user.rb
|
181
|
+
- test/persistence_test.rb
|
182
|
+
- test/polymorphic_association_test.rb
|
183
|
+
- test/preloader_test.rb
|
197
184
|
- test/record_marshal_test.rb
|
198
185
|
- test/require_test.rb
|
186
|
+
- test/second_level_cache_test.rb
|
199
187
|
- test/test_helper.rb
|
@@ -1,28 +0,0 @@
|
|
1
|
-
# -*- encoding : utf-8 -*-
|
2
|
-
require 'active_record/test_helper'
|
3
|
-
|
4
|
-
class ActiveRecord::PreloaderTest < Minitest::Test
|
5
|
-
def setup
|
6
|
-
DatabaseCleaner[:active_record].start
|
7
|
-
@topic1 = Topic.create :title => "title1", :body => "body1"
|
8
|
-
@topic2 = Topic.create :title => "title2", :body => "body2"
|
9
|
-
@topic3 = Topic.create :title => "title3", :body => "body3"
|
10
|
-
@post1 = @topic1.posts.create :body => "post1"
|
11
|
-
@post2 = @topic2.posts.create :body => "post2"
|
12
|
-
@post3 = @topic3.posts.create :body => "post3"
|
13
|
-
end
|
14
|
-
|
15
|
-
def test_preload_work_properly
|
16
|
-
results = Post.includes(:topic).order("id ASC").to_a
|
17
|
-
assert_equal results.size, 3
|
18
|
-
assert_equal results.first.topic, @topic1
|
19
|
-
end
|
20
|
-
|
21
|
-
def test_when_read_multi_missed_from_cache_AR_will_fetch_missed_records_from_db
|
22
|
-
@topic1.expire_second_level_cache
|
23
|
-
results = Post.includes(:topic).order("id ASC").to_a
|
24
|
-
assert_equal results.size, 3
|
25
|
-
assert_equal results.first.topic, @topic1
|
26
|
-
assert_match /IN\s+\(#{@topic1.id}\)/m, $sql_logger
|
27
|
-
end
|
28
|
-
end
|
@@ -1,55 +0,0 @@
|
|
1
|
-
# -*- encoding : utf-8 -*-
|
2
|
-
require 'test_helper'
|
3
|
-
require 'active_record'
|
4
|
-
require 'second_level_cache/active_record'
|
5
|
-
|
6
|
-
def open_test_db_connect
|
7
|
-
ActiveRecord::Base.establish_connection(
|
8
|
-
:adapter => 'sqlite3',
|
9
|
-
:database => 'test/test.sqlite3'
|
10
|
-
)
|
11
|
-
end
|
12
|
-
open_test_db_connect
|
13
|
-
|
14
|
-
def close_test_db_connect
|
15
|
-
ActiveRecord::Base.connection.disconnect!
|
16
|
-
end
|
17
|
-
|
18
|
-
class Minitest::Test
|
19
|
-
def no_connection
|
20
|
-
close_test_db_connect
|
21
|
-
assert_nothing_raised { yield }
|
22
|
-
ensure
|
23
|
-
open_test_db_connect
|
24
|
-
end
|
25
|
-
|
26
|
-
|
27
|
-
def assert_nothing_raised(*)
|
28
|
-
yield
|
29
|
-
end
|
30
|
-
|
31
|
-
def teardown
|
32
|
-
$sql_logger = nil
|
33
|
-
SecondLevelCache.cache_store.clear
|
34
|
-
DatabaseCleaner[:active_record].clean
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
module ActiveRecord
|
39
|
-
module Querying
|
40
|
-
def find_by_sql_with_test(sql, binds = [])
|
41
|
-
$sql_logger ||= ""
|
42
|
-
$sql_logger << sql.to_sql
|
43
|
-
$sql_logger << "\n"
|
44
|
-
find_by_sql_without_test(sql, binds)
|
45
|
-
end
|
46
|
-
alias_method_chain :find_by_sql, :test
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
require 'active_record/model/user'
|
51
|
-
require 'active_record/model/book'
|
52
|
-
require 'active_record/model/image'
|
53
|
-
require 'active_record/model/topic'
|
54
|
-
require 'active_record/model/post'
|
55
|
-
require 'active_record/model/account'
|