kasket 0.6.4 → 0.7.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.
data/lib/kasket.rb CHANGED
@@ -5,7 +5,6 @@ require 'active_support'
5
5
  require 'kasket/active_record_patches'
6
6
 
7
7
  module Kasket
8
- autoload :Cache, 'kasket/cache'
9
8
  autoload :ConfigurationMixin, 'kasket/configuration_mixin'
10
9
  autoload :ReloadAssociationMixin, 'kasket/reload_association_mixin'
11
10
  autoload :RackMiddleware, 'kasket/rack_middleware'
@@ -15,17 +14,13 @@ module Kasket
15
14
 
16
15
  class Version
17
16
  MAJOR = 0
18
- MINOR = 6
19
- PATCH = 4
17
+ MINOR = 7
18
+ PATCH = 0
20
19
  STRING = "#{MAJOR}.#{MINOR}.#{PATCH}"
21
20
  end
22
21
 
23
22
  module_function
24
23
 
25
- def cache
26
- Thread.current["kasket_cache"] ||= Cache.new
27
- end
28
-
29
24
  def setup(options = {})
30
25
  CONFIGURATION[:max_collection_size] = options[:max_collection_size] if options[:max_collection_size]
31
26
 
@@ -33,34 +28,11 @@ module Kasket
33
28
  ActiveRecord::Associations::BelongsToAssociation.send(:include, Kasket::ReloadAssociationMixin)
34
29
  ActiveRecord::Associations::BelongsToPolymorphicAssociation.send(:include, Kasket::ReloadAssociationMixin)
35
30
  ActiveRecord::Associations::HasOneThroughAssociation.send(:include, Kasket::ReloadAssociationMixin)
31
+ end
36
32
 
37
- #sets up local cache clearing before each request.
38
- #this is done to make it work for non rack rails and for functional tests
39
- begin
40
- ApplicationController.before_filter do
41
- Kasket.cache.clear_local
42
- end
43
- rescue NameError => e
44
- puts('WARNING: The kasket before filter did not register (this is OK in the test environment)')
45
- end
46
-
47
- #sets up local cache clearing on rack
48
- begin
49
- ActionController::Dispatcher.middleware.use(Kasket::RackMiddleware)
50
- rescue NameError => e
51
- puts('WARNING: The kasket rack middleware is not in your rack stack (this is OK in the test environment)')
52
- end
53
-
54
- #sets up local cache clearing after each test case
55
- begin
56
- ActiveSupport::TestCase.class_eval do
57
- setup :clear_cache
58
- def clear_cache
59
- Kasket.cache.clear_local
60
- Rails.cache.clear if Rails.cache.respond_to?(:clear)
61
- end
62
- end
63
- rescue NameError => e
33
+ def clear_local
34
+ if Rails.cache.respond_to?(:with_local_cache)
35
+ Rails.cache.send(:local_cache).try(:clear)
64
36
  end
65
37
  end
66
38
  end
@@ -11,8 +11,8 @@ module Kasket
11
11
  sql = sanitize_sql(sql)
12
12
  query = kasket_parser.parse(sql) if use_kasket?
13
13
  if query && has_kasket_index_on?(query[:index])
14
- if value = Kasket.cache.read(query[:key])
15
- Array.wrap(value).collect! { |record| instantiate(record.clone) }
14
+ if value = Rails.cache.read(query[:key])
15
+ Array.wrap(value).collect! { |record| instantiate(record.dup) }
16
16
  else
17
17
  store_in_kasket(query[:key], find_by_sql_without_kasket(sql))
18
18
  end
@@ -25,14 +25,14 @@ module Kasket
25
25
 
26
26
  def store_in_kasket(key, records)
27
27
  if records.size == 1
28
- Kasket.cache.write(key, records.first.instance_variable_get(:@attributes))
29
- else
28
+ Rails.cache.write(key, records.first.instance_variable_get(:@attributes).dup)
29
+ elsif records.size <= Kasket::CONFIGURATION[:max_collection_size]
30
30
  keys = records.map do |record|
31
31
  key = kasket_key_for_id(record.id)
32
- Kasket.cache.write(key, record.instance_variable_get(:@attributes))
32
+ Rails.cache.write(key, record.instance_variable_get(:@attributes).dup)
33
33
  key
34
34
  end
35
- Kasket.cache.write(key, keys)
35
+ Rails.cache.write(key, keys)
36
36
  end
37
37
  records
38
38
  end
@@ -2,7 +2,7 @@ module Kasket
2
2
  module ReloadAssociationMixin
3
3
  def reload_with_kasket_clearing(*args)
4
4
  if loaded?
5
- clear_local_kasket_indices if respond_to?(:clear_local_kasket_indices)
5
+ Kasket.clear_local if include?(WriteMixin)
6
6
  else
7
7
  target_class = proxy_reflection.options[:polymorphic] ? association_class : proxy_reflection.klass
8
8
  Kasket.cache.delete_matched_local(/^#{target_class.kasket_key_prefix}/) if target_class.respond_to?(:kasket_key_prefix)
@@ -4,7 +4,7 @@ module Kasket
4
4
  module ClassMethods
5
5
  def remove_from_kasket(ids)
6
6
  Array(ids).each do |id|
7
- Kasket.cache.delete(kasket_key_for_id(id))
7
+ Rails.cache.delete(kasket_key_for_id(id))
8
8
  end
9
9
  end
10
10
 
@@ -21,7 +21,7 @@ module Kasket
21
21
 
22
22
  def store_in_kasket
23
23
  if !readonly? && kasket_key
24
- Kasket.cache.write(kasket_key, @attributes)
24
+ Rails.cache.write(kasket_key, @attributes.dup)
25
25
  end
26
26
  end
27
27
 
@@ -48,18 +48,12 @@ module Kasket
48
48
 
49
49
  def clear_kasket_indices
50
50
  kasket_keys.each do |key|
51
- Kasket.cache.delete(key)
52
- end
53
- end
54
-
55
- def clear_local_kasket_indices
56
- kasket_keys.each do |key|
57
- Kasket.cache.delete_local(key)
51
+ Rails.cache.delete(key)
58
52
  end
59
53
  end
60
54
 
61
55
  def reload_with_kasket_clearing(*args)
62
- clear_local_kasket_indices
56
+ Kasket.clear_local
63
57
  reload_without_kasket_clearing(*args)
64
58
  end
65
59
  end
@@ -17,11 +17,11 @@ class CacheExpiryTest < ActiveSupport::TestCase
17
17
  end
18
18
 
19
19
  should "clear all indices for instance when deleted" do
20
- Kasket.cache.expects(:delete).with(Post.kasket_key_prefix + "id=#{@post.id}")
21
- Kasket.cache.expects(:delete).with(Post.kasket_key_prefix + "title='#{@post.title}'")
22
- Kasket.cache.expects(:delete).with(Post.kasket_key_prefix + "title='#{@post.title}'/first")
23
- Kasket.cache.expects(:delete).with(Post.kasket_key_prefix + "blog_id=#{@post.blog_id}/id=#{@post.id}")
24
- Kasket.cache.expects(:delete).never
20
+ Rails.cache.expects(:delete).with(Post.kasket_key_prefix + "id=#{@post.id}")
21
+ Rails.cache.expects(:delete).with(Post.kasket_key_prefix + "title='#{@post.title}'")
22
+ Rails.cache.expects(:delete).with(Post.kasket_key_prefix + "title='#{@post.title}'/first")
23
+ Rails.cache.expects(:delete).with(Post.kasket_key_prefix + "blog_id=#{@post.blog_id}/id=#{@post.id}")
24
+ Rails.cache.expects(:delete).never
25
25
 
26
26
  @post.destroy
27
27
  end
@@ -33,13 +33,13 @@ class CacheExpiryTest < ActiveSupport::TestCase
33
33
  end
34
34
 
35
35
  should "clear all indices for instance when updated" do
36
- Kasket.cache.expects(:delete).with(Post.kasket_key_prefix + "id=#{@post.id}")
37
- Kasket.cache.expects(:delete).with(Post.kasket_key_prefix + "title='#{@post.title}'")
38
- Kasket.cache.expects(:delete).with(Post.kasket_key_prefix + "title='#{@post.title}'/first")
39
- Kasket.cache.expects(:delete).with(Post.kasket_key_prefix + "title='new title'")
40
- Kasket.cache.expects(:delete).with(Post.kasket_key_prefix + "title='new title'/first")
41
- Kasket.cache.expects(:delete).with(Post.kasket_key_prefix + "blog_id=#{@post.blog_id}/id=#{@post.id}")
42
- Kasket.cache.expects(:delete).never
36
+ Rails.cache.expects(:delete).with(Post.kasket_key_prefix + "id=#{@post.id}")
37
+ Rails.cache.expects(:delete).with(Post.kasket_key_prefix + "title='#{@post.title}'")
38
+ Rails.cache.expects(:delete).with(Post.kasket_key_prefix + "title='#{@post.title}'/first")
39
+ Rails.cache.expects(:delete).with(Post.kasket_key_prefix + "title='new title'")
40
+ Rails.cache.expects(:delete).with(Post.kasket_key_prefix + "title='new title'/first")
41
+ Rails.cache.expects(:delete).with(Post.kasket_key_prefix + "blog_id=#{@post.blog_id}/id=#{@post.id}")
42
+ Rails.cache.expects(:delete).never
43
43
 
44
44
  @post.title = "new title"
45
45
  @post.save
@@ -13,11 +13,11 @@ class FindOneTest < ActiveSupport::TestCase
13
13
  end
14
14
 
15
15
  should "only cache on indexed attributes" do
16
- Kasket.cache.expects(:read).twice
16
+ Rails.cache.expects(:read).twice
17
17
  Post.find_by_id(1)
18
18
  Post.find_by_id(1, :conditions => {:blog_id => 2})
19
19
 
20
- Kasket.cache.expects(:read).never
20
+ Rails.cache.expects(:read).never
21
21
  Post.first :conditions => {:blog_id => 2}
22
22
  end
23
23
 
@@ -31,10 +31,10 @@ class FindOneTest < ActiveSupport::TestCase
31
31
  Post.find(post.id)
32
32
  assert(Rails.cache.read(post.kasket_key))
33
33
 
34
- Kasket.cache.expects(:read)
34
+ Rails.cache.expects(:read)
35
35
  Post.find(post.id, :select => nil)
36
36
 
37
- Kasket.cache.expects(:read).never
37
+ Rails.cache.expects(:read).never
38
38
  Post.find(post.id, :select => 'title')
39
39
  end
40
40
 
data/test/helper.rb CHANGED
@@ -34,6 +34,11 @@ class ActiveSupport::TestCase
34
34
  self.use_transactional_fixtures = true
35
35
 
36
36
  self.use_instantiated_fixtures = false
37
+
38
+ setup :clear_cache
39
+ def clear_cache
40
+ Rails.cache.clear
41
+ end
37
42
  end
38
43
 
39
44
  ActiveSupport::TestCase.fixture_path = File.dirname(__FILE__) + "/fixtures/"
@@ -10,24 +10,25 @@ class ReadMixinTest < ActiveSupport::TestCase
10
10
  end
11
11
 
12
12
  should "handle unsupported sql" do
13
+ Rails.cache.expects(:read).never
14
+ Rails.cache.expects(:write).never
13
15
  assert_equal @records, Post.find_by_sql_with_kasket('select unsupported sql statement')
14
- assert Kasket.cache.local.empty?
15
16
  end
16
17
 
17
18
  should "read results" do
18
- Kasket.cache.write("kasket-#{Kasket::Version::STRING}/posts/version=3558/id=1", @database_results.first)
19
- assert_equal [ @records.first ], Post.find_by_sql('SELECT * FROM `posts` WHERE (id = 1)'), Kasket.cache.inspect
19
+ Rails.cache.write("kasket-#{Kasket::Version::STRING}/posts/version=3558/id=1", @database_results.first)
20
+ assert_equal [ @records.first ], Post.find_by_sql('SELECT * FROM `posts` WHERE (id = 1)')
20
21
  end
21
22
 
22
23
  should "store results in kasket" do
23
24
  Post.find_by_sql('SELECT * FROM `posts` WHERE (id = 1)')
24
25
 
25
- assert_equal @database_results.first, Kasket.cache.read("kasket-#{Kasket::Version::STRING}/posts/version=3558/id=1"), Kasket.cache.inspect
26
+ assert_equal @database_results.first, Rails.cache.read("kasket-#{Kasket::Version::STRING}/posts/version=3558/id=1")
26
27
  end
27
28
 
28
29
  context "modifying results" do
29
30
  setup do
30
- Kasket.cache.write("kasket-#{Kasket::Version::STRING}/posts/version=3558/id=1", @database_results.first)
31
+ Rails.cache.write("kasket-#{Kasket::Version::STRING}/posts/version=3558/id=1", @database_results.first)
31
32
  @record = Post.find_by_sql('SELECT * FROM `posts` WHERE (id = 1)').first
32
33
  @record.instance_variable_get(:@attributes)['id'] = 3
33
34
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kasket
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.4
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mick Staugaard
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2009-12-09 00:00:00 -08:00
13
+ date: 2010-01-04 00:00:00 +01:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -70,16 +70,13 @@ files:
70
70
  - Rakefile
71
71
  - lib/kasket.rb
72
72
  - lib/kasket/active_record_patches.rb
73
- - lib/kasket/cache.rb
74
73
  - lib/kasket/configuration_mixin.rb
75
74
  - lib/kasket/dirty_mixin.rb
76
75
  - lib/kasket/query_parser.rb
77
- - lib/kasket/rack_middleware.rb
78
76
  - lib/kasket/read_mixin.rb
79
77
  - lib/kasket/reload_association_mixin.rb
80
78
  - lib/kasket/write_mixin.rb
81
79
  - test/cache_expiry_test.rb
82
- - test/cache_test.rb
83
80
  - test/database.yml
84
81
  - test/dirty_test.rb
85
82
  - test/find_one_test.rb
@@ -121,7 +118,6 @@ specification_version: 3
121
118
  summary: A write back caching layer on active record
122
119
  test_files:
123
120
  - test/cache_expiry_test.rb
124
- - test/cache_test.rb
125
121
  - test/dirty_test.rb
126
122
  - test/find_one_test.rb
127
123
  - test/find_some_test.rb
data/lib/kasket/cache.rb DELETED
@@ -1,77 +0,0 @@
1
- module Kasket
2
- class Cache
3
- def initialize
4
- clear_local
5
- end
6
-
7
- def read(*args)
8
- result = @local_cache[args[0]] || Rails.cache.read(*args)
9
- if result.is_a?(Array) && result.first.is_a?(String)
10
- models = get_multi(result)
11
- result = result.map { |key| models[key] }
12
- end
13
-
14
- @local_cache[args[0]] = result if result
15
- result
16
- end
17
-
18
- def get_multi(keys)
19
- map = Hash[*keys.zip(keys.map { |key| @local_cache[key] }).flatten]
20
- missing_keys = map.select { |key, value| value.nil? }.map(&:first)
21
-
22
- unless missing_keys.empty?
23
- if Rails.cache.respond_to?(:read_multi)
24
- missing_map = Rails.cache.read_multi(missing_keys)
25
- missing_map.each do |key, value|
26
- missing_map[key] = @local_cache[key] = value
27
- end
28
- map.merge!(missing_map)
29
- else
30
- missing_keys.each do |key|
31
- map[key] = read(key)
32
- end
33
- end
34
- end
35
-
36
- map
37
- end
38
-
39
- def write(key, value)
40
- if storable?(value)
41
- @local_cache[key] = value.duplicable? ? value.dup : value
42
- Rails.cache.write(key, value.duplicable? ? value.dup : value) # Fix due to Rails.cache freezing values in 2.3.4
43
- end
44
- value
45
- end
46
-
47
- def delete(*args)
48
- @local_cache.delete(args[0])
49
- Rails.cache.delete(*args)
50
- end
51
-
52
- def delete_local(*keys)
53
- keys.each do |key|
54
- @local_cache.delete(key)
55
- end
56
- end
57
-
58
- def delete_matched_local(matcher)
59
- @local_cache.delete_if { |k,v| k =~ matcher }
60
- end
61
-
62
- def clear_local
63
- @local_cache = {}
64
- end
65
-
66
- def local
67
- @local_cache
68
- end
69
-
70
- protected
71
-
72
- def storable?(value)
73
- !value.is_a?(Array) || value.size <= Kasket::CONFIGURATION[:max_collection_size]
74
- end
75
-
76
- end
77
- end
@@ -1,13 +0,0 @@
1
- module Kasket
2
- class RackMiddleware
3
- def initialize(app)
4
- @app = app
5
- end
6
-
7
- def call(env)
8
- @app.call(env)
9
- ensure
10
- Kasket.cache.clear_local
11
- end
12
- end
13
- end
data/test/cache_test.rb DELETED
@@ -1,102 +0,0 @@
1
- require File.dirname(__FILE__) + '/helper'
2
-
3
- class CacheTest < ActiveSupport::TestCase
4
-
5
- context "Cache" do
6
- setup do
7
- @cache = Kasket::Cache.new
8
- end
9
-
10
- context "reading" do
11
-
12
- should "work with non collection values" do
13
- @cache.write('key', 'value')
14
- assert_equal 'value', @cache.read('key')
15
- end
16
-
17
- should "fetch original results of stored collections" do
18
- @cache.write('key1', 'value1')
19
- @cache.write('key2', 'value2')
20
- @cache.write('key3', 'value3')
21
- @cache.write('collection_key', [ 'key1', 'key2', 'key3'])
22
-
23
- assert_equal [ 'value1', 'value2', 'value3'], @cache.read('collection_key')
24
- end
25
-
26
- should "not impact original object" do
27
- record = { 'id' => 1, 'color' => 'red' }
28
- @cache.write('key', record)
29
- record['id'] = 2
30
-
31
- assert_not_equal record, @cache.read('key')
32
- end
33
-
34
- end
35
-
36
- context "writing" do
37
- setup do
38
- @cache.write('key', 'value')
39
- end
40
-
41
- should "store the object locally" do
42
- assert_equal 'value', @cache.local['key']
43
- end
44
-
45
- should "persist the object" do
46
- @cache.clear_local
47
- assert_equal 'value', @cache.read('key')
48
- end
49
-
50
- should "respect max collection size" do
51
- original_max = Kasket::CONFIGURATION[:max_collection_size]
52
- Kasket::CONFIGURATION[:max_collection_size] = 2
53
-
54
- @cache.write('key', [ 'a', 'b'])
55
- assert_equal 2, @cache.read('key').size
56
-
57
- @cache.write('key2', ['a', 'b', 'c'])
58
- assert_equal nil, @cache.read('key2')
59
-
60
- Kasket::CONFIGURATION[:max_collection_size] = original_max
61
- end
62
-
63
- end
64
-
65
- should "delete" do
66
- @cache.write('key', 'value')
67
- @cache.delete('key')
68
-
69
- assert_equal nil, @cache.local['key']
70
- assert_equal nil, @cache.read('key')
71
- end
72
-
73
- should "delete matched local" do
74
- @cache.write('key1', 'value1')
75
- @cache.write('key2', 'value2')
76
- @cache.delete_matched_local(/2/)
77
-
78
- assert_equal nil, @cache.local['key2']
79
- assert_equal 'value1', @cache.local['key1']
80
- assert_equal 'value2', @cache.read('key2')
81
- end
82
-
83
- should "delete local" do
84
- @cache.write('key1', 'value1')
85
- @cache.write('key2', 'value2')
86
- @cache.delete_local('key1', 'key2')
87
-
88
- assert_equal nil, @cache.local['key1']
89
- assert_equal nil, @cache.local['key2']
90
- assert_equal 'value1', @cache.read('key1')
91
- assert_equal 'value2', @cache.read('key2')
92
- end
93
-
94
- should "clear local" do
95
- @cache.write('key1', 'value1')
96
- @cache.clear_local
97
-
98
- assert @cache.local.blank?
99
- end
100
-
101
- end
102
- end