ca_ching 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/.rvmrc ADDED
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # This is an RVM Project .rvmrc file, used to automatically load the ruby
4
+ # development environment upon cd'ing into the directory
5
+
6
+ # First we specify our desired <ruby>[@<gemset>], the @gemset name is optional,
7
+ # Only full ruby name is supported here, for short names use:
8
+ # echo "rvm use 1.9.3" > .rvmrc
9
+ environment_id="ruby-1.9.3-p194@ca_ching"
10
+
11
+ # Uncomment the following lines if you want to verify rvm version per project
12
+ # rvmrc_rvm_version="1.14.5 (stable)" # 1.10.1 seams as a safe start
13
+ # eval "$(echo ${rvm_version}.${rvmrc_rvm_version} | awk -F. '{print "[[ "$1*65536+$2*256+$3" -ge "$4*65536+$5*256+$6" ]]"}' )" || {
14
+ # echo "This .rvmrc file requires at least RVM ${rvmrc_rvm_version}, aborting loading."
15
+ # return 1
16
+ # }
17
+
18
+ # First we attempt to load the desired environment directly from the environment
19
+ # file. This is very fast and efficient compared to running through the entire
20
+ # CLI and selector. If you want feedback on which environment was used then
21
+ # insert the word 'use' after --create as this triggers verbose mode.
22
+ if [[ -d "${rvm_path:-$HOME/.rvm}/environments"
23
+ && -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
24
+ then
25
+ \. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
26
+ [[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]] &&
27
+ \. "${rvm_path:-$HOME/.rvm}/hooks/after_use" || true
28
+ else
29
+ # If the environment file has not yet been created, use the RVM CLI to select.
30
+ rvm --create "$environment_id" || {
31
+ echo "Failed to create RVM environment '${environment_id}'."
32
+ return 1
33
+ }
34
+ fi
35
+
36
+ # If you use bundler, this might be useful to you:
37
+ # if [[ -s Gemfile ]] && {
38
+ # ! builtin command -v bundle >/dev/null ||
39
+ # builtin command -v bundle | GREP_OPTIONS= \grep $rvm_path/bin/bundle >/dev/null
40
+ # }
41
+ # then
42
+ # printf "%b" "The rubygem 'bundler' is not installed. Installing it now.\n"
43
+ # gem install bundler
44
+ # fi
45
+ # if [[ -s Gemfile ]] && builtin command -v bundle >/dev/null
46
+ # then
47
+ # bundle install | GREP_OPTIONS= \grep -vE '^Using|Your bundle is complete'
48
+ # fi
data/Gemfile CHANGED
@@ -3,14 +3,14 @@ source "http://rubygems.org"
3
3
  gemspec
4
4
 
5
5
  # Development gems
6
- gem 'ruby-debug19'
6
+ gem 'debugger'
7
7
  gem 'rake'
8
8
 
9
- gem 'sqlite3'
9
+ gem 'sqlite3', '1.3.5'
10
10
 
11
11
  # Testing
12
12
  gem 'rspec'
13
13
  gem 'machinist'
14
14
  gem 'faker'
15
15
  gem 'guard-rspec'
16
- gem 'growl_notify'
16
+ gem 'growl'
data/README.md CHANGED
@@ -6,7 +6,10 @@ That means that when you read from the database, your results are stored in the
6
6
  the database, whatever is written to the database is also written to the cache (write-through). If the results are already
7
7
  in the cache, great, they're read straight from there on a read, and updated on a write.
8
8
 
9
- Take a look at `SPEC.md` for what's planned for v1.
9
+ This is definitely still alpha-level software. It's just something I thought should exist; I'm not using it in production
10
+ anywhere. It could blow up in totally unexpected, but nevertheless exciting, ways. If it does fall over, [let me know](http://github.com/ahlatimer/ca_ching/issues).
11
+
12
+ Take a look at `SPEC.md` for what's planned for v1.
10
13
 
11
14
  ## Getting started
12
15
 
@@ -50,9 +53,9 @@ miss and pull the data into the cache.
50
53
 
51
54
  ## Queries supported
52
55
 
53
- Generally anything `eqality` is supported by CaChing. Currently, only single fields can be found (e.g., `Person.where(:name => 'Andrew')` will be cached,
56
+ Generally anything involving equality is supported by CaChing. Currently, only single fields can be found (e.g., `Person.where(:name => 'Andrew')` will be cached,
54
57
  `Person.where(:name => 'Andrew', :age => 22)` is not). There is some plumbing for adding support for the latter, and support will be
55
- introduced as soon as possible.
58
+ introduced as soon as possible. I also have plans to add limited support for comparators (i.e., <, <=, >, >=).
56
59
 
57
60
  Anything including joins, includes, `OR`, and inequality (!=) are not supported, nor do I have any plans for adding support.
58
61
 
@@ -75,7 +78,7 @@ These queries are not:
75
78
 
76
79
  ### Order
77
80
 
78
- Order is not currently supported, although there will be some order semantics in the next version.
81
+ Order is not currently supported, although there will be some order functionality in the next version.
79
82
 
80
83
  ### Composite keys and queries against multiple fields
81
84
 
@@ -89,6 +92,12 @@ composite key *is* specified, CaChing will keep the resulting set.
89
92
  While there is support for this in the Redis adapter, there isn't any support in the ActiveRecord ties as I haven't
90
93
  decided how, exactly, I'd like to add this.
91
94
 
95
+ ### Thar be dragons
96
+
97
+ While I've tried to outline the issues here (and write failing specs for them), realize that this is
98
+ still very much alpha software. There are probably a number of unknown unknowns that I just haven't
99
+ uncovered yet. If you find them, please be sure to [let me know](http://github.com/ahlatimer/ca_ching/issues)!
100
+
92
101
  ## Ruby/Rails versions supported
93
102
 
94
103
  Ruby 1.9.2 and Rails 3.1+ are officially supported. I try to stick to Ruby 1.8.7 syntax, so it may be supported,
data/ca_ching.gemspec CHANGED
@@ -20,6 +20,6 @@ Gem::Specification.new do |s|
20
20
 
21
21
  s.add_dependency 'hiredis'
22
22
  s.add_dependency 'redis', '2.2.2'
23
- s.add_dependency 'activesupport', '>= 3.1.0'
24
- s.add_dependency 'activerecord', '>= 3.1.0'
23
+ s.add_dependency 'activesupport', '>= 3.2.0'
24
+ s.add_dependency 'activerecord', '>= 3.2.0'
25
25
  end
data/dump.rdb ADDED
Binary file
@@ -19,10 +19,8 @@ module CaChing
19
19
  end
20
20
  end
21
21
 
22
- module InstanceMethods
23
- def indexed_fields
24
- self.class.indexed_fields
25
- end
22
+ def indexed_fields
23
+ self.class.indexed_fields
26
24
  end
27
25
  end
28
- end
26
+ end
@@ -9,50 +9,49 @@ module CaChing
9
9
  module ClassMethods
10
10
  end
11
11
 
12
- module InstanceMethods
13
- # All queries, be they find(id), dynamic finders (find_by_foo, find_all_by_foo, etc.),
14
- # where(:foo => :bar), order('foo DESC'), etc. go through to_a before being returned.
15
- # Hook into that point to check the cache.
16
- def to_a_with_cache
17
- @_query = CaChing::Query::Select.new(self)
18
-
19
- return to_a_without_cache if CaChing.cache.nil? || CaChing.disabled? || !cacheable?
20
-
21
- result = CaChing.cache.find(@_query)
22
- @from_cache = true
23
-
24
- if result.nil?
25
- result = to_a_without_cache
26
- CaChing.cache.insert(result, :for => @_query)
27
- @from_cache = false
28
- end
29
-
30
- result.from_cache = self.from_cache?
31
- result.each { |item| item.from_cache = self.from_cache? }
32
-
33
- return result
34
- end
12
+ # All queries, be they find(id), dynamic finders (find_by_foo, find_all_by_foo, etc.),
13
+ # where(:foo => :bar), order('foo DESC'), etc. go through to_a before being returned.
14
+ # Hook into that point to check the cache.
15
+ def to_a_with_cache
16
+ @_query = CaChing::Query::Select.new(self)
35
17
 
36
- def from_cache?
37
- @from_cache ||= false
38
- end
18
+ return to_a_without_cache if CaChing.cache.nil? || CaChing.disabled? || !cacheable?
39
19
 
40
- def cacheable?
41
- unsupported_methods = [:from_value,
42
- :group_values,
43
- :having_values,
44
- :includes_values,
45
- :joined_includes_values,
46
- :joins_values,
47
- :lock_value,
48
- :select_values]
49
- !where_values.empty? && find_on_indexed_fields? && unsupported_methods.inject(true) { |flag, method| self.send(method).send(method.to_s =~ /values/ ? :empty? : :nil?) && flag }
50
- end
20
+ result = CaChing.cache.find(@_query)
21
+ @from_cache = true
51
22
 
52
- private
53
- def find_on_indexed_fields?
54
- (@_query.where.keys - indexed_fields.keys).empty?
23
+ if result.nil?
24
+ result = to_a_without_cache
25
+ CaChing.cache.insert(result, :for => @_query)
26
+ @from_cache = false
55
27
  end
28
+
29
+ result.from_cache = self.from_cache?
30
+ result.each { |item| item.from_cache = self.from_cache? }
31
+
32
+ return result
33
+ end
34
+
35
+ def from_cache?
36
+ @from_cache ||= false
37
+ end
38
+
39
+ def cacheable?
40
+ unsupported_methods = [:from_value,
41
+ :group_values,
42
+ :having_values,
43
+ :includes_values,
44
+ :joined_includes_values,
45
+ :joins_values,
46
+ :lock_value,
47
+ :select_values,
48
+ :order_values]
49
+ !where_values.empty? && find_on_indexed_fields? && unsupported_methods.inject(true) { |flag, method| self.send(method).send(method.to_s =~ /values/ ? :empty? : :nil?) && flag }
50
+ end
51
+
52
+ private
53
+ def find_on_indexed_fields?
54
+ (@_query.where.keys - indexed_fields.keys).empty?
56
55
  end
57
56
 
58
57
  included do |base|
@@ -61,4 +60,4 @@ module CaChing
61
60
  end
62
61
  end
63
62
  end
64
- end
63
+ end
@@ -2,7 +2,7 @@ module CaChing
2
2
  module Version
3
3
  MAJOR = 0
4
4
  MINOR = 1
5
- PATCH = 0
5
+ PATCH = 1
6
6
  PRE = nil
7
7
 
8
8
 
@@ -5,19 +5,33 @@ module CaChing
5
5
  module ClassMethods
6
6
  end
7
7
 
8
- module InstanceMethods
9
- def save_with_cache(*)
10
- return save_without_cache if CaChing.cache.nil? || CaChing.disabled?
11
-
12
- CaChing.cache.update(self)
13
- save_without_cache
14
- end
8
+ def save_with_cache(*)
9
+ return save_without_cache if CaChing.cache.nil? || CaChing.disabled?
10
+
11
+ CaChing.cache.update(self)
12
+ save_without_cache
13
+ end
14
+
15
+ def save_with_cache!
16
+ return save_without_cache! if CaChing.cache.nil? || CaChing.disabled?
17
+
18
+ CaChing.cache.update(self)
19
+ save_without_cache!
15
20
  end
16
21
 
22
+ def destroy_with_cache(*)
23
+ return destroy_without_cache if CaChing.cache.nil? || CaChing.disabled?
24
+
25
+ CaChing.cache.destroy(self)
26
+ destroy_without_cache
27
+ end
28
+
17
29
  included do |base|
18
30
  base.class_eval do
19
31
  alias_method_chain :save, :cache
32
+ alias_method_chain :save!, :cache
33
+ alias_method_chain :destroy, :cache
20
34
  end
21
35
  end
22
36
  end
23
- end
37
+ end
@@ -99,7 +99,7 @@ module CaChing
99
99
  it 'handles multiple clauses' do
100
100
  ar = Person.where(:name => 'Andrew', :age => 22)
101
101
  query = Abstract.new(ar)
102
- query.where.should == { :name => ['=', 'Andrew'], :age => ['=', 22] }
102
+ query.where.should == { :name => ['=', 'Andrew'], :age => ['=', '22'] }
103
103
  end
104
104
  end
105
105
  end
@@ -192,4 +192,4 @@ module CaChing
192
192
  end
193
193
  end
194
194
  end
195
- end
195
+ end
@@ -11,15 +11,41 @@ module CaChing
11
11
  @cache.clear!
12
12
  end
13
13
 
14
- it 'updates the cache for a cached object' do
14
+ it 'updates the cache for a cached object with AR#save' do
15
15
  ar = Person.where(:id => 1)
16
16
  query = CaChing::Query::Abstract.new(ar)
17
17
  @cache.insert(ar.to_a_without_cache, :for => query)
18
18
 
19
- @person.name = @person.name.reverse
19
+ name = @person.name.reverse
20
+
21
+ @person.name = name
20
22
  @person.save
21
23
 
22
- @cache.find(CaChing::Query::Abstract.new(ar)).first.name.should == @person.name
24
+ @cache.find(CaChing::Query::Abstract.new(ar)).first.name.should == name
25
+ end
26
+
27
+ it 'updates the cache for a cached object with AR#save!' do
28
+ ar = Person.where(:id => 1)
29
+ query = CaChing::Query::Abstract.new(ar)
30
+ @cache.insert(ar.to_a_without_cache, :for => query)
31
+
32
+ name = @person.name.reverse
33
+
34
+ @person.name = name
35
+ @person.save!
36
+
37
+ @cache.find(CaChing::Query::Abstract.new(ar)).first.name.should == name
38
+ end
39
+
40
+ it 'updates the cache for a cached object with AR#update_attributes' do
41
+ ar = Person.where(:id => 1)
42
+ query = CaChing::Query::Abstract.new(ar)
43
+ @cache.insert(ar.to_a_without_cache, :for => query)
44
+
45
+ name = @person.name.reverse
46
+ @person.update_attributes(:name => name)
47
+
48
+ @cache.find(CaChing::Query::Abstract.new(ar)).first.name.should == name
23
49
  end
24
50
  end
25
51
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ca_ching
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-10-13 00:00:00.000000000Z
12
+ date: 2013-03-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: hiredis
16
- requirement: &2155697920 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,40 +21,60 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2155697920
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: redis
27
- requirement: &2155697420 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
- - - =
35
+ - - '='
31
36
  - !ruby/object:Gem::Version
32
37
  version: 2.2.2
33
38
  type: :runtime
34
39
  prerelease: false
35
- version_requirements: *2155697420
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - '='
44
+ - !ruby/object:Gem::Version
45
+ version: 2.2.2
36
46
  - !ruby/object:Gem::Dependency
37
47
  name: activesupport
38
- requirement: &2155696920 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
39
49
  none: false
40
50
  requirements:
41
51
  - - ! '>='
42
52
  - !ruby/object:Gem::Version
43
- version: 3.1.0
53
+ version: 3.2.0
44
54
  type: :runtime
45
55
  prerelease: false
46
- version_requirements: *2155696920
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 3.2.0
47
62
  - !ruby/object:Gem::Dependency
48
63
  name: activerecord
49
- requirement: &2155696440 !ruby/object:Gem::Requirement
64
+ requirement: !ruby/object:Gem::Requirement
50
65
  none: false
51
66
  requirements:
52
67
  - - ! '>='
53
68
  - !ruby/object:Gem::Version
54
- version: 3.1.0
69
+ version: 3.2.0
55
70
  type: :runtime
56
71
  prerelease: false
57
- version_requirements: *2155696440
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: 3.2.0
58
78
  description: Write-through ActiveRecord model caching that's right on the money
59
79
  email:
60
80
  - andrew@elpasoera.com
@@ -63,6 +83,7 @@ extensions: []
63
83
  extra_rdoc_files: []
64
84
  files:
65
85
  - .gitignore
86
+ - .rvmrc
66
87
  - Gemfile
67
88
  - Guardfile
68
89
  - LICENSE.txt
@@ -70,6 +91,7 @@ files:
70
91
  - Rakefile
71
92
  - SPEC.md
72
93
  - ca_ching.gemspec
94
+ - dump.rdb
73
95
  - lib/ca_ching.rb
74
96
  - lib/ca_ching/adapters/active_record.rb
75
97
  - lib/ca_ching/adapters/redis.rb
@@ -114,7 +136,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
114
136
  version: '0'
115
137
  segments:
116
138
  - 0
117
- hash: -832901543252096864
139
+ hash: 3771213621582903175
118
140
  required_rubygems_version: !ruby/object:Gem::Requirement
119
141
  none: false
120
142
  requirements:
@@ -123,10 +145,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
123
145
  version: '0'
124
146
  segments:
125
147
  - 0
126
- hash: -832901543252096864
148
+ hash: 3771213621582903175
127
149
  requirements: []
128
150
  rubyforge_project: ca_ching
129
- rubygems_version: 1.8.10
151
+ rubygems_version: 1.8.24
130
152
  signing_key:
131
153
  specification_version: 3
132
154
  summary: Write-through ActiveRecord model caching that's right on the money