cache_back 0.4.1 → 0.5.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/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.1
1
+ 0.5.0
@@ -5,7 +5,16 @@ module CacheBack
5
5
  end
6
6
 
7
7
  def read(*args)
8
- @local_cache[args[0]] ||= Rails.cache.read(*args)
8
+ result = @local_cache[args[0]] || Rails.cache.read(*args)
9
+ if result.is_a?(CachedModel)
10
+ result = result.instanciate_model
11
+ elsif result.is_a?(Array)
12
+ models = get_multi(result)
13
+ result = result.map { |key| models[key]}
14
+ end
15
+
16
+ @local_cache[args[0]] = result if result
17
+ result
9
18
  end
10
19
 
11
20
  def get_multi(keys)
@@ -16,7 +25,8 @@ module CacheBack
16
25
  if Rails.cache.respond_to?(:read_multi)
17
26
  missing_map = Rails.cache.read_multi(missing_keys)
18
27
  missing_map.each do |key, value|
19
- @local_cache[key] = value
28
+ value = value.instanciate_model if value.is_a?(CachedModel)
29
+ missing_map[key] = @local_cache[key] = value
20
30
  end
21
31
  map.merge!(missing_map)
22
32
  else
@@ -31,6 +41,11 @@ module CacheBack
31
41
 
32
42
  def write(*args)
33
43
  @local_cache[args[0]] = args[1]
44
+
45
+ if args[1].is_a?(ActiveRecord::Base)
46
+ args[1] = CachedModel.new(args[1])
47
+ end
48
+
34
49
  Rails.cache.write(*args)
35
50
  end
36
51
 
@@ -42,5 +57,16 @@ module CacheBack
42
57
  def reset!
43
58
  @local_cache = {}
44
59
  end
60
+
61
+ class CachedModel
62
+ def initialize(model)
63
+ @name = model.class.name
64
+ @attributes = model.instance_variable_get(:@attributes)
65
+ end
66
+
67
+ def instanciate_model
68
+ @name.constantize.send(:instantiate, @attributes)
69
+ end
70
+ end
45
71
  end
46
72
  end
@@ -0,0 +1,72 @@
1
+ module CacheBack
2
+ class ConditionsParser
3
+ def initialize(model_class)
4
+ @model_class = model_class
5
+ end
6
+
7
+ def attribute_value_pairs(options, scope)
8
+ from_scope = attribute_value_pairs_for_conditions((scope || {})[:conditions])
9
+ return nil unless from_scope
10
+
11
+ from_options = attribute_value_pairs_for_conditions(options[:conditions])
12
+ return nil unless from_options
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
22
+ end
23
+
24
+ pairs.sort! { |pair1, pair2| pair1[0] <=> pair2[0] }
25
+
26
+ pairs.map do |attribute, value|
27
+ if value.is_a?(Array)
28
+ value.flatten!
29
+ if value.size == 1
30
+ [attribute.to_sym, value[0]]
31
+ else
32
+ [attribute.to_sym, value]
33
+ end
34
+ else
35
+ [attribute.to_sym, value]
36
+ end
37
+ end
38
+ end
39
+
40
+ def attribute_value_pairs_for_conditions(conditions)
41
+ case conditions
42
+ when Hash
43
+ conditions.to_a.collect { |key, value| [key.to_s, value] }
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
+ end
52
+
53
+ AND = /\s+AND\s+/i
54
+ TABLE_AND_COLUMN = /(?:(?:`|")?(\w+)(?:`|")?\.)?(?:`|")?(\w+)(?:`|")?/ # Matches: `users`.id, `users`.`id`, users.id, id
55
+ VALUE = /'?(\d+|\?|(?:(?:[^']|'')*))'?/ # Matches: 123, ?, '123', '12''3'
56
+ KEY_EQ_VALUE = /^\(?#{TABLE_AND_COLUMN}\s+=\s+#{VALUE}\)?$/ # Matches: KEY = VALUE, (KEY = VALUE)
57
+ ORDER = /^#{TABLE_AND_COLUMN}\s*(ASC|DESC)?$/i # Matches: COLUMN ASC, COLUMN DESC, COLUMN
58
+
59
+ def parse_indices_from_condition(conditions = '', *values)
60
+ values = values.dup
61
+ conditions.split(AND).inject([]) do |indices, condition|
62
+ matched, table_name, column_name, sql_value = *(KEY_EQ_VALUE.match(condition))
63
+ if matched
64
+ value = sql_value == '?' ? values.shift : @model_class.columns_hash[column_name].type_cast(sql_value)
65
+ indices << [column_name, value]
66
+ else
67
+ return nil
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -1,4 +1,4 @@
1
- require 'activesupport'
1
+ require 'active_support'
2
2
 
3
3
  module CacheBack
4
4
  autoload :ReadMixin, 'cache_back/read_mixin'
@@ -26,18 +26,54 @@ module CacheBack
26
26
  end
27
27
  end
28
28
 
29
- def cache_back_key_for(id)
30
- "cache_back/#{table_name}/version_#{inherited_cache_back_version}/#{id}"
29
+ def cache_back_key_for(attribute_value_pairs)
30
+ key = "cache_back/#{table_name}/version=#{inherited_cache_back_version}"
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
40
+ end
41
+
42
+ def cache_back_key_for_id(id)
43
+ cache_back_key_for([['id', id]])
44
+ end
45
+
46
+ def cache_back_indices
47
+ result = @cache_back_indices || []
48
+ result += superclass.cache_back_indices unless self == ActiveRecord::Base
49
+ result.uniq
50
+ end
51
+
52
+ def has_cache_back_index_on?(sorted_attributes)
53
+ cache_back_indices.include?(sorted_attributes)
31
54
  end
32
55
 
33
56
  def has_cache_back(options = {})
34
- @cache_back_version = options.delete(:version) || '1'
35
- @cache_back_option = options
57
+ has_cache_back_on :id
58
+ end
59
+
60
+ def has_cache_back_on(*args)
61
+ options = args.extract_options!
62
+ 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
+ if attributes != [:id] && !cache_back_indices.include?([:id])
68
+ has_cache_back_on(:id)
69
+ end
70
+
71
+ @cache_back_indices ||= []
72
+ @cache_back_indices << attributes unless @cache_back_indices.include?(attributes)
36
73
 
37
74
  include WriteMixin unless instance_methods.include?('store_in_cache_back')
38
- extend ReadMixin unless methods.include?('find_one_with_cache_back')
75
+ extend ReadMixin unless methods.include?('without_cache_back')
39
76
  extend DirtyMixin unless methods.include?('cache_back_dirty_methods')
40
77
  end
41
-
42
78
  end
43
79
  end
@@ -6,7 +6,7 @@ module CacheBack
6
6
  alias_method("without_cache_back_update_#{method}", method)
7
7
  define_method(method) do |*args|
8
8
  result = send("without_cache_back_update_#{method}", *args)
9
- store_in_cache_back
9
+ clear_cache_back_indices
10
10
  result
11
11
  end
12
12
  end
@@ -1,29 +1,60 @@
1
+ require 'cache_back/conditions_parser'
2
+
1
3
  module CacheBack
2
4
  module ReadMixin
3
5
 
4
6
  def self.extended(model_class)
5
7
  class << model_class
6
- alias_method_chain :find_one, :cache_back
7
- alias_method_chain :find_some, :cache_back
8
+ alias_method_chain :find_some, :cache_back unless methods.include?('find_some_without_cache_back')
9
+ alias_method_chain :find_every, :cache_back unless methods.include?('find_every_without_cache_back')
8
10
  end
9
11
  end
10
12
 
11
- def find_one_with_cache_back(id, options)
12
- if cache_safe?(options)
13
- unless record = CacheBack.cache.read(cache_back_key_for(id))
14
- record = find_one_without_cache_back(id, options)
15
- record.store_in_cache_back if record
13
+ def without_cache_back(&block)
14
+ old_value = @use_cache_back || true
15
+ @use_cache_back = false
16
+ yield
17
+ ensure
18
+ @use_cache_back = old_value
19
+ end
20
+
21
+ def find_every_with_cache_back(options)
22
+ attribute_value_pairs = cache_back_conditions_parser.attribute_value_pairs(options, scope(:find)) if cache_safe?(options)
23
+
24
+ limit = (options[:limit] || (scope(:find) || {})[:limit])
25
+
26
+ if (limit.nil? || limit == 1) && attribute_value_pairs && has_cache_back_index_on?(attribute_value_pairs.map(&:first))
27
+ collection_key = cache_back_key_for(attribute_value_pairs)
28
+ collection_key << '/first' if limit == 1
29
+ unless records = CacheBack.cache.read(collection_key)
30
+ records = without_cache_back do
31
+ find_every_without_cache_back(options)
32
+ end
33
+
34
+ if records.size == 1
35
+ CacheBack.cache.write(collection_key, records[0])
36
+ elsif records.size <= CacheBack::CONFIGURATION[:max_collection_size]
37
+ records.each { |record| record.store_in_cache_back if record }
38
+ CacheBack.cache.write(collection_key, records.map(&:cache_back_key))
39
+ end
16
40
  end
17
41
 
18
- record
42
+ Array(records)
19
43
  else
20
- find_one_without_cache_back(id, options)
44
+ without_cache_back do
45
+ find_every_without_cache_back(options)
46
+ end
21
47
  end
22
48
  end
23
49
 
24
50
  def find_some_with_cache_back(ids, options)
25
- if cache_safe?(options)
26
- id_to_key_map = Hash[ids.uniq.map { |id| [id, cache_back_key_for(id)] }]
51
+ attribute_value_pairs = cache_back_conditions_parser.attribute_value_pairs(options, scope(:find)) if cache_safe?(options)
52
+ attribute_value_pairs << [:id, ids] if attribute_value_pairs
53
+
54
+ limit = (options[:limit] || (scope(:find) || {})[:limit])
55
+
56
+ if limit.nil? && attribute_value_pairs && has_cache_back_index_on?(attribute_value_pairs.map(&:first))
57
+ id_to_key_map = Hash[ids.uniq.map { |id| [id, cache_back_key_for_id(id)] }]
27
58
  cached_record_map = CacheBack.cache.get_multi(id_to_key_map.values)
28
59
 
29
60
  missing_keys = Hash[cached_record_map.select { |key, record| record.nil? }].keys
@@ -32,19 +63,30 @@ module CacheBack
32
63
 
33
64
  missing_ids = Hash[id_to_key_map.invert.select { |key, id| missing_keys.include?(key) }].values
34
65
 
35
- db_records = find_some_without_cache_back(missing_ids, options)
66
+ db_records = without_cache_back do
67
+ find_some_without_cache_back(missing_ids, options)
68
+ end
36
69
  db_records.each { |record| record.store_in_cache_back if record }
37
70
 
38
71
  (cached_record_map.values + db_records).compact.uniq.sort { |x, y| x.id <=> y.id}
39
72
  else
40
- find_some_without_cache_back(ids, options)
73
+ without_cache_back do
74
+ find_some_without_cache_back(ids, options)
75
+ end
41
76
  end
42
77
  end
43
78
 
44
79
  private
45
80
 
46
81
  def cache_safe?(options)
47
- options[:select].nil?
82
+ @use_cache_back != false && [options, scope(:find) || {}].all? do |hash|
83
+ result = hash[:select].nil? && hash[:joins].nil? && hash[:order].nil? && hash[:offset].nil?
84
+ result && (options[:limit].nil? || options[:limit] == 1)
85
+ end
86
+ end
87
+
88
+ def cache_back_conditions_parser
89
+ @cache_back_conditions_parser ||= CacheBack::ConditionsParser.new(self)
48
90
  end
49
91
 
50
92
  end
@@ -0,0 +1,15 @@
1
+ module CacheBack
2
+ module ReloadAssociationMixin
3
+ def reload_with_cache_back_clearing(*args)
4
+ # TODO we could calculate the right key to clear by parsing the association conditions.
5
+ # this would clear less keys, and we would not have to load the target
6
+ load_target
7
+ target.clear_cache_back_indices if target.respond_to?(:clear_cache_back_indices)
8
+ reload_without_cache_back_clearing(*args)
9
+ end
10
+
11
+ def self.included(base)
12
+ base.alias_method_chain :reload, :cache_back_clearing
13
+ end
14
+ end
15
+ end
@@ -3,7 +3,7 @@ module CacheBack
3
3
  module ClassMethods
4
4
  def remove_from_cache_back(ids)
5
5
  Array(ids).each do |id|
6
- CacheBack.cache.delete(cache_back_key_for(id))
6
+ CacheBack.cache.delete(cache_back_key_for_id(id))
7
7
  end
8
8
  end
9
9
 
@@ -14,29 +14,35 @@ module CacheBack
14
14
  end
15
15
 
16
16
  module InstanceMethods
17
- def shallow_clone
18
- clone = self.class.new
19
- clone.instance_variable_set("@attributes", instance_variable_get(:@attributes))
20
- clone.instance_variable_set("@new_record", new_record?)
21
- clone
22
- end
23
-
24
17
  def cache_back_key
25
- @cache_back_key ||= new_record? ? nil : self.class.cache_back_key_for(id)
18
+ @cache_back_key ||= new_record? ? nil : self.class.cache_back_key_for_id(id)
26
19
  end
27
20
 
28
21
  def store_in_cache_back
29
22
  if !readonly? && cache_back_key
30
- CacheBack.cache.write(cache_back_key, shallow_clone, self.class.inherited_cache_back_options)
23
+ CacheBack.cache.write(cache_back_key, self, self.class.inherited_cache_back_options)
31
24
  end
32
25
  end
33
26
 
34
- def remove_from_cache_back
35
- CacheBack.cache.delete(cache_back_key) if cache_back_key
27
+ def clear_cache_back_indices
28
+ new_attributes = attributes.symbolize_keys
29
+
30
+ old_attributes = Hash[changes.map {|attribute, values| [attribute, values[0]]}].symbolize_keys
31
+ old_attributes.reverse_merge!(new_attributes)
32
+
33
+ self.class.cache_back_indices.each do |index|
34
+ old_key = self.class.cache_back_key_for(index.map { |attribute| [attribute, old_attributes[attribute]]})
35
+ new_key = self.class.cache_back_key_for(index.map { |attribute| [attribute, new_attributes[attribute]]})
36
+
37
+ [old_key, new_key].uniq.each do |key|
38
+ CacheBack.cache.delete(key)
39
+ CacheBack.cache.delete("#{key}/first")
40
+ end
41
+ end
36
42
  end
37
43
 
38
44
  def reload_with_cache_back_clearing(*args)
39
- remove_from_cache_back
45
+ clear_cache_back_indices
40
46
  reload_without_cache_back_clearing(*args)
41
47
  end
42
48
  end
@@ -45,9 +51,9 @@ module CacheBack
45
51
  model_class.extend ClassMethods
46
52
  model_class.send :include, InstanceMethods
47
53
 
48
- #model_class.after_save :store_in_cache_back
49
- model_class.after_update :remove_from_cache_back
50
- model_class.after_destroy :remove_from_cache_back
54
+ model_class.after_save :clear_cache_back_indices
55
+ model_class.after_destroy :clear_cache_back_indices
56
+
51
57
  model_class.alias_method_chain :reload, :cache_back_clearing
52
58
 
53
59
  class << model_class
data/lib/cache_back.rb CHANGED
@@ -1,23 +1,48 @@
1
1
  require 'rubygems'
2
- require 'activerecord'
2
+ require 'active_record'
3
+ require 'active_support'
3
4
 
4
5
  require 'cache_back/configuration_mixin'
6
+ require 'cache_back/reload_association_mixin'
5
7
  require 'cache_back/cache'
6
8
  require 'cache_back/rack_middleware'
7
9
 
8
10
  module CacheBack
11
+ CONFIGURATION = {:max_collection_size => 100}
12
+
9
13
  module_function
10
14
 
11
15
  def cache
12
16
  Thread.current["cache_back_cache"] ||= Cache.new
13
17
  end
14
- end
15
18
 
16
- ActiveRecord::Base.extend(CacheBack::ConfigurationMixin)
19
+ def setup(options = {})
20
+ CONFIGURATION[:max_collection_size] = options[:max_collection_size] if options[:max_collection_size]
17
21
 
18
- begin
19
- ActionController::Dispatcher.middleware.use(CacheBack::RackMiddleware)
20
- rescue NameError => e
21
-
22
- end
22
+ ActiveRecord::Base.extend(CacheBack::ConfigurationMixin)
23
+ ActiveRecord::Associations::BelongsToAssociation.send(:include, CacheBack::ReloadAssociationMixin)
24
+ ActiveRecord::Associations::BelongsToPolymorphicAssociation.send(:include, CacheBack::ReloadAssociationMixin)
25
+ ActiveRecord::Associations::HasOneThroughAssociation.send(:include, CacheBack::ReloadAssociationMixin)
26
+
27
+ #sets up local cache clearing after each request
28
+ begin
29
+ ApplicationController.after_filter do
30
+ CacheBack.cache.reset!
31
+ end
32
+ rescue NameError => e
23
33
 
34
+ end
35
+
36
+ #sets up local cache clearing after each test case
37
+ begin
38
+ ActiveSupport::TestCase.class_eval do
39
+ setup :clear_cache
40
+ def clear_cache
41
+ CacheBack.cache.reset!
42
+ Rails.cache.clear if Rails.cache.respond_to?(:clear)
43
+ end
44
+ end
45
+ rescue NameError => e
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,55 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class CacheExpiryTest < ActiveSupport::TestCase
4
+ fixtures :blogs, :posts
5
+
6
+ Post.has_cache_back
7
+ Post.has_cache_back_on :title
8
+ Post.has_cache_back_on :blog_id
9
+
10
+ context "a cached object" do
11
+ setup do
12
+ post = Post.first
13
+ @post = Post.find(post.id)
14
+ assert(Rails.cache.read(@post.cache_back_key))
15
+ end
16
+
17
+ should "be removed from cache when deleted" do
18
+ @post.destroy
19
+ assert_nil(Rails.cache.read(@post.cache_back_key))
20
+ end
21
+
22
+ should "clear all indices for instance when deleted" do
23
+ CacheBack.cache.expects(:delete).with("cache_back/posts/version=1/id=#{@post.id}")
24
+ CacheBack.cache.expects(:delete).with("cache_back/posts/version=1/id=#{@post.id}/first")
25
+ CacheBack.cache.expects(:delete).with("cache_back/posts/version=1/title=#{@post.title}")
26
+ CacheBack.cache.expects(:delete).with("cache_back/posts/version=1/title=#{@post.title}/first")
27
+ CacheBack.cache.expects(:delete).with("cache_back/posts/version=1/blog_id=#{@post.blog_id}")
28
+ CacheBack.cache.expects(:delete).with("cache_back/posts/version=1/blog_id=#{@post.blog_id}/first")
29
+ CacheBack.cache.expects(:delete).never
30
+
31
+ @post.destroy
32
+ end
33
+
34
+ should "be removed from cache when updated" do
35
+ @post.title = "new title"
36
+ @post.save
37
+ assert_nil(Rails.cache.read(@post.cache_back_key))
38
+ end
39
+
40
+ should "clear all indices for instance when updated" do
41
+ CacheBack.cache.expects(:delete).with("cache_back/posts/version=1/id=#{@post.id}")
42
+ CacheBack.cache.expects(:delete).with("cache_back/posts/version=1/id=#{@post.id}/first")
43
+ CacheBack.cache.expects(:delete).with("cache_back/posts/version=1/title=#{@post.title}")
44
+ CacheBack.cache.expects(:delete).with("cache_back/posts/version=1/title=#{@post.title}/first")
45
+ CacheBack.cache.expects(:delete).with("cache_back/posts/version=1/title=new title")
46
+ CacheBack.cache.expects(:delete).with("cache_back/posts/version=1/title=new title/first")
47
+ CacheBack.cache.expects(:delete).with("cache_back/posts/version=1/blog_id=#{@post.blog_id}")
48
+ CacheBack.cache.expects(:delete).with("cache_back/posts/version=1/blog_id=#{@post.blog_id}/first")
49
+ CacheBack.cache.expects(:delete).never
50
+
51
+ @post.title = "new title"
52
+ @post.save
53
+ end
54
+ end
55
+ end
data/test/dirty_test.rb CHANGED
@@ -6,13 +6,14 @@ class DirtyTest < ActiveSupport::TestCase
6
6
  Post.has_cache_back
7
7
  Post.cache_back_dirty_methods :make_dirty!
8
8
 
9
- should "update the cache when a dirty method is called" do
9
+ should "clear the indices when a dirty method is called" do
10
10
  post = Post.first
11
11
 
12
12
  pots = Post.find(post.id)
13
13
  assert(Rails.cache.read(post.cache_back_key))
14
14
 
15
- CacheBack.cache.expects(:write)
16
15
  post.make_dirty!
16
+
17
+ assert_nil(Rails.cache.read(post.cache_back_key))
17
18
  end
18
19
  end
@@ -30,4 +30,15 @@ class FindOneTest < ActiveSupport::TestCase
30
30
  CacheBack.cache.expects(:read).never
31
31
  Post.find(post.id, :select => 'title')
32
32
  end
33
+
34
+ should "respect scope" do
35
+ post = Post.find(Post.first.id)
36
+ other_blog = Blog.first(:conditions => "id != #{post.blog_id}")
37
+
38
+ assert(Rails.cache.read(post.cache_back_key))
39
+
40
+ assert_raise(ActiveRecord::RecordNotFound) do
41
+ other_blog.posts.find(post.id)
42
+ end
43
+ end
33
44
  end
@@ -4,6 +4,7 @@ class FindSomeTest < ActiveSupport::TestCase
4
4
  fixtures :blogs, :posts
5
5
 
6
6
  Post.has_cache_back
7
+ Post.has_cache_back_on :blog_id
7
8
 
8
9
  should "cache find(id, id) calls" do
9
10
  post1 = Post.first
@@ -36,4 +37,13 @@ class FindSomeTest < ActiveSupport::TestCase
36
37
  found_posts = Post.find(post1.id, post2.id)
37
38
  assert_equal([post1, post2].map(&:id).sort, found_posts.map(&:id).sort)
38
39
  end
40
+
41
+ should "cache on index other than primary key" do
42
+ blog = blogs(:a_blog)
43
+ posts = Post.find_all_by_blog_id(blog.id)
44
+
45
+ Post.expects(:find_every_without_cache_back).never
46
+
47
+ assert_equal(posts, Post.find_all_by_blog_id(blog.id))
48
+ end
39
49
  end
@@ -1,2 +1,5 @@
1
1
  a_blog:
2
- name: My Blog
2
+ name: My Blog
3
+
4
+ other_blog:
5
+ name: Some Other Blog
@@ -6,6 +6,10 @@ has_two_comments:
6
6
  blog: a_blog
7
7
  title: This post has a few comments
8
8
 
9
+ on_other_blog:
10
+ blog: other_blog
11
+ title: This post has no comments
12
+
9
13
  has_many_comments:
10
14
  blog: a_blog
11
15
  title: A shit load of comments on this one
data/test/helper.rb CHANGED
@@ -16,12 +16,14 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
16
16
  $LOAD_PATH.unshift(File.dirname(__FILE__))
17
17
  require 'cache_back'
18
18
 
19
+ CacheBack.setup
20
+
19
21
  class ActiveSupport::TestCase
20
22
  include ActiveRecord::TestFixtures
21
23
 
22
24
  fixtures :all
23
25
 
24
- setup :clear_cache
26
+ #setup :clear_cache
25
27
 
26
28
  def create_fixtures(*table_names)
27
29
  if block_given?
@@ -0,0 +1,21 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class SerializationTest < ActiveSupport::TestCase
4
+ fixtures :blogs, :posts
5
+
6
+ Post.has_cache_back
7
+
8
+ should "store a CachedModel" do
9
+ post = Post.first
10
+ post.store_in_cache_back
11
+ assert_instance_of(CacheBack::Cache::CachedModel, Rails.cache.read(post.cache_back_key))
12
+ end
13
+
14
+ should "bring convert CachedModel to model instances" do
15
+ post = Post.first
16
+ post.store_in_cache_back
17
+
18
+ post = CacheBack.cache.read(post.cache_back_key)
19
+ assert_instance_of(Post, post)
20
+ end
21
+ end
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.4.1
4
+ version: 0.5.0
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-26 00:00:00 -08:00
12
+ date: 2009-11-29 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -50,11 +50,14 @@ files:
50
50
  - VERSION
51
51
  - lib/cache_back.rb
52
52
  - lib/cache_back/cache.rb
53
+ - lib/cache_back/conditions_parser.rb
53
54
  - lib/cache_back/configuration_mixin.rb
54
55
  - lib/cache_back/dirty_mixin.rb
55
56
  - lib/cache_back/rack_middleware.rb
56
57
  - lib/cache_back/read_mixin.rb
58
+ - lib/cache_back/reload_association_mixin.rb
57
59
  - lib/cache_back/write_mixin.rb
60
+ - test/cache_expiry_test.rb
58
61
  - test/database.yml
59
62
  - test/dirty_test.rb
60
63
  - test/find_one_test.rb
@@ -64,6 +67,7 @@ files:
64
67
  - test/fixtures/posts.yml
65
68
  - test/helper.rb
66
69
  - test/schema.rb
70
+ - test/serialization_test.rb
67
71
  has_rdoc: true
68
72
  homepage: http://github.com/staugaard/cache_back
69
73
  licenses: []
@@ -93,8 +97,10 @@ signing_key:
93
97
  specification_version: 3
94
98
  summary: A write back caching layer on active record
95
99
  test_files:
100
+ - test/cache_expiry_test.rb
96
101
  - test/dirty_test.rb
97
102
  - test/find_one_test.rb
98
103
  - test/find_some_test.rb
99
104
  - test/helper.rb
100
105
  - test/schema.rb
106
+ - test/serialization_test.rb