ca_ching 0.1.0

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.
@@ -0,0 +1,214 @@
1
+ require 'spec_helper'
2
+
3
+ module CaChing
4
+ describe ReadThrough do
5
+ describe 'finding on indexed fields' do
6
+ before :all do
7
+ @person = Person.where(:id => 1).to_a_without_cache.first
8
+ @cache = CaChing::Adapters::Redis.new
9
+ end
10
+
11
+ before :each do
12
+ @cache.clear!
13
+ end
14
+
15
+ describe 'cache hit' do
16
+ before(:each) do
17
+ # Prime the cache
18
+ @cache.insert(Person.where(:id => 1).to_a_without_cache, :for => CaChing::Query::Abstract.new(Person.where(:id => 1)))
19
+ @cache.insert(Person.where(:name => @person.name).to_a_without_cache, :for => CaChing::Query::Abstract.new(Person.where(:name => @person.name)))
20
+ @cache.insert(Person.where(:age => @person.age).to_a_without_cache, :for => CaChing::Query::Abstract.new(Person.where(:age => @person.age)))
21
+ @cache.insert(Person.where(:age => @person.age, :salary => @person.salary).to_a_without_cache, :for => CaChing::Query::Abstract.new(Person.where(:age => @person.age, :salary => @person.salary)))
22
+ @cache.insert(Article.where(:person_id => @person.id).to_a_without_cache, :for => CaChing::Query::Abstract.new(Article.where(:person_id => @person.id)))
23
+ end
24
+
25
+ it 'returns the result without querying the database' do
26
+ person = Person.find(1)
27
+ person.from_cache?.should == true
28
+ person.should == Person.where(:id => 1).to_a_without_cache.first
29
+ end
30
+
31
+ it 'finds by id' do
32
+ person = Person.find(1)
33
+ person.from_cache?.should == true
34
+ person.should == Person.where(:id => 1).to_a_without_cache.first
35
+ end
36
+
37
+ describe 'dynamic finders' do
38
+ it 'finds with one parameter' do
39
+ person = Person.find_by_name(@person.name)
40
+ person.from_cache?.should == true
41
+ person.should == @person
42
+ end
43
+
44
+ it 'finds with many parameters' do
45
+ pending
46
+
47
+ person = Person.find_by_name_and_age(@person.name, @person.age)
48
+ person.from_cache?.should == true
49
+ person.should == @person
50
+ end
51
+
52
+ it 'finds all with one parameter' do
53
+ people = Person.find_all_by_age(@person.age)
54
+ people.from_cache?.should == true
55
+ people.map { |p| p.id }.sort.should == Person.where(:age => @person.age).to_a_without_cache.map { |p| p.id }.sort
56
+ end
57
+
58
+ it 'finds all with many parameters' do
59
+ pending
60
+
61
+ people = Person.find_all_by_age_and_salary(@person.age, @person.salary)
62
+ people.from_cache?.should == true
63
+ people.should == Person.where(:age => @person.age, :salary => @person.salary).to_a_without_cache
64
+ end
65
+ end
66
+
67
+ describe 'Arel-style finders' do
68
+ describe 'where' do
69
+ it 'finds with one parameter' do
70
+ people = Person.where(:age => @person.age).all
71
+ people.from_cache?.should == true
72
+ people.sort.should == Person.where(:age => @person.age).to_a_without_cache.sort
73
+ end
74
+
75
+ it 'finds with many parameters' do
76
+ pending
77
+
78
+ people = Person.where(:age => @person.age, :salary => @person.salary).all
79
+ people.from_cache?.should == true
80
+ people.should == Person.where(:age => @person.age, :salary => @person.salary).to_a_without_cache
81
+ end
82
+ end
83
+
84
+ describe 'order' do
85
+ it 'finds if the order matches the order on an indexed field in the query' do
86
+ people = Person.where(:salary => @person.salary).order('salary DESC').all
87
+ people.from_cache?.should == true
88
+ people.should == Person.where(:salary => @person.salary).order('salary DESC').to_a_without_cache
89
+ end
90
+
91
+ it 'skips the cache if the order does not match an order on an indexed field in the query' do
92
+ people = Person.where(:salary => @person.salary).order('salary ASC').all
93
+ people.from_cache?.should == false
94
+ end
95
+ end
96
+
97
+ describe 'limit' do
98
+ it 'limits the returned set to the number specified in limit' do
99
+ articles = Article.where(:person_id => @person.id).limit(2).all
100
+ articles.size.should == 2
101
+ articles.from_cache?.should == true
102
+ end
103
+ end
104
+
105
+ describe 'offset' do
106
+ it 'offsets the returned set by the number specified' do
107
+ articles = Article.where(:person_id => @person.id).offset(3).all
108
+ articles.from_cache?.should == true
109
+ Article.where(:person_id => @person.id).offset(3).to_a_without_cache.should == articles
110
+ end
111
+ end
112
+
113
+ describe 'join, include, etc.' do
114
+ it 'skips the cache' do
115
+ Article.where(:person_id => @person.id).includes(:person).all.from_cache?.should == false
116
+ end
117
+ end
118
+ end
119
+ end
120
+
121
+ describe 'cache miss' do
122
+ it 'stores the result returned from the database' do
123
+ person = Person.find(1)
124
+ person.from_cache?.should == false
125
+
126
+ person = Person.find(1)
127
+ person.from_cache?.should == true
128
+ end
129
+
130
+ it 'finds by id' do
131
+ person = Person.find(1)
132
+ person.from_cache?.should == false
133
+
134
+ person = Person.find(1)
135
+ person.from_cache?.should == true
136
+ end
137
+
138
+ describe 'dynamic finders' do
139
+ it 'finds with one parameter' do
140
+ person = Person.find_by_name(@person.name)
141
+ person.from_cache?.should == false
142
+
143
+ person = Person.find_by_name(@person.name)
144
+ person.from_cache?.should == true
145
+ end
146
+
147
+ it 'finds with many parameters' do
148
+ pending
149
+
150
+ person = Person.find_by_name_and_age(@person.name, @person.age)
151
+ person.from_cache?.should == false
152
+
153
+ person = Person.find_by_name_and_age(@person.name, @person.age)
154
+ person.from_cache?.should == true
155
+ end
156
+
157
+ it 'finds all with one parameter' do
158
+ person = Person.find_all_by_name(@person.name)
159
+ person.from_cache?.should == false
160
+
161
+ person = Person.find_all_by_name(@person.name)
162
+ person.from_cache?.should == true
163
+ end
164
+
165
+ it 'finds all with many parameters' do
166
+ pending
167
+
168
+ person = Person.find_all_by_name_and_age(@person.name, @person.age)
169
+ person.from_cache?.should == false
170
+
171
+ person = Person.find_all_by_name_and_age(@person.name, @person.age)
172
+ person.from_cache?.should == true
173
+ end
174
+ end
175
+
176
+ describe 'Arel-style finders' do
177
+ describe 'where' do
178
+ it 'finds with one parameter' do
179
+ person = Person.where(:name => @person.name).all
180
+ person.from_cache?.should == false
181
+
182
+ person = Person.where(:name => @person.name).all
183
+ person.from_cache?.should == true
184
+ end
185
+
186
+ it 'finds with many parameters' do
187
+ pending
188
+ person = Person.where(:name => @person.name, :age => @person.age).all
189
+ person.from_cache?.should == false
190
+
191
+ person = Person.where(:name => @person.name, :age => @person.age).all
192
+ person.from_cache?.should == true
193
+ end
194
+ end
195
+
196
+ describe 'limit' do
197
+ it 'will cache an incorrect number of items' do
198
+ true.should == false
199
+ end
200
+ end
201
+ end
202
+ end
203
+
204
+ end
205
+
206
+ describe 'finding on non-indexed fields' do
207
+ it 'does not attempt to find via the cache' do
208
+ Tag.where(:name => 'abc').all.from_cache?.should == false
209
+ # Do it twice to illustrate that it isn't cached on miss (because there is no miss)
210
+ Tag.where(:name => 'abc').all.from_cache?.should == false
211
+ end
212
+ end
213
+ end
214
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ module CaChing
4
+ describe WriteThrough do
5
+ before :all do
6
+ @person = Person.where(:id => 1).to_a_without_cache.first
7
+ @cache = CaChing::Adapters::Redis.new
8
+ end
9
+
10
+ before :each do
11
+ @cache.clear!
12
+ end
13
+
14
+ it 'updates the cache for a cached object' do
15
+ ar = Person.where(:id => 1)
16
+ query = CaChing::Query::Abstract.new(ar)
17
+ @cache.insert(ar.to_a_without_cache, :for => query)
18
+
19
+ @person.name = @person.name.reverse
20
+ @person.save
21
+
22
+ @cache.find(CaChing::Query::Abstract.new(ar)).first.name.should == @person.name
23
+ end
24
+ end
25
+ end
data/spec/console.rb ADDED
@@ -0,0 +1,22 @@
1
+ Bundler.setup
2
+ require 'machinist/active_record'
3
+ require 'sham'
4
+ require 'faker'
5
+
6
+ Dir[File.expand_path('../../spec/{helpers,support,blueprints}/*.rb', __FILE__)].each do |f|
7
+ require f
8
+ end
9
+
10
+ Sham.define do
11
+ name { Faker::Name.name }
12
+ title { Faker::Lorem.sentence }
13
+ body { Faker::Lorem.paragraph }
14
+ salary {|index| 30000 + (index * 1000)}
15
+ note { Faker::Lorem.words(7).join(' ') }
16
+ tag_name { Faker::Lorem.words(3).join(' ') }
17
+ end
18
+
19
+ Schema.create unless ENV['SCHEMA'] == 'no'
20
+
21
+ require 'ca_ching'
22
+
@@ -0,0 +1,2 @@
1
+ module CaChingHelper
2
+ end
@@ -0,0 +1,37 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ require 'active_record'
5
+ require 'machinist/active_record'
6
+ require 'sham'
7
+ require 'faker'
8
+
9
+ require 'ca_ching'
10
+
11
+ Dir[File.expand_path('../{helpers,support,blueprints}/*.rb', __FILE__)].each do |f|
12
+ require f
13
+ end
14
+
15
+ Sham.define do
16
+ name { Faker::Name.name }
17
+ title { Faker::Lorem.sentence }
18
+ body { Faker::Lorem.paragraph }
19
+ salary {|index| 30000 + (index * 1000)}
20
+ note { Faker::Lorem.words(7).join(' ') }
21
+ tag_name { Faker::Lorem.words(3).join(' ') }
22
+ end
23
+
24
+ RSpec.configure do |config|
25
+ CaChing.configure do |config|
26
+ config.cache = CaChing::Adapters::Redis.new(:host => 'localhost', :port => 6379)
27
+ config.disabled = true
28
+ end
29
+
30
+ config.before(:suite) do
31
+ Schema.create
32
+ CaChing.disabled = false
33
+ end
34
+
35
+ config.before(:all) { Sham.reset(:before_all) }
36
+ config.before(:each) { Sham.reset(:before_each) }
37
+ end
@@ -0,0 +1,98 @@
1
+ require 'active_record'
2
+ require 'ca_ching'
3
+
4
+ ActiveRecord::Base.establish_connection(
5
+ :adapter => 'sqlite3',
6
+ :database => ':memory:'
7
+ )
8
+
9
+ class Person < ActiveRecord::Base
10
+ belongs_to :parent, :class_name => 'Person', :foreign_key => 'parent_id'
11
+ has_many :children, :class_name => 'Person', :foreign_key => 'parent_id'
12
+
13
+ has_many :articles
14
+ has_many :comments
15
+
16
+ index :id
17
+ index :name
18
+ index :age
19
+ end
20
+
21
+ class Article < ActiveRecord::Base
22
+ belongs_to :person
23
+ has_many :tags
24
+ has_many :comments
25
+
26
+ index :title
27
+ index :person_id
28
+ end
29
+
30
+ class Comment < ActiveRecord::Base
31
+ belongs_to :person
32
+ belongs_to :article
33
+ end
34
+
35
+ class Tag < ActiveRecord::Base
36
+ belongs_to :article
37
+ end
38
+
39
+ module Schema
40
+ def self.create
41
+ ActiveRecord::Base.silence do
42
+ ActiveRecord::Migration.verbose = false
43
+
44
+ ActiveRecord::Schema.define do
45
+ create_table :people, :force => true do |t|
46
+ t.integer :parent_id
47
+ t.string :name
48
+ t.integer :salary
49
+ t.integer :age
50
+
51
+ t.timestamps
52
+ end
53
+
54
+ create_table :articles, :force => true do |t|
55
+ t.integer :person_id
56
+ t.string :title
57
+ t.text :body
58
+
59
+ t.timestamps
60
+ end
61
+
62
+ create_table :comments, :force => true do |t|
63
+ t.integer :article_id
64
+ t.integer :person_id
65
+ t.text :body
66
+
67
+ t.timestamps
68
+ end
69
+
70
+ create_table :tags, :force => true do |t|
71
+ t.integer :article_id
72
+ t.string :name
73
+
74
+ t.timestamps
75
+ end
76
+ end
77
+ end
78
+
79
+ 10.times do
80
+ person = Person.make
81
+ 3.times do
82
+ article = Article.make(:person => person)
83
+ 3.times do
84
+ article.tags = [Tag.make, Tag.make, Tag.make]
85
+ end
86
+ 10.times do
87
+ Comment.make(:article => article)
88
+ end
89
+ end
90
+ 2.times do
91
+ Comment.make(:person => person)
92
+ end
93
+ end
94
+
95
+ Comment.make(:body => 'First post!', :article => Article.make(:title => 'Hello, world!'))
96
+
97
+ end
98
+ end
metadata ADDED
@@ -0,0 +1,150 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ca_ching
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Andrew Latimer
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-10-13 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: hiredis
16
+ requirement: &2155697920 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *2155697920
25
+ - !ruby/object:Gem::Dependency
26
+ name: redis
27
+ requirement: &2155697420 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - =
31
+ - !ruby/object:Gem::Version
32
+ version: 2.2.2
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *2155697420
36
+ - !ruby/object:Gem::Dependency
37
+ name: activesupport
38
+ requirement: &2155696920 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: 3.1.0
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *2155696920
47
+ - !ruby/object:Gem::Dependency
48
+ name: activerecord
49
+ requirement: &2155696440 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: 3.1.0
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: *2155696440
58
+ description: Write-through ActiveRecord model caching that's right on the money
59
+ email:
60
+ - andrew@elpasoera.com
61
+ executables: []
62
+ extensions: []
63
+ extra_rdoc_files: []
64
+ files:
65
+ - .gitignore
66
+ - Gemfile
67
+ - Guardfile
68
+ - LICENSE.txt
69
+ - README.md
70
+ - Rakefile
71
+ - SPEC.md
72
+ - ca_ching.gemspec
73
+ - lib/ca_ching.rb
74
+ - lib/ca_ching/adapters/active_record.rb
75
+ - lib/ca_ching/adapters/redis.rb
76
+ - lib/ca_ching/configuration.rb
77
+ - lib/ca_ching/core_ext/array.rb
78
+ - lib/ca_ching/errors.rb
79
+ - lib/ca_ching/index.rb
80
+ - lib/ca_ching/query/abstract.rb
81
+ - lib/ca_ching/query/calculation.rb
82
+ - lib/ca_ching/query/select.rb
83
+ - lib/ca_ching/read_through.rb
84
+ - lib/ca_ching/version.rb
85
+ - lib/ca_ching/write_through.rb
86
+ - spec/blueprints/articles.rb
87
+ - spec/blueprints/comments.rb
88
+ - spec/blueprints/people.rb
89
+ - spec/blueprints/tags.rb
90
+ - spec/ca_ching/adapters/active_record_spec.rb
91
+ - spec/ca_ching/adapters/redis_spec.rb
92
+ - spec/ca_ching/configuration_spec.rb
93
+ - spec/ca_ching/index_spec.rb
94
+ - spec/ca_ching/query/abstract_spec.rb
95
+ - spec/ca_ching/query/calculation_spec.rb
96
+ - spec/ca_ching/query/select_spec.rb
97
+ - spec/ca_ching/read_through_spec.rb
98
+ - spec/ca_ching/write_through_spec.rb
99
+ - spec/console.rb
100
+ - spec/helpers/ca_ching_helper.rb
101
+ - spec/spec_helper.rb
102
+ - spec/support/schema.rb
103
+ homepage: http://github.com/ahlatimer/ca_ching
104
+ licenses: []
105
+ post_install_message:
106
+ rdoc_options: []
107
+ require_paths:
108
+ - lib
109
+ required_ruby_version: !ruby/object:Gem::Requirement
110
+ none: false
111
+ requirements:
112
+ - - ! '>='
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ segments:
116
+ - 0
117
+ hash: -832901543252096864
118
+ required_rubygems_version: !ruby/object:Gem::Requirement
119
+ none: false
120
+ requirements:
121
+ - - ! '>='
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ segments:
125
+ - 0
126
+ hash: -832901543252096864
127
+ requirements: []
128
+ rubyforge_project: ca_ching
129
+ rubygems_version: 1.8.10
130
+ signing_key:
131
+ specification_version: 3
132
+ summary: Write-through ActiveRecord model caching that's right on the money
133
+ test_files:
134
+ - spec/blueprints/articles.rb
135
+ - spec/blueprints/comments.rb
136
+ - spec/blueprints/people.rb
137
+ - spec/blueprints/tags.rb
138
+ - spec/ca_ching/adapters/active_record_spec.rb
139
+ - spec/ca_ching/adapters/redis_spec.rb
140
+ - spec/ca_ching/configuration_spec.rb
141
+ - spec/ca_ching/index_spec.rb
142
+ - spec/ca_ching/query/abstract_spec.rb
143
+ - spec/ca_ching/query/calculation_spec.rb
144
+ - spec/ca_ching/query/select_spec.rb
145
+ - spec/ca_ching/read_through_spec.rb
146
+ - spec/ca_ching/write_through_spec.rb
147
+ - spec/console.rb
148
+ - spec/helpers/ca_ching_helper.rb
149
+ - spec/spec_helper.rb
150
+ - spec/support/schema.rb