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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 20293fa5d03f7ea6bf4639ccef5b99287cf2988c
4
- data.tar.gz: 170d3adfc3c7b8b9513a5bffb5b358f3e9307736
3
+ metadata.gz: f442e69779971d6ff0f8a67e79a9b1afd68ee1d5
4
+ data.tar.gz: 5b457b1b5ac6a0bce872ca6a11b9778a1b67bb38
5
5
  SHA512:
6
- metadata.gz: 39ee2cd6379fe68db021a13dd2a1433ffc96d2bd9f2c6677850c1fd34b34a27f87e9f160aea8027d61fe2a5ce1992a24c6f7e086012f6cc1cca8308c814c54b6
7
- data.tar.gz: daf102a9d873e4f9cca57c1569e7ac5673cf3834013c381a69070d2be27b5011a6e428b7d0d00c402bac1265723a7ffa6e4c10fa3ec07714dd07cedd2ad388ff
6
+ metadata.gz: 88cde79729754c86cfb0af302fc5fed3e68b679f9a17bb1b9615fcec2ce9b1e6d229b84203ec106df35e04f9704d7a2613c092d629513f8e185cb0b7ba1611bb
7
+ data.tar.gz: 4b1ac2601cbd5cf2515b4b811211222bf6dd84b7dd425488308b7d33c4a30e7974457faad348a6180657f0ec5a8b6d69dd0f99876bdf7807eb6821f3d2c5cc00
@@ -4,6 +4,10 @@ Unreleased
4
4
 
5
5
  * none
6
6
 
7
+ v0.5.0
8
+
9
+ * support polymorphic associations
10
+
7
11
  v0.4.3
8
12
 
9
13
  * fix dependency to activerecord and builds
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- batch-loader-active-record (0.4.3)
4
+ batch-loader-active-record (0.5.0)
5
5
  activerecord (>= 4.2.0, < 5.3.0)
6
6
  batch-loader (~> 1.2.0)
7
7
 
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
- Note that it doesn't yet support all cases handled by Active Record associations, 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.
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
 
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- batch-loader-active-record (0.4.3)
4
+ batch-loader-active-record (0.5.0)
5
5
  activerecord (>= 4.2.0, < 5.3.0)
6
6
  batch-loader (~> 1.2.0)
7
7
 
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- batch-loader-active-record (0.4.3)
4
+ batch-loader-active-record (0.5.0)
5
5
  activerecord (>= 4.2.0, < 5.3.0)
6
6
  batch-loader (~> 1.2.0)
7
7
 
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- batch-loader-active-record (0.4.3)
4
+ batch-loader-active-record (0.5.0)
5
5
  activerecord (>= 4.2.0, < 5.3.0)
6
6
  batch-loader (~> 1.2.0)
7
7
 
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- batch-loader-active-record (0.4.3)
4
+ batch-loader-active-record (0.5.0)
5
5
  activerecord (>= 4.2.0, < 5.3.0)
6
6
  batch-loader (~> 1.2.0)
7
7
 
@@ -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
- define_method(manager.accessor_name) { manager.belongs_to_batch_loader(self) }
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 |reflections|
36
- manager = AssociationManager.new(model: self, reflection: reflections.values.last)
37
- define_method(manager.accessor_name) { manager.belongs_to_batch_loader(self) }
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 |reflections|
43
- manager = AssociationManager.new(model: self, reflection: reflections.values.last)
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 |reflections|
50
- manager = AssociationManager.new(model: self, reflection: reflections.values.last)
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 |reflections|
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).each do |instance|
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 batch_key
82
- @batch_key ||= [model.table_name, reflection.name].freeze
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 assert_not_polymorphic
86
- if reflection.polymorphic? || reflection.options.has_key?(:as) || reflection.options.has_key?(:source_type)
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:)
@@ -1,3 +1,3 @@
1
1
  module BatchLoaderActiveRecord
2
- VERSION = "0.4.3"
2
+ VERSION = "0.5.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: batch-loader-active-record
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.3
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - mathieul