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.
- checksums.yaml +4 -4
- data/LICENSE.txt +1 -1
- data/lib/store_base_sti_class/version.rb +1 -1
- data/lib/store_base_sti_class.rb +3 -11
- data/lib/{store_base_sti_class_for_5_2.rb → store_base_sti_class_for_6_1.rb} +22 -42
- data/lib/store_base_sti_class_for_7_0.rb +156 -0
- data/store_base_sti_class.gemspec +25 -24
- metadata +28 -78
- data/Appraisals +0 -15
- data/Gemfile +0 -3
- data/Gemfile.lock +0 -46
- data/README.md +0 -85
- data/Rakefile +0 -23
- data/gemfiles/rails_4.2.11.gemfile +0 -8
- data/gemfiles/rails_5.0.7.gemfile +0 -8
- data/gemfiles/rails_5.1.6.gemfile +0 -8
- data/gemfiles/rails_5.2.3.gemfile +0 -8
- data/gemfiles/rails_5.2.4.gemfile +0 -8
- data/gemfiles/rails_6.0.1.gemfile +0 -8
- data/lib/store_base_sti_class_for_4_2.rb +0 -360
- data/lib/store_base_sti_class_for_5_0.rb +0 -420
- data/lib/store_base_sti_class_for_5_1.rb +0 -367
@@ -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
|