join_cache 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown CHANGED
@@ -47,10 +47,12 @@ class Employee < ActiveRecord::Base
47
47
  end
48
48
  ```
49
49
 
50
+ It also works with `has_many :through` associations!
51
+
50
52
  ## TODO
51
53
 
52
- * [Support has_many :through](https://github.com/KevinBongart/join_cache/issues/1)
53
54
  * [Support callbacks: after_add and after_remove](https://github.com/KevinBongart/join_cache/issues/2)
55
+ * [Add tests](https://github.com/KevinBongart/join_cache/issues/3)
54
56
 
55
57
  [View the full list](https://github.com/KevinBongart/join_cache/issues)
56
58
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.2
1
+ 0.2.0
data/join_cache.gemspec CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "join_cache"
8
- s.version = "0.1.2"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Kevin Bongart"]
data/lib/join_cache.rb CHANGED
@@ -39,5 +39,48 @@ module JoinCache
39
39
  association.klass.where(id: send(cached_ids_name))
40
40
  end
41
41
  end
42
+
43
+ has_many_through_associations = reflect_on_all_associations(:has_many).select do |association|
44
+ association.is_a?(ActiveRecord::Reflection::ThroughReflection)
45
+ end
46
+
47
+ # Generates methods for faster retrieval of has_many :through associations
48
+ # by storing foreign keys in cache and avoiding large joins
49
+ #
50
+ # For example:
51
+ # class Physician < ActiveRecord::Base
52
+ # has_many :appointments
53
+ # has_many :patients, through: :appointments
54
+ # include JoinCache
55
+ # end
56
+ #
57
+ # Physician.first.cached_patient_ids
58
+ # => [4, 8, 15, 16, 23, 42]
59
+ #
60
+ # Physician.first.cached_patients
61
+ # => Patient.where(id: [4, 8, 15, 16, 23, 42])
62
+ #
63
+ has_many_through_associations.each do |association|
64
+ singular_name = association.name.to_s.singularize # patient
65
+ plural_name = association.plural_name # patients
66
+ cached_name = "cached_#{plural_name}" # cached_patients
67
+ cached_ids_name = "cached_#{singular_name}_ids" # cached_patient_ids
68
+ primary_key = self.name.foreign_key # employee_id
69
+ foreign_key = association.foreign_key # patient_id
70
+ join_table = association.options[:through] # appointments
71
+ join_model = join_table.to_s.classify.constantize # Appointment
72
+
73
+ # cached_patient_ids
74
+ define_method(cached_ids_name) do
75
+ Rails.cache.fetch("#{cache_key}/#{cached_ids_name}") do
76
+ join_model.where(primary_key => id).pluck(foreign_key.to_sym)
77
+ end
78
+ end
79
+
80
+ # cached_patients
81
+ define_method(cached_name) do
82
+ association.klass.where(id: send(cached_ids_name))
83
+ end
84
+ end
42
85
  end
43
86
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: join_cache
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -109,7 +109,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
109
109
  version: '0'
110
110
  segments:
111
111
  - 0
112
- hash: -785509289355240113
112
+ hash: 1146460858880032511
113
113
  required_rubygems_version: !ruby/object:Gem::Requirement
114
114
  none: false
115
115
  requirements: