store_base_sti_class 2.0.1 → 3.0.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.
@@ -1,420 +0,0 @@
1
- require 'active_record/associations/join_dependency/join_part'
2
-
3
- if ActiveRecord::VERSION::STRING =~ /^5\.0/
4
- module ActiveRecord
5
-
6
- class Base
7
- class_attribute :store_base_sti_class
8
- self.store_base_sti_class = true
9
- end
10
-
11
- class PredicateBuilder
12
- class AssociationQueryHandler
13
- def call(attribute, value)
14
- queries = {}
15
-
16
- table = value.associated_table
17
- if value.base_class
18
- queries[table.association_foreign_type.to_s] = ActiveRecord::Base.store_base_sti_class ? value.base_class.name : value.value.class.name
19
- end
20
-
21
- queries[table.association_foreign_key.to_s] = value.ids
22
- predicate_builder.build_from_hash(queries)
23
- end
24
- end
25
- end
26
-
27
- module Associations
28
- class Association
29
- private
30
-
31
- def creation_attributes
32
- attributes = {}
33
-
34
- if (reflection.has_one? || reflection.collection?) && !options[:through]
35
- attributes[reflection.foreign_key] = owner[reflection.active_record_primary_key]
36
-
37
- if reflection.options[:as]
38
- # START PATCH
39
- # original:
40
- # attributes[reflection.type] = owner.class.base_class.name
41
-
42
- attributes[reflection.type] = ActiveRecord::Base.store_base_sti_class ? owner.class.base_class.name : owner.class.name
43
- # END PATCH
44
- end
45
- end
46
-
47
- attributes
48
- end
49
- end
50
-
51
- class JoinDependency # :nodoc:
52
- class JoinAssociation < JoinPart # :nodoc:
53
- def join_constraints(foreign_table, foreign_klass, node, join_type, tables, scope_chain, chain)
54
- joins = []
55
- binds = []
56
- tables = tables.reverse
57
-
58
- scope_chain_index = 0
59
- scope_chain = scope_chain.reverse
60
-
61
- # The chain starts with the target table, but we want to end with it here (makes
62
- # more sense in this context), so we reverse
63
- chain.reverse_each do |reflection|
64
- table = tables.shift
65
- klass = reflection.klass
66
-
67
- join_keys = reflection.join_keys(klass)
68
- key = join_keys.key
69
- foreign_key = join_keys.foreign_key
70
-
71
- constraint = build_constraint(klass, table, key, foreign_table, foreign_key)
72
-
73
- predicate_builder = PredicateBuilder.new(TableMetadata.new(klass, table))
74
- scope_chain_items = scope_chain[scope_chain_index].map do |item|
75
- if item.is_a?(Relation)
76
- item
77
- else
78
- ActiveRecord::Relation.create(klass, table, predicate_builder)
79
- .instance_exec(node, &item)
80
- end
81
- end
82
- scope_chain_index += 1
83
-
84
- klass_scope =
85
- if klass.current_scope
86
- klass.current_scope.clone
87
- else
88
- relation = ActiveRecord::Relation.create(
89
- klass,
90
- table,
91
- predicate_builder,
92
- )
93
- klass.send(:build_default_scope, relation)
94
- end
95
- scope_chain_items.concat [klass_scope].compact
96
-
97
- rel = scope_chain_items.inject(scope_chain_items.shift) do |left, right|
98
- left.merge right
99
- end
100
-
101
- if rel && !rel.arel.constraints.empty?
102
- binds += rel.bound_attributes
103
- constraint = constraint.and rel.arel.constraints
104
- end
105
-
106
- if reflection.type
107
- # START PATCH
108
- # original:
109
- # value = foreign_klass.base_class.name
110
- value = ActiveRecord::Base.store_base_sti_class ? foreign_klass.base_class.name : foreign_klass.name
111
- # END PATCH
112
- column = klass.columns_hash[reflection.type.to_s]
113
-
114
- binds << Relation::QueryAttribute.new(column.name, value, klass.type_for_attribute(column.name))
115
- constraint = constraint.and klass.arel_attribute(reflection.type, table).eq(Arel::Nodes::BindParam.new)
116
- end
117
-
118
- joins << table.create_join(table, table.create_on(constraint), join_type)
119
-
120
- # The current table in this iteration becomes the foreign table in the next
121
- foreign_table, foreign_klass = table, klass
122
- end
123
-
124
- JoinInformation.new joins, binds
125
- end
126
- end
127
- end
128
-
129
- class BelongsToPolymorphicAssociation
130
- private
131
-
132
- def replace_keys(record)
133
- super
134
-
135
- # START PATCH
136
- # original:
137
- # owner[reflection.foreign_type] = record.class.base_class.name
138
-
139
- owner[reflection.foreign_type] = ActiveRecord::Base.store_base_sti_class ? record.class.base_class.name : record.class.name
140
-
141
- # END PATCH
142
- end
143
- end
144
-
145
- class Preloader
146
- class Association
147
- private
148
-
149
- def build_scope
150
- scope = klass.unscoped
151
-
152
- values = reflection_scope.values
153
- preload_values = preload_scope.values
154
-
155
- scope.where_clause = reflection_scope.where_clause + preload_scope.where_clause
156
- scope.references_values = Array(values[:references]) + Array(preload_values[:references])
157
-
158
- if preload_values[:select] || values[:select]
159
- scope._select!(preload_values[:select] || values[:select])
160
- end
161
- scope.includes! preload_values[:includes] || values[:includes]
162
- if preload_scope.joins_values.any?
163
- scope.joins!(preload_scope.joins_values)
164
- else
165
- scope.joins!(reflection_scope.joins_values)
166
- end
167
-
168
- if order_values = preload_values[:order] || values[:order]
169
- scope.order!(order_values)
170
- end
171
-
172
- if preload_values[:reordering] || values[:reordering]
173
- scope.reordering_value = true
174
- end
175
-
176
- if preload_values[:readonly] || values[:readonly]
177
- scope.readonly!
178
- end
179
-
180
- if options[:as]
181
- # START PATCH
182
- # original:
183
- # scope.where!(klass.table_name => { reflection.type => model.base_class.sti_name })
184
-
185
- scope.where!(klass.table_name => { reflection.type => ActiveRecord::Base.store_base_sti_class ? model.base_class.sti_name : model.sti_name })
186
-
187
- # END PATCH
188
- end
189
-
190
- scope.unscope_values = Array(values[:unscope]) + Array(preload_values[:unscope])
191
- klass.default_scoped.merge(scope)
192
- end
193
- end
194
-
195
- module ThroughAssociation
196
- private
197
-
198
- def through_scope
199
- scope = through_reflection.klass.unscoped
200
-
201
- if options[:source_type]
202
- # BEGIN PATCH
203
- # original: scope.where! reflection.foreign_type => options[:source_type]
204
-
205
- adjusted_foreign_type =
206
- if ActiveRecord::Base.store_base_sti_class
207
- options[:source_type]
208
- else
209
- ([options[:source_type].constantize] + options[:source_type].constantize.descendants).map(&:to_s)
210
- end
211
-
212
- scope.where! reflection.foreign_type => adjusted_foreign_type
213
-
214
- # END PATCH
215
- else
216
- unless reflection_scope.where_clause.empty?
217
- scope.includes_values = Array(reflection_scope.values[:includes] || options[:source])
218
- scope.where_clause = reflection_scope.where_clause
219
- end
220
-
221
- scope.references! reflection_scope.values[:references]
222
- if scope.eager_loading? && order_values = reflection_scope.values[:order]
223
- scope = scope.order(order_values)
224
- end
225
- end
226
-
227
- scope
228
- end
229
- end
230
- end
231
-
232
- class AssociationScope
233
-
234
- def self.get_bind_values(owner, chain)
235
- binds = []
236
- last_reflection = chain.last
237
-
238
- binds << last_reflection.join_id_for(owner)
239
- if last_reflection.type
240
- # START PATCH
241
- # original: binds << owner.class.base_class.name
242
- binds << (ActiveRecord::Base.store_base_sti_class ? owner.class.base_class.name : owner.class.name)
243
- # END PATCH
244
- end
245
-
246
- chain.each_cons(2).each do |reflection, next_reflection|
247
- if reflection.type
248
- # START PATCH
249
- # original: binds << next_reflection.klass.base_class.name
250
- binds << (ActiveRecord::Base.store_base_sti_class ? next_reflection.klass.base_class.name : next_reflection.klass.name)
251
- # END PATCH
252
- end
253
- end
254
- binds
255
- end
256
-
257
- private
258
-
259
- def next_chain_scope(scope, table, reflection, association_klass, foreign_table, next_reflection)
260
- join_keys = reflection.join_keys(association_klass)
261
- key = join_keys.key
262
- foreign_key = join_keys.foreign_key
263
-
264
- constraint = table[key].eq(foreign_table[foreign_key])
265
-
266
- if reflection.type
267
- # BEGIN PATCH
268
- # original:
269
- # value = transform_value(next_reflection.klass.base_class.name)
270
- # scope = scope.where(table.name => { reflection.type => value })
271
- if ActiveRecord::Base.store_base_sti_class
272
- value = transform_value(next_reflection.klass.base_class.name)
273
- else
274
- klass = next_reflection.klass
275
- value = ([klass] + klass.descendants).map(&:name)
276
- end
277
- scope = scope.where(table.name => { reflection.type => value })
278
- # END PATCH
279
- end
280
-
281
- scope = scope.joins(join(foreign_table, constraint))
282
- end
283
-
284
- def last_chain_scope(scope, table, reflection, owner, association_klass)
285
- join_keys = reflection.join_keys(association_klass)
286
- key = join_keys.key
287
- foreign_key = join_keys.foreign_key
288
-
289
- value = transform_value(owner[foreign_key])
290
- scope = scope.where(table.name => { key => value })
291
-
292
- if reflection.type
293
- # BEGIN PATCH
294
- # polymorphic_type = transform_value(owner.class.base_class.name)
295
- polymorphic_type = transform_value(ActiveRecord::Base.store_base_sti_class ? owner.class.base_class.name : owner.class.name)
296
- # END PATCH
297
- scope = scope.where(table.name => { reflection.type => polymorphic_type })
298
- end
299
-
300
- scope
301
- end
302
-
303
- end
304
-
305
- module ThroughAssociation
306
- private
307
-
308
- def construct_join_attributes(*records)
309
- ensure_mutable
310
-
311
- if source_reflection.association_primary_key(reflection.klass) == reflection.klass.primary_key
312
- join_attributes = { source_reflection.name => records }
313
- else
314
- join_attributes = {
315
- source_reflection.foreign_key =>
316
- records.map { |record|
317
- record.send(source_reflection.association_primary_key(reflection.klass))
318
- }
319
- }
320
- end
321
-
322
- if options[:source_type]
323
-
324
- # START PATCH
325
- # original:
326
- # join_attributes[source_reflection.foreign_type] =
327
- # records.map { |record| record.class.base_class.name }
328
-
329
- join_attributes[source_reflection.foreign_type] =
330
- records.map { |record| ActiveRecord::Base.store_base_sti_class ? record.class.base_class.name : record.class.name }
331
-
332
- # END PATCH
333
- end
334
-
335
- if records.count == 1
336
- Hash[join_attributes.map { |k, v| [k, v.first] }]
337
- else
338
- join_attributes
339
- end
340
- end
341
- end
342
-
343
- class HasManyThroughAssociation
344
- private
345
-
346
- def build_through_record(record)
347
- @through_records[record.object_id] ||= begin
348
- ensure_mutable
349
-
350
- through_record = through_association.build(*options_for_through_record)
351
- through_record.send("#{source_reflection.name}=", record)
352
-
353
- # START PATCH
354
- if ActiveRecord::Base.store_base_sti_class
355
- if options[:source_type]
356
- through_record.send("#{source_reflection.foreign_type}=", options[:source_type])
357
- end
358
- end
359
- # END PATCH
360
-
361
- through_record
362
- end
363
- end
364
- end
365
- end
366
-
367
- module Reflection
368
- class PolymorphicReflection
369
- def source_type_info
370
- type = @previous_reflection.foreign_type
371
- source_type = @previous_reflection.options[:source_type]
372
-
373
- # START PATCH
374
- adjusted_source_type =
375
- if ActiveRecord::Base.store_base_sti_class
376
- source_type
377
- else
378
- ([source_type.constantize] + source_type.constantize.descendants).map(&:to_s)
379
- end
380
- # END PATCH
381
-
382
- lambda { |object| where(type => adjusted_source_type) }
383
- end
384
- end
385
-
386
- class ThroughReflection
387
- def scope_chain
388
- @scope_chain ||= begin
389
- scope_chain = source_reflection.scope_chain.map(&:dup)
390
-
391
- # Add to it the scope from this reflection (if any)
392
- scope_chain.first << scope if scope
393
-
394
- through_scope_chain = through_reflection.scope_chain.map(&:dup)
395
-
396
- if options[:source_type]
397
- type = foreign_type
398
- # START PATCH
399
- # original: source_type = options[:source_type]
400
- source_type =
401
- if ActiveRecord::Base.store_base_sti_class
402
- options[:source_type]
403
- else
404
- ([options[:source_type].constantize] + options[:source_type].constantize.descendants).map(&:to_s)
405
- end
406
- # END PATCH
407
- through_scope_chain.first << lambda { |object|
408
- where(type => source_type)
409
- }
410
- end
411
-
412
- # Recursively fill out the rest of the array from the through reflection
413
- scope_chain + through_scope_chain
414
- end
415
- end
416
- end
417
- end
418
- end
419
-
420
- end