activerecord_cache 0.0.1 → 0.0.2

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.
@@ -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: