store_base_sti_class 2.0.3 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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