batch-loader-active-record 0.4.3 → 0.5.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.
- 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:)
|