activerecord_cache 0.0.6 → 0.0.7
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 +7 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +92 -0
- data/Rakefile +31 -1
- data/activerecord_cache.gemspec +1 -1
- data/lib/activerecord_cache.rb +1 -0
- data/lib/activerecord_cache/base.rb +2 -2
- data/lib/activerecord_cache/finder_methods.rb +3 -26
- data/lib/activerecord_cache/railtie.rb +4 -1
- data/lib/activerecord_cache/relation.rb +4 -6
- data/lib/activerecord_cache/version.rb +1 -1
- data/test/activerecord_cache_test.rb +167 -0
- data/test/dummy/README.rdoc +261 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/app/assets/javascripts/application.js +15 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/mailers/.gitkeep +0 -0
- data/test/dummy/app/models/.gitkeep +0 -0
- data/test/dummy/app/models/associated_record.rb +3 -0
- data/test/dummy/app/models/cached_record.rb +3 -0
- data/test/dummy/app/models/non_primary_associated.rb +3 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +55 -0
- data/test/dummy/config/boot.rb +10 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +39 -0
- data/test/dummy/config/environments/production.rb +70 -0
- data/test/dummy/config/environments/test.rb +33 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/inflections.rb +15 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +7 -0
- data/test/dummy/config/initializers/session_store.rb +8 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +5 -0
- data/test/dummy/config/routes.rb +58 -0
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/migrate/20140715044034_create_cached_records.rb +9 -0
- data/test/dummy/db/migrate/20140715052133_create_associated_records.rb +10 -0
- data/test/dummy/db/migrate/20140715053153_create_non_primary_associateds.rb +9 -0
- data/test/dummy/db/schema.rb +36 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/lib/assets/.gitkeep +0 -0
- data/test/dummy/log/.gitkeep +0 -0
- data/test/dummy/public/404.html +26 -0
- data/test/dummy/public/422.html +26 -0
- data/test/dummy/public/500.html +25 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/script/rails +6 -0
- data/test/dummy/test/fixtures/associated_records.yml +9 -0
- data/test/dummy/test/fixtures/cached_records.yml +7 -0
- data/test/dummy/test/fixtures/non_primary_associateds.yml +9 -0
- data/test/dummy/test/unit/associated_record_test.rb +7 -0
- data/test/dummy/test/unit/cached_record_test.rb +7 -0
- data/test/dummy/test/unit/non_primary_associated_test.rb +7 -0
- data/test/test_helper.rb +15 -0
- metadata +61 -27
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: cc8aa7320c445aea2920adb2282e87eaf140c084
|
4
|
+
data.tar.gz: ef5d398cf49741e94e3b1073ba619e0c810559b7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b57793fdef8d3b740e866bab4595401201f211e881b91e198c77c809ed99770b39563a059805745d374da2f2a5552efd6b3ddcf9384ed0d0a981cc70095fc66a
|
7
|
+
data.tar.gz: ccb1921116861244af6285ffaa82106f28279d8e7ac328521d30bad004a031ef877fd7a96266ec399ea8e20d492ea97fe70092bb4e54b451c0e096afd8ebb85d
|
data/Gemfile
CHANGED
data/Gemfile.lock
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
activerecord_cache (0.0.7)
|
5
|
+
rails (~> 4.0.0)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: http://rubygems.org/
|
9
|
+
specs:
|
10
|
+
actionmailer (4.0.8)
|
11
|
+
actionpack (= 4.0.8)
|
12
|
+
mail (~> 2.5.4)
|
13
|
+
actionpack (4.0.8)
|
14
|
+
activesupport (= 4.0.8)
|
15
|
+
builder (~> 3.1.0)
|
16
|
+
erubis (~> 2.7.0)
|
17
|
+
rack (~> 1.5.2)
|
18
|
+
rack-test (~> 0.6.2)
|
19
|
+
activemodel (4.0.8)
|
20
|
+
activesupport (= 4.0.8)
|
21
|
+
builder (~> 3.1.0)
|
22
|
+
activerecord (4.0.8)
|
23
|
+
activemodel (= 4.0.8)
|
24
|
+
activerecord-deprecated_finders (~> 1.0.2)
|
25
|
+
activesupport (= 4.0.8)
|
26
|
+
arel (~> 4.0.0)
|
27
|
+
activerecord-deprecated_finders (1.0.3)
|
28
|
+
activesupport (4.0.8)
|
29
|
+
i18n (~> 0.6, >= 0.6.9)
|
30
|
+
minitest (~> 4.2)
|
31
|
+
multi_json (~> 1.3)
|
32
|
+
thread_safe (~> 0.1)
|
33
|
+
tzinfo (~> 0.3.37)
|
34
|
+
arel (4.0.2)
|
35
|
+
bourne (1.5.0)
|
36
|
+
mocha (>= 0.13.2, < 0.15)
|
37
|
+
builder (3.1.4)
|
38
|
+
erubis (2.7.0)
|
39
|
+
hike (1.2.3)
|
40
|
+
i18n (0.6.11)
|
41
|
+
mail (2.5.4)
|
42
|
+
mime-types (~> 1.16)
|
43
|
+
treetop (~> 1.4.8)
|
44
|
+
metaclass (0.0.4)
|
45
|
+
mime-types (1.25.1)
|
46
|
+
minitest (4.7.5)
|
47
|
+
mocha (0.14.0)
|
48
|
+
metaclass (~> 0.0.1)
|
49
|
+
multi_json (1.10.1)
|
50
|
+
polyglot (0.3.5)
|
51
|
+
rack (1.5.2)
|
52
|
+
rack-test (0.6.2)
|
53
|
+
rack (>= 1.0)
|
54
|
+
rails (4.0.8)
|
55
|
+
actionmailer (= 4.0.8)
|
56
|
+
actionpack (= 4.0.8)
|
57
|
+
activerecord (= 4.0.8)
|
58
|
+
activesupport (= 4.0.8)
|
59
|
+
bundler (>= 1.3.0, < 2.0)
|
60
|
+
railties (= 4.0.8)
|
61
|
+
sprockets-rails (~> 2.0)
|
62
|
+
railties (4.0.8)
|
63
|
+
actionpack (= 4.0.8)
|
64
|
+
activesupport (= 4.0.8)
|
65
|
+
rake (>= 0.8.7)
|
66
|
+
thor (>= 0.18.1, < 2.0)
|
67
|
+
rake (10.3.2)
|
68
|
+
sprockets (2.12.1)
|
69
|
+
hike (~> 1.2)
|
70
|
+
multi_json (~> 1.0)
|
71
|
+
rack (~> 1.0)
|
72
|
+
tilt (~> 1.1, != 1.3.0)
|
73
|
+
sprockets-rails (2.1.3)
|
74
|
+
actionpack (>= 3.0)
|
75
|
+
activesupport (>= 3.0)
|
76
|
+
sprockets (~> 2.8)
|
77
|
+
sqlite3 (1.3.9)
|
78
|
+
thor (0.19.1)
|
79
|
+
thread_safe (0.3.4)
|
80
|
+
tilt (1.4.1)
|
81
|
+
treetop (1.4.15)
|
82
|
+
polyglot
|
83
|
+
polyglot (>= 0.3.1)
|
84
|
+
tzinfo (0.3.40)
|
85
|
+
|
86
|
+
PLATFORMS
|
87
|
+
ruby
|
88
|
+
|
89
|
+
DEPENDENCIES
|
90
|
+
activerecord_cache!
|
91
|
+
bourne
|
92
|
+
sqlite3
|
data/Rakefile
CHANGED
@@ -1,2 +1,32 @@
|
|
1
|
-
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'TestPlugin'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.rdoc')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
|
2
20
|
Bundler::GemHelper.install_tasks
|
21
|
+
|
22
|
+
require 'rake/testtask'
|
23
|
+
|
24
|
+
Rake::TestTask.new(:test) do |t|
|
25
|
+
t.libs << 'lib'
|
26
|
+
t.libs << 'test'
|
27
|
+
t.pattern = 'test/**/*_test.rb'
|
28
|
+
t.verbose = false
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
task default: :test
|
data/activerecord_cache.gemspec
CHANGED
data/lib/activerecord_cache.rb
CHANGED
@@ -6,5 +6,6 @@ require File.join(File.dirname(__FILE__), 'activerecord_cache/finder_methods')
|
|
6
6
|
require File.join(File.dirname(__FILE__), 'activerecord_cache/belongs_to_association')
|
7
7
|
require File.join(File.dirname(__FILE__), 'activerecord_cache/belongs_to_preloader')
|
8
8
|
require File.join(File.dirname(__FILE__), 'activerecord_cache/relation')
|
9
|
+
require File.join(File.dirname(__FILE__), 'activerecord_cache/errors')
|
9
10
|
|
10
11
|
require 'activerecord_cache/railtie.rb' if defined?(Rails)
|
@@ -14,7 +14,7 @@ module ActiveRecordCache
|
|
14
14
|
def cache_key(id_or_record)
|
15
15
|
unless use_activerecord_cache
|
16
16
|
message = "ActiveRecord cache is not enabled for #{self.name}"
|
17
|
-
raise ActiveRecordCache::
|
17
|
+
raise ActiveRecordCache::CacheNotEnabled, message
|
18
18
|
end
|
19
19
|
|
20
20
|
if id_or_record.is_a?(ActiveRecord::Base)
|
@@ -53,7 +53,7 @@ module ActiveRecordCache
|
|
53
53
|
end
|
54
54
|
|
55
55
|
if cache_misses.present?
|
56
|
-
records += where(primary_key => cache_misses).
|
56
|
+
records += where(primary_key => cache_misses).load
|
57
57
|
end
|
58
58
|
|
59
59
|
records
|
@@ -3,39 +3,18 @@ module ActiveRecordCache
|
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
5
|
included do
|
6
|
-
alias_method_chain :find_by_attributes, :caching
|
7
6
|
alias_method_chain :find_some, :caching
|
8
7
|
alias_method_chain :find_one, :caching
|
9
8
|
end
|
10
9
|
|
11
10
|
protected
|
12
11
|
|
13
|
-
def find_by_attributes_with_caching(match, attributes, *args)
|
14
|
-
unless cached_lookup_allowed? && attributes == Array(@klass.primary_key) && (match.finder == :all || !args.first.is_a?(Array))
|
15
|
-
return find_by_attributes_without_caching(match, attributes, *args)
|
16
|
-
end
|
17
|
-
|
18
|
-
param = args.first
|
19
|
-
|
20
|
-
results = case match.finder
|
21
|
-
when :all then @klass.find_some_through_cache(Array(param))
|
22
|
-
when :first then @klass.find_through_cache(param)
|
23
|
-
when :last then @klass.find_through_cache(param)
|
24
|
-
end
|
25
|
-
|
26
|
-
results
|
27
|
-
end
|
28
|
-
|
29
12
|
def find_some_with_caching(ids)
|
30
13
|
return find_some_without_caching(ids) unless cached_lookup_allowed?
|
31
14
|
|
32
15
|
results = find_some_through_cache(ids)
|
33
16
|
|
34
|
-
|
35
|
-
error = "Couldn't find all #{@klass.name.pluralize} with IDs "
|
36
|
-
error << "(#{ids.join(", ")}) (found #{results.size} results, but was looking for #{ids.size})"
|
37
|
-
raise ActiveRecord::RecordNotFound, error
|
38
|
-
end
|
17
|
+
raise_record_not_found_exception!(ids, result.size, ids.size) unless results.size == ids.size
|
39
18
|
|
40
19
|
results
|
41
20
|
end
|
@@ -43,11 +22,9 @@ module ActiveRecordCache
|
|
43
22
|
def find_one_with_caching(id)
|
44
23
|
return find_one_without_caching(id) unless cached_lookup_allowed?
|
45
24
|
|
46
|
-
record =
|
25
|
+
record = find_through_cache(id)
|
47
26
|
|
48
|
-
unless record
|
49
|
-
raise ActiveRecord::RecordNotFound, "Couldn't find #{@klass.name} with #{primary_key}=#{id}"
|
50
|
-
end
|
27
|
+
raise_record_not_found_exception!(id, 0, 1) unless record
|
51
28
|
|
52
29
|
record
|
53
30
|
end
|
@@ -6,10 +6,13 @@ class ActiveRecordCache::Railtie < Rails::Railtie
|
|
6
6
|
initializer "activerecord_cache.initialize" do
|
7
7
|
ActiveSupport.on_load(:active_record) do
|
8
8
|
ActiveRecord::Base.send(:include, ActiveRecordCache::Base)
|
9
|
-
ActiveRecord::FinderMethods.send(:include, ActiveRecordCache::FinderMethods)
|
10
9
|
ActiveRecord::Associations::BelongsToAssociation.send(:include, ActiveRecordCache::BelongsToAssociation)
|
11
10
|
ActiveRecord::Associations::Preloader::BelongsTo.send(:include, ActiveRecordCache::BelongsToPreloader)
|
12
11
|
ActiveRecord::Relation.send(:include, ActiveRecordCache::Relation)
|
12
|
+
|
13
|
+
# FinderMethods only gets included in ActiveRecord::Relation, so extend it there.
|
14
|
+
# This gets around some headaches caused by extending modules already included in other classes.
|
15
|
+
ActiveRecord::Relation.send(:include, ActiveRecordCache::FinderMethods)
|
13
16
|
end
|
14
17
|
end
|
15
18
|
|
@@ -3,14 +3,12 @@ module ActiveRecordCache
|
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
5
|
included do
|
6
|
-
alias_method_chain :
|
6
|
+
alias_method_chain :exec_queries, :caching
|
7
7
|
end
|
8
8
|
|
9
|
-
def
|
10
|
-
|
11
|
-
|
12
|
-
records = to_a_without_caching
|
13
|
-
records.each(&:write_to_cache) if @klass.use_activerecord_cache && !previously_loaded && select_values.empty?
|
9
|
+
def exec_queries_with_caching
|
10
|
+
records = exec_queries_without_caching
|
11
|
+
records.each(&:write_to_cache) if @klass.use_activerecord_cache && select_values.empty?
|
14
12
|
|
15
13
|
records
|
16
14
|
end
|
@@ -0,0 +1,167 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class ActiveRecordCacheTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
setup do
|
6
|
+
Rails.cache.clear
|
7
|
+
end
|
8
|
+
|
9
|
+
|
10
|
+
|
11
|
+
# Loading records should persist to cache
|
12
|
+
test "loading records using find should persist them to the cache" do
|
13
|
+
Rails.cache.expects(:write).twice
|
14
|
+
CachedRecord.find(1, 2)
|
15
|
+
end
|
16
|
+
|
17
|
+
test "loading all records should persist them to the cache" do
|
18
|
+
Rails.cache.expects(:write).twice
|
19
|
+
CachedRecord.all.load
|
20
|
+
end
|
21
|
+
|
22
|
+
test "loading records using a where should persist them to the cache" do
|
23
|
+
Rails.cache.expects(:write).once
|
24
|
+
CachedRecord.where(:name => 'John').load
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
|
29
|
+
# Finders should use the cache
|
30
|
+
test "#find(id) should use the cache" do
|
31
|
+
cache_records(1)
|
32
|
+
|
33
|
+
assert_query_count 0 do
|
34
|
+
CachedRecord.find(1)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
test "#find(ids) should use the cache" do
|
39
|
+
cache_records(1,2)
|
40
|
+
|
41
|
+
assert_query_count 0 do
|
42
|
+
CachedRecord.find(1, 2)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
test "#find(ids) with some cached records should query for additional records" do
|
47
|
+
cache_records(1)
|
48
|
+
|
49
|
+
assert_query_count 1 do
|
50
|
+
CachedRecord.find(1, 2)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
|
56
|
+
# Complex queries should skip the cache
|
57
|
+
test "#where(:id => id, :other => criteria) should NOT use the cache" do
|
58
|
+
cache_records(1)
|
59
|
+
|
60
|
+
records = CachedRecord.where(:id => 1, :name => 'Bogus').load
|
61
|
+
|
62
|
+
assert records.empty?, 'should not find cached record'
|
63
|
+
end
|
64
|
+
|
65
|
+
test "#select(:id) should NOT use the cache" do
|
66
|
+
cache_records(1)
|
67
|
+
|
68
|
+
Rails.cache.expects(:write).never
|
69
|
+
CachedRecord.select(:id).load
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
|
74
|
+
# belongs_to associations should use the cache
|
75
|
+
test "accessing cached associations should use the cache" do
|
76
|
+
cache_records(1)
|
77
|
+
associated = AssociatedRecord.find(1)
|
78
|
+
|
79
|
+
assert_query_count 0 do
|
80
|
+
associated.cached_record
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
test "accessing associations should persist records to the cache" do
|
85
|
+
associated = AssociatedRecord.find(1)
|
86
|
+
|
87
|
+
Rails.cache.expects(:write).once
|
88
|
+
associated.cached_record
|
89
|
+
end
|
90
|
+
|
91
|
+
test "associations that do not reference the primary key should NOT use the cache" do
|
92
|
+
cache_records(1, 2)
|
93
|
+
non_primary = NonPrimaryAssociated.find(1)
|
94
|
+
|
95
|
+
assert_query_count 1 do
|
96
|
+
non_primary.cached_record
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
|
102
|
+
# Preloading associations should use the cache
|
103
|
+
test "preloading associations should use the cache" do
|
104
|
+
cache_records(1)
|
105
|
+
|
106
|
+
assert_query_count 1 do
|
107
|
+
AssociatedRecord.includes(:cached_record).find(1)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
test "preloading associations should persist records to the cache" do
|
112
|
+
Rails.cache.expects(:write).once
|
113
|
+
AssociatedRecord.includes(:cached_record).find(1)
|
114
|
+
end
|
115
|
+
|
116
|
+
test "preloading associations that do not reference the primary key should NOT use the cache" do
|
117
|
+
cache_records(1, 2)
|
118
|
+
|
119
|
+
assert_query_count 2 do
|
120
|
+
NonPrimaryAssociated.includes(:cached_record).find(1)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
|
125
|
+
|
126
|
+
# Saving and destroying
|
127
|
+
test "saving a record should write it to the cache" do
|
128
|
+
Rails.cache.expects(:write).once
|
129
|
+
CachedRecord.create!({})
|
130
|
+
end
|
131
|
+
|
132
|
+
test "destroying a record should remove it from the cache" do
|
133
|
+
Rails.cache.expects(:delete).once
|
134
|
+
CachedRecord.find(1).destroy
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
|
139
|
+
private
|
140
|
+
|
141
|
+
def assert_query_count(expected_count, &block)
|
142
|
+
count = count_queries do
|
143
|
+
yield block
|
144
|
+
end
|
145
|
+
|
146
|
+
assert_equal expected_count, count, "expected #{expected_count} queries"
|
147
|
+
end
|
148
|
+
|
149
|
+
def count_queries(&block)
|
150
|
+
count = 0
|
151
|
+
|
152
|
+
counter = ->(name, started, finished, unique_id, payload) {
|
153
|
+
unless payload[:name].in? %w[ CACHE SCHEMA ]
|
154
|
+
count += 1
|
155
|
+
end
|
156
|
+
}
|
157
|
+
|
158
|
+
ActiveSupport::Notifications.subscribed(counter, "sql.active_record", &block)
|
159
|
+
|
160
|
+
count
|
161
|
+
end
|
162
|
+
|
163
|
+
def cache_records(*records)
|
164
|
+
CachedRecord.find(Array(records).flatten)
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|