activerecord_cache 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,18 +1,16 @@
1
1
  module ActiveRecordCache
2
2
  module Base
3
+ extend ActiveSupport::Concern
3
4
 
4
- def self.included(base)
5
- base.class_eval do
6
-
7
- class_attribute :use_activerecord_cache, :instance_writer => false
8
- self.use_activerecord_cache = false
9
-
10
- extend ActiveRecordCache::Base::CacheMethods
11
-
12
- end
5
+ included do
6
+ class_attribute :use_activerecord_cache, :instance_writer => false
7
+ self.use_activerecord_cache = false
8
+
9
+ after_save :write_to_cache, :if => lambda { self.class.use_activerecord_cache }
10
+ after_destroy :delete_from_cache, :if => lambda { self.class.use_activerecord_cache }
13
11
  end
14
12
 
15
- module CacheMethods
13
+ module ClassMethods
16
14
  def cache_key(id_or_record)
17
15
  unless use_activerecord_cache
18
16
  message = "ActiveRecord cache is not enabled for #{self.name}"
@@ -25,30 +23,66 @@ module ActiveRecordCache
25
23
  id = id_or_record
26
24
  end
27
25
 
28
- "#{name}:#{id}"
26
+ "#{model_name}/#{id}"
29
27
  end
30
28
 
31
29
  def find_through_cache(id)
32
30
  unless use_activerecord_cache
33
31
  message = "ActiveRecord cache is not enabled for #{self.name}"
34
- raise ActiveRecordCache::CachingNotEnabled, message
32
+ raise ActiveRecordCache::CacheNotEnabled, message
35
33
  end
36
34
 
37
- Rails.cache.fetch(cache_key(id)) { where(primary_key => id).first }
35
+ Rails.cache.read(cache_key(id)) || where(primary_key => id).first
38
36
  end
39
37
 
40
- def write_to_cache(record)
38
+ def find_some_through_cache(ids)
41
39
  unless use_activerecord_cache
42
40
  message = "ActiveRecord cache is not enabled for #{self.name}"
43
- raise ActiveRecordCache::CachingNotEnabled, message
41
+ raise ActiveRecordCache::CacheNotEnabled, message
44
42
  end
45
43
 
46
- unless record.class == self
47
- message = "Instance of #{self} expected, got #{record.class}"
48
- raise ActiveRecordCache::RecordTypeMismatch, message
44
+ records = []
45
+ cache_misses = []
46
+
47
+ ids.each do |id|
48
+ if record = find_in_cache(id)
49
+ records << record
50
+ else
51
+ cache_misses << id
52
+ end
53
+ end
54
+
55
+ if cache_misses.present?
56
+ records += where(primary_key => cache_misses).all
49
57
  end
50
58
 
51
- Rails.cache.write(cache_key(record), record)
59
+ records
60
+ end
61
+
62
+ def find_in_cache(id)
63
+ unless use_activerecord_cache
64
+ message = "ActiveRecord cache is not enabled for #{self.name}"
65
+ raise ActiveRecordCache::CacheNotEnabled, message
66
+ end
67
+
68
+ Rails.cache.read(cache_key(id))
69
+ end
70
+
71
+ end
72
+
73
+ module InstanceMethods
74
+
75
+ def write_to_cache
76
+ unless self.class.use_activerecord_cache
77
+ message = "ActiveRecord cache is not enabled for #{self.class.name}"
78
+ raise ActiveRecordCache::CacheNotEnabled, message
79
+ end
80
+
81
+ Rails.cache.write(self.class.cache_key(self), self)
82
+ end
83
+
84
+ def delete_from_cache
85
+ Rails.cache.delete(self.class.cache_key(self))
52
86
  end
53
87
 
54
88
  end
@@ -1,19 +1,22 @@
1
1
  module ActiveRecordCache
2
2
  module BelongsToAssociation
3
+ extend ActiveSupport::Concern
3
4
 
4
- def self.included(base)
5
- base.class_eval do
6
- alias_method_chain :find_target, :caching
7
- end
5
+ included do
6
+ alias_method_chain :find_target, :caching
8
7
  end
9
-
10
- protected
11
-
12
- def find_target_with_caching
13
- if klass.use_activerecord_cache
14
- klass.find_through_cache(owner[reflection.foreign_key])
15
- else
16
- find_target_without_caching
8
+
9
+
10
+ module InstanceMethods
11
+
12
+ private
13
+
14
+ def find_target_with_caching
15
+ if klass.use_activerecord_cache && reflection.foreign_key == klass.primary_key
16
+ klass.find_through_cache(owner[reflection.foreign_key]).tap { |record| set_inverse_instance(record) }
17
+ else
18
+ find_target_without_caching
19
+ end
17
20
  end
18
21
  end
19
22
 
@@ -0,0 +1,23 @@
1
+ module ActiveRecordCache
2
+ module BelongsToPreloader
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ alias_method_chain :records_for, :caching
7
+ end
8
+
9
+
10
+ module InstanceMethods
11
+
12
+ def records_for_with_caching(ids)
13
+ if klass.use_activerecord_cache && association_key.name == klass.primary_key
14
+ find_some_through_cache(ids)
15
+ else
16
+ records_for_without_caching(ids)
17
+ end
18
+ end
19
+
20
+ end
21
+
22
+ end
23
+ end
@@ -1,9 +1,6 @@
1
1
  module ActiveRecordCache
2
2
 
3
- class CachingNotEnabled < StandardError
4
- end
5
-
6
- class RecordTypeMismatch < StandardError
3
+ class CacheNotEnabled < StandardError
7
4
  end
8
5
 
9
6
  end
@@ -1,64 +1,67 @@
1
1
  module ActiveRecordCache
2
2
  module FinderMethods
3
+ extend ActiveSupport::Concern
3
4
 
4
- def self.included(base)
5
- base.module_eval do
6
- alias_method_chain :find_by_attributes, :caching
7
- alias_method_chain :find_some, :caching
8
- alias_method_chain :find_one, :caching
9
- end
5
+ included do
6
+ alias_method_chain :find_by_attributes, :caching
7
+ alias_method_chain :find_some, :caching
8
+ alias_method_chain :find_one, :caching
10
9
  end
11
-
12
- protected
13
10
 
14
- def find_by_attributes_with_caching(match, attributes, *args)
15
- unless cached_lookup_allowed? && attributes == Array(@klass.primary_key) # must only be finding by primary key
16
- return find_by_attributes_without_caching(match, attributes, *args)
17
- end
11
+ module InstanceMethods
18
12
 
19
- ids = Array(args.first)
13
+ protected
20
14
 
21
- results = case match.finder
22
- when :all then ids.map {|id| @klass.find_through_cache(id)}.compact
23
- when :first then @klass.find_through_cache(ids.first)
24
- when :last then @klass.find_through_cache(ids.last)
25
- end
15
+ def find_by_attributes_with_caching(match, attributes, *args)
16
+ unless cached_lookup_allowed? && attributes == Array(@klass.primary_key) && (match.finder == :all || !args.first.is_a?(Array))
17
+ return find_by_attributes_without_caching(match, attributes, *args)
18
+ end
19
+
20
+ param = args.first
26
21
 
27
- results
28
- end
22
+ results = case match.finder
23
+ when :all then @klass.find_some_through_cache(Array(param))
24
+ when :first then @klass.find_through_cache(param)
25
+ when :last then @klass.find_through_cache(param)
26
+ end
27
+
28
+ results
29
+ end
29
30
 
30
31
 
31
- def find_some_with_caching(ids)
32
- return find_some_without_caching(ids) unless cached_lookup_allowed?
32
+ def find_some_with_caching(ids)
33
+ return find_some_without_caching(ids) unless cached_lookup_allowed?
33
34
 
34
- results = ids.map {|id| @klass.find_through_cache(id)}.compact
35
+ results = find_some_through_cache(ids)
36
+
37
+ if results.size != ids.size
38
+ error = "Couldn't find all #{@klass.name.pluralize} with IDs "
39
+ error << "(#{ids.join(", ")}) (found #{results.size} results, but was looking for #{ids.size})"
40
+ raise ActiveRecord::RecordNotFound, error
41
+ end
35
42
 
36
- if results.size != ids.size
37
- error = "Couldn't find all #{@klass.name.pluralize} with IDs "
38
- error << "(#{ids.join(", ")}) (found #{result.size} results, but was looking for #{ids.size})"
39
- raise ActiveRecord::RecordNotFound, error
43
+ results
40
44
  end
41
-
42
- results
43
- end
44
45
 
45
46
 
46
- def find_one_with_caching(id)
47
- return find_one_without_caching(id) unless cached_lookup_allowed?
47
+ def find_one_with_caching(id)
48
+ return find_one_without_caching(id) unless cached_lookup_allowed?
48
49
 
49
- record = @klass.find_through_cache(id)
50
+ record = @klass.find_through_cache(id)
50
51
 
51
- unless record
52
- raise ActiveRecord::RecordNotFound, "Couldn't find #{@klass.name} with #{primary_key}=#{id}"
53
- end
52
+ unless record
53
+ raise ActiveRecord::RecordNotFound, "Couldn't find #{@klass.name} with #{primary_key}=#{id}"
54
+ end
54
55
 
55
- record
56
- end
56
+ record
57
+ end
57
58
 
58
59
 
59
- # only support the most basic lookups through the cache
60
- def cached_lookup_allowed?
61
- @klass.use_activerecord_cache && arel.where_sql.nil? && @limit_value.nil? && @offset_value.nil?
60
+ # only support the most basic lookups through the cache
61
+ def cached_lookup_allowed?
62
+ @klass.use_activerecord_cache && arel.where_sql.nil? && arel.join_sql.nil? && @limit_value.nil? && @offset_value.nil?
63
+ end
64
+
62
65
  end
63
66
 
64
67
  end
@@ -8,6 +8,8 @@ class ActiveRecordCache::Railtie < Rails::Railtie
8
8
  ActiveRecord::Base.send(:include, ActiveRecordCache::Base)
9
9
  ActiveRecord::FinderMethods.send(:include, ActiveRecordCache::FinderMethods)
10
10
  ActiveRecord::Associations::BelongsToAssociation.send(:include, ActiveRecordCache::BelongsToAssociation)
11
+ ActiveRecord::Associations::Preloader::BelongsTo.send(:include, ActiveRecordCache::BelongsToPreloader)
12
+ ActiveRecord::Relation.send(:include, ActiveRecordCache::Relation)
11
13
  end
12
14
  end
13
15
 
@@ -0,0 +1,22 @@
1
+ module ActiveRecordCache
2
+ module Relation
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ alias_method_chain :to_a, :caching
7
+ end
8
+
9
+ module InstanceMethods
10
+ def to_a_with_caching
11
+ previously_loaded = loaded?
12
+
13
+ records = to_a_without_caching
14
+ records.each(&:write_to_cache) if @klass.use_activerecord_cache && !previously_loaded
15
+
16
+ records
17
+ end
18
+
19
+ end
20
+
21
+ end
22
+ end
@@ -2,7 +2,7 @@ module ActiveRecordCache
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 0
5
- TINY = 1
5
+ TINY = 2
6
6
  PRE = nil
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
@@ -4,5 +4,7 @@ end
4
4
  require File.join(File.dirname(__FILE__), 'activerecord_cache/base')
5
5
  require File.join(File.dirname(__FILE__), 'activerecord_cache/finder_methods')
6
6
  require File.join(File.dirname(__FILE__), 'activerecord_cache/belongs_to_association')
7
+ require File.join(File.dirname(__FILE__), 'activerecord_cache/belongs_to_preloader')
8
+ require File.join(File.dirname(__FILE__), 'activerecord_cache/relation')
7
9
 
8
10
  require 'activerecord_cache/railtie.rb' if defined?(Rails)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord_cache
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
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: 2012-02-14 00:00:00.000000000Z
12
+ date: 2012-02-16 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
16
- requirement: &2167650840 !ruby/object:Gem::Requirement
16
+ requirement: &2167643440 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,7 +21,7 @@ dependencies:
21
21
  version: 3.1.3
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2167650840
24
+ version_requirements: *2167643440
25
25
  description: Caches ActiveRecord models for simple finds using the Rails low-level
26
26
  cache
27
27
  email:
@@ -37,9 +37,11 @@ files:
37
37
  - lib/activerecord_cache.rb
38
38
  - lib/activerecord_cache/base.rb
39
39
  - lib/activerecord_cache/belongs_to_association.rb
40
+ - lib/activerecord_cache/belongs_to_preloader.rb
40
41
  - lib/activerecord_cache/errors.rb
41
42
  - lib/activerecord_cache/finder_methods.rb
42
43
  - lib/activerecord_cache/railtie.rb
44
+ - lib/activerecord_cache/relation.rb
43
45
  - lib/activerecord_cache/version.rb
44
46
  homepage: https://github.com/davedoan/activerecord_cache
45
47
  licenses: