batch-loader-active-record 0.4.3 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/Gemfile.lock +1 -1
- data/README.md +1 -1
- data/gemfiles/activerecord_4_2.gemfile.lock +1 -1
- data/gemfiles/activerecord_5_0.gemfile.lock +1 -1
- data/gemfiles/activerecord_5_1.gemfile.lock +1 -1
- data/gemfiles/activerecord_5_2.gemfile.lock +1 -1
- data/lib/batch_loader_active_record.rb +18 -9
- data/lib/batch_loader_active_record/association_manager.rb +27 -8
- data/lib/batch_loader_active_record/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f442e69779971d6ff0f8a67e79a9b1afd68ee1d5
|
4
|
+
data.tar.gz: 5b457b1b5ac6a0bce872ca6a11b9778a1b67bb38
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 88cde79729754c86cfb0af302fc5fed3e68b679f9a17bb1b9615fcec2ce9b1e6d229b84203ec106df35e04f9704d7a2613c092d629513f8e185cb0b7ba1611bb
|
7
|
+
data.tar.gz: 4b1ac2601cbd5cf2515b4b811211222bf6dd84b7dd425488308b7d33c4a30e7974457faad348a6180657f0ec5a8b6d69dd0f99876bdf7807eb6821f3d2c5cc00
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -14,7 +14,7 @@ It is not intended to be used for all associations though, but only where necess
|
|
14
14
|
|
15
15
|
This gem has a very simple implementation and delegates all batch loading responsibilities (used to avoid N+1 calls to the database) to the [batch-loader gem](https://github.com/exAspArk/batch-loader). It allows to generate a lazy association accessor with a simple statement: `association_accessor :association_name`.
|
16
16
|
|
17
|
-
|
17
|
+
Refer to the [CHANGELOG](https://github.com/mathieul/batch-loader-active-record/blob/master/CHANGELOG.md) to know what is supported and what is not.
|
18
18
|
|
19
19
|
It is also possible to use one of the macros below in replacement of the original Active Record macro to both declare the association and trigger a lazy association accessort in a single statement.
|
20
20
|
|
@@ -15,7 +15,11 @@ module BatchLoaderActiveRecord
|
|
15
15
|
manager = AssociationManager.new(model: self, reflection: reflection)
|
16
16
|
case reflection.macro
|
17
17
|
when :belongs_to
|
18
|
-
|
18
|
+
if reflection.polymorphic?
|
19
|
+
define_method(manager.accessor_name) { manager.polymorphic_belongs_to_batch_loader(self) }
|
20
|
+
else
|
21
|
+
define_method(manager.accessor_name) { manager.belongs_to_batch_loader(self) }
|
22
|
+
end
|
19
23
|
when :has_one
|
20
24
|
define_method(manager.accessor_name) { manager.has_one_to_batch_loader(self) }
|
21
25
|
when :has_many
|
@@ -32,22 +36,27 @@ module BatchLoaderActiveRecord
|
|
32
36
|
end
|
33
37
|
|
34
38
|
def belongs_to_lazy(*args)
|
35
|
-
belongs_to(*args).tap do
|
36
|
-
|
37
|
-
|
39
|
+
belongs_to(*args).tap do
|
40
|
+
reflection = reflect_on_all_associations.last
|
41
|
+
manager = AssociationManager.new(model: self, reflection: reflection)
|
42
|
+
if reflection.polymorphic?
|
43
|
+
define_method(manager.accessor_name) { manager.polymorphic_belongs_to_batch_loader(self) }
|
44
|
+
else
|
45
|
+
define_method(manager.accessor_name) { manager.belongs_to_batch_loader(self) }
|
46
|
+
end
|
38
47
|
end
|
39
48
|
end
|
40
49
|
|
41
50
|
def has_one_lazy(*args)
|
42
|
-
has_one(*args).tap do
|
43
|
-
manager = AssociationManager.new(model: self, reflection:
|
51
|
+
has_one(*args).tap do
|
52
|
+
manager = AssociationManager.new(model: self, reflection: reflect_on_all_associations.last)
|
44
53
|
define_method(manager.accessor_name) { manager.has_one_to_batch_loader(self) }
|
45
54
|
end
|
46
55
|
end
|
47
56
|
|
48
57
|
def has_many_lazy(*args)
|
49
|
-
has_many(*args).tap do
|
50
|
-
manager = AssociationManager.new(model: self, reflection:
|
58
|
+
has_many(*args).tap do
|
59
|
+
manager = AssociationManager.new(model: self, reflection: reflect_on_all_associations.last)
|
51
60
|
define_method(manager.accessor_name) do |instance_scope = nil|
|
52
61
|
manager.has_many_to_batch_loader(self, instance_scope)
|
53
62
|
end
|
@@ -55,7 +64,7 @@ module BatchLoaderActiveRecord
|
|
55
64
|
end
|
56
65
|
|
57
66
|
def has_and_belongs_to_many_lazy(*args)
|
58
|
-
has_and_belongs_to_many(*args).tap do
|
67
|
+
has_and_belongs_to_many(*args).tap do
|
59
68
|
manager = AssociationManager.new(model: self, reflection: reflect_on_all_associations.last)
|
60
69
|
define_method(manager.accessor_name) do |instance_scope = nil|
|
61
70
|
manager.has_and_belongs_to_many_to_batch_loader(self, instance_scope)
|
@@ -5,7 +5,6 @@ module BatchLoaderActiveRecord
|
|
5
5
|
def initialize(model:, reflection:)
|
6
6
|
@model = model
|
7
7
|
@reflection = reflection
|
8
|
-
assert_not_polymorphic
|
9
8
|
end
|
10
9
|
|
11
10
|
def accessor_name
|
@@ -19,9 +18,26 @@ module BatchLoaderActiveRecord
|
|
19
18
|
end
|
20
19
|
end
|
21
20
|
|
21
|
+
def polymorphic_belongs_to_batch_loader(instance)
|
22
|
+
foreign_id = instance.send(reflection.foreign_key) or return nil
|
23
|
+
foreign_type = instance.send(reflection.foreign_type)&.constantize or return nil
|
24
|
+
BatchLoader.for([foreign_type, foreign_id]).batch(key: batch_key) do |foreign_ids_types, loader|
|
25
|
+
foreign_ids_types
|
26
|
+
.group_by(&:first)
|
27
|
+
.each do |type, type_ids|
|
28
|
+
ids = type_ids.map(&:second)
|
29
|
+
klass_scope(type).where(id: ids).each do |instance|
|
30
|
+
loader.call([type, instance.id], instance)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
22
36
|
def has_one_to_batch_loader(instance)
|
23
37
|
BatchLoader.for(instance.id).batch(key: batch_key) do |model_ids, loader|
|
24
|
-
target_scope.where(reflection.foreign_key => model_ids)
|
38
|
+
relation = target_scope.where(reflection.foreign_key => model_ids)
|
39
|
+
relation = relation.where(reflection.type => model.to_s) if reflection.type
|
40
|
+
relation.each do |instance|
|
25
41
|
loader.call(instance.public_send(reflection.foreign_key), instance)
|
26
42
|
end
|
27
43
|
end
|
@@ -32,6 +48,7 @@ module BatchLoaderActiveRecord
|
|
32
48
|
custom_key += [instance_scope.to_sql.hash] unless instance_scope.nil?
|
33
49
|
BatchLoader.for(instance.id).batch(default_value: [], key: custom_key) do |model_ids, loader|
|
34
50
|
relation = relation_with_scope(instance_scope)
|
51
|
+
relation = relation.where(reflection.type => model.to_s) if reflection.type
|
35
52
|
if reflection.through_reflection
|
36
53
|
instances = fetch_for_model_ids(model_ids, relation: relation)
|
37
54
|
instances.each do |instance|
|
@@ -78,14 +95,16 @@ module BatchLoaderActiveRecord
|
|
78
95
|
end
|
79
96
|
end
|
80
97
|
|
81
|
-
def
|
82
|
-
|
98
|
+
def klass_scope(klass)
|
99
|
+
if reflection.scope.nil?
|
100
|
+
klass
|
101
|
+
else
|
102
|
+
klass.instance_eval(&reflection.scope)
|
103
|
+
end
|
83
104
|
end
|
84
105
|
|
85
|
-
def
|
86
|
-
|
87
|
-
raise NotImplementedError, "polymorphic associations are not yet supported (#{reflection.name})"
|
88
|
-
end
|
106
|
+
def batch_key
|
107
|
+
@batch_key ||= [model.table_name, reflection.name].freeze
|
89
108
|
end
|
90
109
|
|
91
110
|
def fetch_for_model_ids(ids, relation:)
|