ar-preloader 1.0.0 → 1.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 584f98e3ee0d6805aeeb6ad6b93403c0385c6ee5
4
- data.tar.gz: 864b63c2631cd805b72c4f513a095b312aad4177
3
+ metadata.gz: 2d895597b76cd8b4d0264a01a1edbd02dae18d12
4
+ data.tar.gz: aef0a1676a11b7a1d6d9c802415d52c976913342
5
5
  SHA512:
6
- metadata.gz: f261c86808b820ad41ace486d0bec69379bdbad03529c42451eece0888039e034e3af3778b5b946bd9dc6797f4049087b3099618bd71b5e61b30b93d9f54466f
7
- data.tar.gz: a480f9e5ea51d9ac98922194b9cfecf124b410c2a5226851bf1fdb7ad9b592830f24345de591d4951b4f3a3327afe86596f5fb0095418932f5ef28814a322541
6
+ metadata.gz: baf8de3beb914d202cb72431db24a71ccb0844d97353ce06211450aa2bebcc2d522ef43b83ea0dc52314378d0626966b1e720de409b8b8c796bc1381ca05ecd4
7
+ data.tar.gz: a7407f60a72dfacb079ac3426f0d97a39bc2b84050a8a211a12cf41899c202d4085edb600c6302770f93b2842c4de99773483223c7b1a88e760b7b54bf473bcb
data/lib/ar/preloader.rb CHANGED
@@ -9,6 +9,10 @@ module Ar
9
9
  case association
10
10
  when String, Symbol
11
11
  return klass.reflections.keys.include?(association.to_s)
12
+ when Array
13
+ association.each do |v|
14
+ return false unless Ar::Preloader.check_association_exists(klass, v)
15
+ end
12
16
  when Hash
13
17
  association.each_pair do |k,v|
14
18
  return false unless klass.reflections.keys.include?(k.to_s)
@@ -38,6 +42,8 @@ module Ar
38
42
  case association
39
43
  when String, Symbol
40
44
  klass = list.first.class
45
+ klass.send :attr_reader, "_#{association}".to_sym
46
+
41
47
  association_details = klass.reflections[association.to_s]
42
48
  association_klass = association_details.class_name.constantize
43
49
 
@@ -46,6 +52,11 @@ module Ar
46
52
  foreign_key = association_details.foreign_key
47
53
  association_pk = association_klass.primary_key
48
54
 
55
+ list.each do |obj|
56
+ instance_variable_name = "@_#{association}".to_sym
57
+ obj.instance_variable_set(instance_variable_name, [])
58
+ end
59
+
49
60
  query = <<-EOS
50
61
  SELECT
51
62
  distinct #{association_klass.table_name}.*
@@ -56,15 +67,14 @@ EOS
56
67
 
57
68
  association_list = association_klass.find_by_sql(query).to_a
58
69
 
59
- association_list.preload(*inner_associations)
70
+ if inner_associations.is_a?(Array)
71
+ association_list.preload(*inner_associations)
72
+ else
73
+ association_list.preload(inner_associations)
74
+ end
60
75
 
61
76
  list.each do |obj|
62
- klass.send :attr_reader, "_#{association}".to_sym
63
-
64
77
  instance_variable_name = "@_#{association}".to_sym
65
- if obj.instance_variable_get(instance_variable_name).nil?
66
- obj.instance_variable_set(instance_variable_name, [])
67
- end
68
78
 
69
79
  association_list.select{ |e| e[foreign_key.to_sym] == obj[klass.primary_key.to_sym] }.each do |association_obj|
70
80
  each_list = obj.instance_variable_get(instance_variable_name)
@@ -76,6 +86,10 @@ EOS
76
86
  foreign_key = association_details.foreign_key
77
87
  association_pk = association_klass.primary_key
78
88
 
89
+ if list.map{ |e| e[foreign_key.to_sym] }.compact.length == 0
90
+ return true
91
+ end
92
+
79
93
  query = <<-EOS
80
94
  SELECT
81
95
  distinct #{association_klass.table_name}.*
@@ -86,22 +100,73 @@ EOS
86
100
 
87
101
  association_list = association_klass.find_by_sql(query).to_a
88
102
 
89
- association_list.preload(*inner_associations)
103
+ if inner_associations.is_a?(Array)
104
+ association_list.preload(*inner_associations)
105
+ else
106
+ association_list.preload(inner_associations)
107
+ end
90
108
 
91
109
  association_map = association_list.map{ |e| [e[e.class.primary_key.to_sym], e] }.to_h
92
110
 
93
111
  list.each do |obj|
94
112
  if obj[foreign_key.to_sym].present? && association_map[obj[foreign_key.to_sym]].present?
95
- klass.send :attr_reader, "_#{association}".to_sym
96
113
  obj.instance_variable_set( "@_#{association}".to_sym, association_map[obj[foreign_key.to_sym]] )
97
114
  end
98
115
  end
116
+ when ActiveRecord::Reflection::HasAndBelongsToManyReflection
117
+ foreign_key = association_details.foreign_key
118
+ association_foreign_key = association_details.association_foreign_key
119
+ join_table = association_details.join_table
120
+
121
+ list.each do |obj|
122
+ instance_variable_name = "@_#{association}".to_sym
123
+ obj.instance_variable_set(instance_variable_name, [])
124
+ end
125
+
126
+ join_query = <<-EOS
127
+ SELECT
128
+ #{join_table}.#{foreign_key},
129
+ #{join_table}.#{association_foreign_key}
130
+ FROM #{join_table}
131
+ WHERE #{join_table}.#{foreign_key} IN (#{ list.map{ |e| e[klass.primary_key.to_sym].try(:to_s) }.compact.join(",") })
132
+
133
+ EOS
134
+ join_entries = ActiveRecord::Base.connection.execute(join_query).to_a
135
+
136
+ query = <<-EOS
137
+ SELECT
138
+ distinct #{association_klass.table_name}.*
139
+ FROM #{association_klass.table_name}
140
+ INNER JOIN #{join_table} ON #{join_table}.#{association_foreign_key} = #{association_klass.table_name}.#{association_klass.primary_key}
141
+ WHERE #{join_table}.#{foreign_key} IN (#{ list.map{ |e| e[klass.primary_key.to_sym].try(:to_s) }.compact.join(",") })
142
+
143
+ EOS
144
+
145
+ association_list = association_klass.find_by_sql(query).to_a
146
+
147
+ if inner_associations.is_a?(Array)
148
+ association_list.preload(*inner_associations)
149
+ else
150
+ association_list.preload(inner_associations)
151
+ end
152
+
153
+ list.each do |obj|
154
+ instance_variable_name = "@_#{association}".to_sym
155
+
156
+ association_key_list = join_entries.select{ |e| e[0] == obj[klass.primary_key.to_s] }.map(&:last)
157
+
158
+ association_list.select{ |e| association_key_list.include?( e[association_klass.primary_key.to_s] ) }.each do |association_obj|
159
+ each_list = obj.instance_variable_get(instance_variable_name)
160
+ each_list << association_obj
161
+ obj.instance_variable_set(instance_variable_name, each_list)
162
+ end
163
+ end
99
164
  else
100
- raise Ar::Preloader::Error.new("Unsupported assocation type: '#{assocation}'")
165
+ raise Ar::Preloader::Error.new("Unsupported association type: '#{association}'")
101
166
  end
102
167
  when Hash
103
168
  association.each_pair do |k,v|
104
- Ar::Preloader.preload_association(list, k, [v])
169
+ Ar::Preloader.preload_association(list, k, v)
105
170
  end
106
171
  end
107
172
  end
@@ -115,6 +180,7 @@ class Array
115
180
  raise Ar::Preloader::Error.new("Cannot preload. Mixed type lists are not supported.") if (self.map(&:class).uniq.count > 1)
116
181
  raise Ar::Preloader::Error.new("Cannot preload. At least one element in array is not an ActiveRecord object.") if (self.reject{|e| e.is_a?(ActiveRecord::Base) }.count > 0)
117
182
 
183
+
118
184
  args.each do |arg|
119
185
  raise Ar::Preloader::Error.new("Cannot find association '#{arg}' on one or more of the ActiveRecord objects.") if (self.reject{|e| Ar::Preloader.check_association_exists(e.class, arg) }.count > 0)
120
186
  end
@@ -1,5 +1,5 @@
1
1
  module Ar
2
2
  module Preloader
3
- VERSION = "1.0.0"
3
+ VERSION = "1.1.0"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ar-preloader
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ajith Hussain