cache_back 0.5.0 → 0.5.1
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/VERSION +1 -1
- data/lib/cache_back.rb +0 -1
- data/lib/cache_back/cache.rb +6 -0
- data/lib/cache_back/conditions_parser.rb +45 -38
- data/lib/cache_back/configuration_mixin.rb +4 -33
- data/lib/cache_back/dirty_mixin.rb +2 -0
- data/lib/cache_back/read_mixin.rb +2 -3
- data/lib/cache_back/reload_association_mixin.rb +2 -3
- data/lib/cache_back/write_mixin.rb +19 -5
- data/test/cache_expiry_test.rb +14 -14
- metadata +2 -3
- data/lib/cache_back/rack_middleware.rb +0 -13
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.5.
|
1
|
+
0.5.1
|
data/lib/cache_back.rb
CHANGED
data/lib/cache_back/cache.rb
CHANGED
@@ -4,57 +4,64 @@ module CacheBack
|
|
4
4
|
@model_class = model_class
|
5
5
|
end
|
6
6
|
|
7
|
-
def attribute_value_pairs(options
|
8
|
-
|
9
|
-
|
7
|
+
def attribute_value_pairs(options)
|
8
|
+
#pulls out the conditions from each hash
|
9
|
+
condition_fragments = [options[:conditions]]
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
pairs = from_scope.inject(from_options) do |memo, pair|
|
15
|
-
attribute = pair[0]
|
16
|
-
if memo_pair = memo.find{ |p| p[0] == attribute}
|
17
|
-
memo_pair[0] = Array(memo_pair[0])
|
18
|
-
memo_pair[0] << pair[1]
|
19
|
-
else
|
20
|
-
memo << pair
|
21
|
-
end
|
11
|
+
#add the scope to the mix
|
12
|
+
if scope = @model_class.send(:scope, :find)
|
13
|
+
condition_fragments << scope[:conditions]
|
22
14
|
end
|
23
15
|
|
24
|
-
|
16
|
+
#add the type if we are on STI
|
17
|
+
condition_fragments << {:type => @model_class.name} if @model_class.finder_needs_type_condition?
|
25
18
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
19
|
+
condition_fragments.compact!
|
20
|
+
|
21
|
+
#parses each conditions fragment but bails if one of the did not parse
|
22
|
+
attributes_fragments = condition_fragments.map do |condition_fragment|
|
23
|
+
attributes_fragment = attributes_for_conditions(condition_fragment)
|
24
|
+
return nil unless attributes_fragment
|
25
|
+
attributes_fragment
|
26
|
+
end
|
27
|
+
|
28
|
+
#merges the hashes but bails if there is an overlap
|
29
|
+
attributes = attributes_fragments.inject({}) do |memo, attributes_fragment|
|
30
|
+
attributes_fragment.each do |attribute, value|
|
31
|
+
return nil if memo.has_key?(attribute)
|
32
|
+
memo[attribute] = value
|
36
33
|
end
|
34
|
+
memo
|
37
35
|
end
|
36
|
+
|
37
|
+
attributes.keys.sort.map { |attribute| [attribute.to_sym, attributes[attribute]] }
|
38
38
|
end
|
39
39
|
|
40
|
-
def
|
41
|
-
case conditions
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
40
|
+
def attributes_for_conditions(conditions)
|
41
|
+
pairs = case conditions
|
42
|
+
when Hash
|
43
|
+
return conditions.stringify_keys
|
44
|
+
when String
|
45
|
+
parse_indices_from_condition(conditions)
|
46
|
+
when Array
|
47
|
+
parse_indices_from_condition(*conditions)
|
48
|
+
when NilClass
|
49
|
+
[]
|
50
|
+
end
|
51
|
+
|
52
|
+
return nil unless pairs
|
53
|
+
|
54
|
+
pairs.inject({}) do |memo, pair|
|
55
|
+
return nil if memo.has_key?(pair[0])
|
56
|
+
memo[pair[0]] = pair[1]
|
57
|
+
memo
|
50
58
|
end
|
51
59
|
end
|
52
60
|
|
53
61
|
AND = /\s+AND\s+/i
|
54
62
|
TABLE_AND_COLUMN = /(?:(?:`|")?(\w+)(?:`|")?\.)?(?:`|")?(\w+)(?:`|")?/ # Matches: `users`.id, `users`.`id`, users.id, id
|
55
63
|
VALUE = /'?(\d+|\?|(?:(?:[^']|'')*))'?/ # Matches: 123, ?, '123', '12''3'
|
56
|
-
KEY_EQ_VALUE =
|
57
|
-
ORDER = /^#{TABLE_AND_COLUMN}\s*(ASC|DESC)?$/i # Matches: COLUMN ASC, COLUMN DESC, COLUMN
|
64
|
+
KEY_EQ_VALUE = /^[\(\s]*#{TABLE_AND_COLUMN}\s+=\s+#{VALUE}[\)\s]*$/ # Matches: KEY = VALUE, (KEY = VALUE), ()(KEY = VALUE))
|
58
65
|
|
59
66
|
def parse_indices_from_condition(conditions = '', *values)
|
60
67
|
values = values.dup
|
@@ -69,4 +76,4 @@ module CacheBack
|
|
69
76
|
end
|
70
77
|
end
|
71
78
|
end
|
72
|
-
end
|
79
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'active_support'
|
2
|
+
require 'zlib'
|
2
3
|
|
3
4
|
module CacheBack
|
4
5
|
autoload :ReadMixin, 'cache_back/read_mixin'
|
@@ -6,37 +7,12 @@ module CacheBack
|
|
6
7
|
autoload :DirtyMixin, 'cache_back/dirty_mixin'
|
7
8
|
|
8
9
|
module ConfigurationMixin
|
9
|
-
def
|
10
|
-
@
|
11
|
-
end
|
12
|
-
|
13
|
-
def inherited_cache_back_version
|
14
|
-
if self == ActiveRecord::Base
|
15
|
-
@cache_back_version
|
16
|
-
else
|
17
|
-
@cache_back_version ||= superclass.inherited_cache_back_version
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def inherited_cache_back_options
|
22
|
-
if self == ActiveRecord::Base
|
23
|
-
@cache_back_option
|
24
|
-
else
|
25
|
-
@cache_back_option ||= superclass.inherited_cache_back_options
|
26
|
-
end
|
10
|
+
def cache_back_key_prefix
|
11
|
+
@cache_back_key_prefix ||= "cache_back/#{table_name}/version=#{Zlib.crc32(column_names.sort.join)}/"
|
27
12
|
end
|
28
13
|
|
29
14
|
def cache_back_key_for(attribute_value_pairs)
|
30
|
-
|
31
|
-
attribute_value_pairs.each do |attribute, value|
|
32
|
-
key << "/#{attribute}="
|
33
|
-
if value.is_a?(Array)
|
34
|
-
key << value.join(',')
|
35
|
-
else
|
36
|
-
key << value.to_s
|
37
|
-
end
|
38
|
-
end
|
39
|
-
key
|
15
|
+
cache_back_key_prefix + attribute_value_pairs.map {|attribute, value| attribute.to_s + '=' + value.to_s}.join('/')
|
40
16
|
end
|
41
17
|
|
42
18
|
def cache_back_key_for_id(id)
|
@@ -58,12 +34,7 @@ module CacheBack
|
|
58
34
|
end
|
59
35
|
|
60
36
|
def has_cache_back_on(*args)
|
61
|
-
options = args.extract_options!
|
62
37
|
attributes = args.sort! { |x, y| x.to_s <=> y.to_s }
|
63
|
-
|
64
|
-
@cache_back_version ||= options.delete(:version) || '1'
|
65
|
-
@cache_back_option ||= options
|
66
|
-
|
67
38
|
if attributes != [:id] && !cache_back_indices.include?([:id])
|
68
39
|
has_cache_back_on(:id)
|
69
40
|
end
|
@@ -19,7 +19,7 @@ module CacheBack
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def find_every_with_cache_back(options)
|
22
|
-
attribute_value_pairs = cache_back_conditions_parser.attribute_value_pairs(options
|
22
|
+
attribute_value_pairs = cache_back_conditions_parser.attribute_value_pairs(options) if cache_safe?(options)
|
23
23
|
|
24
24
|
limit = (options[:limit] || (scope(:find) || {})[:limit])
|
25
25
|
|
@@ -48,7 +48,7 @@ module CacheBack
|
|
48
48
|
end
|
49
49
|
|
50
50
|
def find_some_with_cache_back(ids, options)
|
51
|
-
attribute_value_pairs = cache_back_conditions_parser.attribute_value_pairs(options
|
51
|
+
attribute_value_pairs = cache_back_conditions_parser.attribute_value_pairs(options) if cache_safe?(options)
|
52
52
|
attribute_value_pairs << [:id, ids] if attribute_value_pairs
|
53
53
|
|
54
54
|
limit = (options[:limit] || (scope(:find) || {})[:limit])
|
@@ -88,6 +88,5 @@ module CacheBack
|
|
88
88
|
def cache_back_conditions_parser
|
89
89
|
@cache_back_conditions_parser ||= CacheBack::ConditionsParser.new(self)
|
90
90
|
end
|
91
|
-
|
92
91
|
end
|
93
92
|
end
|
@@ -2,9 +2,8 @@ module CacheBack
|
|
2
2
|
module ReloadAssociationMixin
|
3
3
|
def reload_with_cache_back_clearing(*args)
|
4
4
|
# TODO we could calculate the right key to clear by parsing the association conditions.
|
5
|
-
# this would clear less keys
|
6
|
-
|
7
|
-
target.clear_cache_back_indices if target.respond_to?(:clear_cache_back_indices)
|
5
|
+
# this would clear less keys
|
6
|
+
CacheBack.cache.reset!
|
8
7
|
reload_without_cache_back_clearing(*args)
|
9
8
|
end
|
10
9
|
|
@@ -20,29 +20,43 @@ module CacheBack
|
|
20
20
|
|
21
21
|
def store_in_cache_back
|
22
22
|
if !readonly? && cache_back_key
|
23
|
-
CacheBack.cache.write(cache_back_key, self
|
23
|
+
CacheBack.cache.write(cache_back_key, self)
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
def
|
27
|
+
def cache_back_keys
|
28
28
|
new_attributes = attributes.symbolize_keys
|
29
29
|
|
30
30
|
old_attributes = Hash[changes.map {|attribute, values| [attribute, values[0]]}].symbolize_keys
|
31
31
|
old_attributes.reverse_merge!(new_attributes)
|
32
32
|
|
33
|
+
keys = []
|
33
34
|
self.class.cache_back_indices.each do |index|
|
34
35
|
old_key = self.class.cache_back_key_for(index.map { |attribute| [attribute, old_attributes[attribute]]})
|
35
36
|
new_key = self.class.cache_back_key_for(index.map { |attribute| [attribute, new_attributes[attribute]]})
|
36
37
|
|
37
38
|
[old_key, new_key].uniq.each do |key|
|
38
|
-
|
39
|
-
|
39
|
+
keys << key
|
40
|
+
keys << "#{key}/first"
|
40
41
|
end
|
41
42
|
end
|
43
|
+
keys
|
44
|
+
end
|
45
|
+
|
46
|
+
def clear_cache_back_indices
|
47
|
+
cache_back_keys.each do |key|
|
48
|
+
CacheBack.cache.delete(key)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def clear_local_cache_back_indices
|
53
|
+
cache_back_keys.each do |key|
|
54
|
+
CacheBack.cache.delete_local(key)
|
55
|
+
end
|
42
56
|
end
|
43
57
|
|
44
58
|
def reload_with_cache_back_clearing(*args)
|
45
|
-
|
59
|
+
clear_local_cache_back_indices
|
46
60
|
reload_without_cache_back_clearing(*args)
|
47
61
|
end
|
48
62
|
end
|
data/test/cache_expiry_test.rb
CHANGED
@@ -20,12 +20,12 @@ class CacheExpiryTest < ActiveSupport::TestCase
|
|
20
20
|
end
|
21
21
|
|
22
22
|
should "clear all indices for instance when deleted" do
|
23
|
-
CacheBack.cache.expects(:delete).with("
|
24
|
-
CacheBack.cache.expects(:delete).with("
|
25
|
-
CacheBack.cache.expects(:delete).with("
|
26
|
-
CacheBack.cache.expects(:delete).with("
|
27
|
-
CacheBack.cache.expects(:delete).with("
|
28
|
-
CacheBack.cache.expects(:delete).with("
|
23
|
+
CacheBack.cache.expects(:delete).with(Post.cache_back_key_prefix + "id=#{@post.id}")
|
24
|
+
CacheBack.cache.expects(:delete).with(Post.cache_back_key_prefix + "id=#{@post.id}/first")
|
25
|
+
CacheBack.cache.expects(:delete).with(Post.cache_back_key_prefix + "title=#{@post.title}")
|
26
|
+
CacheBack.cache.expects(:delete).with(Post.cache_back_key_prefix + "title=#{@post.title}/first")
|
27
|
+
CacheBack.cache.expects(:delete).with(Post.cache_back_key_prefix + "blog_id=#{@post.blog_id}")
|
28
|
+
CacheBack.cache.expects(:delete).with(Post.cache_back_key_prefix + "blog_id=#{@post.blog_id}/first")
|
29
29
|
CacheBack.cache.expects(:delete).never
|
30
30
|
|
31
31
|
@post.destroy
|
@@ -38,14 +38,14 @@ class CacheExpiryTest < ActiveSupport::TestCase
|
|
38
38
|
end
|
39
39
|
|
40
40
|
should "clear all indices for instance when updated" do
|
41
|
-
CacheBack.cache.expects(:delete).with("
|
42
|
-
CacheBack.cache.expects(:delete).with("
|
43
|
-
CacheBack.cache.expects(:delete).with("
|
44
|
-
CacheBack.cache.expects(:delete).with("
|
45
|
-
CacheBack.cache.expects(:delete).with("
|
46
|
-
CacheBack.cache.expects(:delete).with("
|
47
|
-
CacheBack.cache.expects(:delete).with("
|
48
|
-
CacheBack.cache.expects(:delete).with("
|
41
|
+
CacheBack.cache.expects(:delete).with(Post.cache_back_key_prefix + "id=#{@post.id}")
|
42
|
+
CacheBack.cache.expects(:delete).with(Post.cache_back_key_prefix + "id=#{@post.id}/first")
|
43
|
+
CacheBack.cache.expects(:delete).with(Post.cache_back_key_prefix + "title=#{@post.title}")
|
44
|
+
CacheBack.cache.expects(:delete).with(Post.cache_back_key_prefix + "title=#{@post.title}/first")
|
45
|
+
CacheBack.cache.expects(:delete).with(Post.cache_back_key_prefix + "title=new title")
|
46
|
+
CacheBack.cache.expects(:delete).with(Post.cache_back_key_prefix + "title=new title/first")
|
47
|
+
CacheBack.cache.expects(:delete).with(Post.cache_back_key_prefix + "blog_id=#{@post.blog_id}")
|
48
|
+
CacheBack.cache.expects(:delete).with(Post.cache_back_key_prefix + "blog_id=#{@post.blog_id}/first")
|
49
49
|
CacheBack.cache.expects(:delete).never
|
50
50
|
|
51
51
|
@post.title = "new title"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cache_back
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mick Staugaard
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-11-
|
12
|
+
date: 2009-11-30 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -53,7 +53,6 @@ files:
|
|
53
53
|
- lib/cache_back/conditions_parser.rb
|
54
54
|
- lib/cache_back/configuration_mixin.rb
|
55
55
|
- lib/cache_back/dirty_mixin.rb
|
56
|
-
- lib/cache_back/rack_middleware.rb
|
57
56
|
- lib/cache_back/read_mixin.rb
|
58
57
|
- lib/cache_back/reload_association_mixin.rb
|
59
58
|
- lib/cache_back/write_mixin.rb
|