join_cache 0.1.2 → 0.2.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/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: