store_base_sti_class 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 +4 -4
- data/Appraisals +5 -0
- data/Gemfile.lock +17 -17
- data/gemfiles/rails_4.2.8.gemfile +7 -0
- data/gemfiles/rails_5.0.2.gemfile +7 -0
- data/gemfiles/rails_5.0.3.gemfile +7 -0
- data/gemfiles/rails_5.1.0.gemfile +7 -0
- data/gemfiles/rails_5.1.1.gemfile +7 -0
- data/lib/store_base_sti_class/version.rb +1 -1
- data/lib/store_base_sti_class.rb +2 -0
- data/lib/store_base_sti_class_for_5_1.rb +351 -0
- metadata +9 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 82287e5bc596474535ed2f815cb34cbfe2abb089
|
4
|
+
data.tar.gz: 3f1999f09ccaa5f380cb4230f4cba6eb81c2dc2e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fccef96be8809df757d5936781d2fe4811b5d4fd56d5b53fd026448c35d86288f4c10327b1562b4478e360f7e38f2c8406a7b3995b2364ffff05cfaf231b8d00
|
7
|
+
data.tar.gz: 94e2b0a7c09cfcd051f791077636c9d0301687cd713ce0d899efc39994fbf07e5604e9f38a3ecd02ec008774f43694f5ed354103983e193fc1d7e0f25bade606
|
data/Appraisals
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,39 +1,36 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
store_base_sti_class (1.
|
4
|
+
store_base_sti_class (1.1.0)
|
5
5
|
activerecord (>= 4.0)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
|
-
activemodel (
|
11
|
-
activesupport (=
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
10
|
+
activemodel (5.1.1)
|
11
|
+
activesupport (= 5.1.1)
|
12
|
+
activerecord (5.1.1)
|
13
|
+
activemodel (= 5.1.1)
|
14
|
+
activesupport (= 5.1.1)
|
15
|
+
arel (~> 8.0)
|
16
|
+
activesupport (5.1.1)
|
17
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
18
18
|
i18n (~> 0.7)
|
19
|
-
json (~> 1.7, >= 1.7.7)
|
20
19
|
minitest (~> 5.1)
|
21
|
-
thread_safe (~> 0.3, >= 0.3.4)
|
22
20
|
tzinfo (~> 1.1)
|
23
21
|
appraisal (2.1.0)
|
24
22
|
bundler
|
25
23
|
rake
|
26
24
|
thor (>= 0.14.0)
|
27
|
-
arel (
|
28
|
-
|
29
|
-
i18n (0.8.
|
30
|
-
json (1.8.6)
|
25
|
+
arel (8.0.0)
|
26
|
+
concurrent-ruby (1.0.5)
|
27
|
+
i18n (0.8.1)
|
31
28
|
minitest (5.8.4)
|
32
29
|
rake (11.1.2)
|
33
30
|
sqlite3 (1.3.11)
|
34
31
|
thor (0.19.1)
|
35
|
-
thread_safe (0.3.
|
36
|
-
tzinfo (1.2.
|
32
|
+
thread_safe (0.3.6)
|
33
|
+
tzinfo (1.2.3)
|
37
34
|
thread_safe (~> 0.1)
|
38
35
|
|
39
36
|
PLATFORMS
|
@@ -45,3 +42,6 @@ DEPENDENCIES
|
|
45
42
|
minitest (>= 4.0)
|
46
43
|
sqlite3
|
47
44
|
store_base_sti_class!
|
45
|
+
|
46
|
+
BUNDLED WITH
|
47
|
+
1.14.6
|
data/lib/store_base_sti_class.rb
CHANGED
@@ -8,6 +8,8 @@ elsif ActiveRecord::VERSION::STRING =~ /^4\.2/
|
|
8
8
|
require 'store_base_sti_class_for_4_2'
|
9
9
|
elsif ActiveRecord::VERSION::STRING =~ /^5\.0/
|
10
10
|
require 'store_base_sti_class_for_5_0'
|
11
|
+
elsif ActiveRecord::VERSION::STRING =~ /^5\.1/
|
12
|
+
require 'store_base_sti_class_for_5_1'
|
11
13
|
end
|
12
14
|
|
13
15
|
module StoreBaseSTIClass
|
@@ -0,0 +1,351 @@
|
|
1
|
+
require 'active_record/associations/join_dependency/join_part'
|
2
|
+
|
3
|
+
if ActiveRecord::VERSION::STRING =~ /^5\.1/
|
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
|
+
module Associations
|
12
|
+
class Association
|
13
|
+
private
|
14
|
+
|
15
|
+
def creation_attributes
|
16
|
+
attributes = {}
|
17
|
+
|
18
|
+
if (reflection.has_one? || reflection.collection?) && !options[:through]
|
19
|
+
attributes[reflection.foreign_key] = owner[reflection.active_record_primary_key]
|
20
|
+
|
21
|
+
if reflection.options[:as]
|
22
|
+
# START PATCH
|
23
|
+
# original:
|
24
|
+
# attributes[reflection.type] = owner.class.base_class.name
|
25
|
+
|
26
|
+
attributes[reflection.type] = ActiveRecord::Base.store_base_sti_class ? owner.class.base_class.name : owner.class.name
|
27
|
+
# END PATCH
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
attributes
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class JoinDependency # :nodoc:
|
36
|
+
class JoinAssociation < JoinPart # :nodoc:
|
37
|
+
def join_constraints(foreign_table, foreign_klass, join_type, tables, chain)
|
38
|
+
joins = []
|
39
|
+
binds = []
|
40
|
+
tables = tables.reverse
|
41
|
+
|
42
|
+
# The chain starts with the target table, but we want to end with it here (makes
|
43
|
+
# more sense in this context), so we reverse
|
44
|
+
chain.reverse_each do |reflection|
|
45
|
+
table = tables.shift
|
46
|
+
klass = reflection.klass
|
47
|
+
|
48
|
+
join_keys = reflection.join_keys
|
49
|
+
key = join_keys.key
|
50
|
+
foreign_key = join_keys.foreign_key
|
51
|
+
|
52
|
+
constraint = build_constraint(klass, table, key, foreign_table, foreign_key)
|
53
|
+
|
54
|
+
predicate_builder = PredicateBuilder.new(TableMetadata.new(klass, table))
|
55
|
+
scope_chain_items = reflection.join_scopes(table, predicate_builder)
|
56
|
+
klass_scope = reflection.klass_join_scope(table, predicate_builder)
|
57
|
+
|
58
|
+
scope_chain_items.concat [klass_scope].compact
|
59
|
+
|
60
|
+
rel = scope_chain_items.inject(scope_chain_items.shift) do |left, right|
|
61
|
+
left.merge right
|
62
|
+
end
|
63
|
+
|
64
|
+
if rel && !rel.arel.constraints.empty?
|
65
|
+
binds += rel.bound_attributes
|
66
|
+
constraint = constraint.and rel.arel.constraints
|
67
|
+
end
|
68
|
+
|
69
|
+
if reflection.type
|
70
|
+
# START PATCH
|
71
|
+
# original:
|
72
|
+
# value = foreign_klass.base_class.name
|
73
|
+
value = ActiveRecord::Base.store_base_sti_class ? foreign_klass.base_class.name : foreign_klass.name
|
74
|
+
# END PATCH
|
75
|
+
column = klass.columns_hash[reflection.type.to_s]
|
76
|
+
|
77
|
+
binds << Relation::QueryAttribute.new(column.name, value, klass.type_for_attribute(column.name))
|
78
|
+
constraint = constraint.and klass.arel_attribute(reflection.type, table).eq(Arel::Nodes::BindParam.new)
|
79
|
+
end
|
80
|
+
|
81
|
+
joins << table.create_join(table, table.create_on(constraint), join_type)
|
82
|
+
|
83
|
+
# The current table in this iteration becomes the foreign table in the next
|
84
|
+
foreign_table, foreign_klass = table, klass
|
85
|
+
end
|
86
|
+
|
87
|
+
JoinInformation.new joins, binds
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
class BelongsToPolymorphicAssociation
|
93
|
+
private
|
94
|
+
|
95
|
+
def replace_keys(record)
|
96
|
+
super
|
97
|
+
|
98
|
+
# START PATCH
|
99
|
+
# original:
|
100
|
+
# owner[reflection.foreign_type] = record.class.base_class.name
|
101
|
+
|
102
|
+
owner[reflection.foreign_type] = ActiveRecord::Base.store_base_sti_class ? record.class.base_class.name : record.class.name
|
103
|
+
|
104
|
+
# END PATCH
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
class Preloader
|
109
|
+
class Association
|
110
|
+
private
|
111
|
+
|
112
|
+
def build_scope
|
113
|
+
scope = klass.unscoped
|
114
|
+
|
115
|
+
values = reflection_scope.values
|
116
|
+
preload_values = preload_scope.values
|
117
|
+
|
118
|
+
scope.where_clause = reflection_scope.where_clause + preload_scope.where_clause
|
119
|
+
scope.references_values = Array(values[:references]) + Array(preload_values[:references])
|
120
|
+
|
121
|
+
if preload_values[:select] || values[:select]
|
122
|
+
scope._select!(preload_values[:select] || values[:select])
|
123
|
+
end
|
124
|
+
scope.includes! preload_values[:includes] || values[:includes]
|
125
|
+
if preload_scope.joins_values.any?
|
126
|
+
scope.joins!(preload_scope.joins_values)
|
127
|
+
else
|
128
|
+
scope.joins!(reflection_scope.joins_values)
|
129
|
+
end
|
130
|
+
|
131
|
+
if order_values = preload_values[:order] || values[:order]
|
132
|
+
scope.order!(order_values)
|
133
|
+
end
|
134
|
+
|
135
|
+
if preload_values[:reordering] || values[:reordering]
|
136
|
+
scope.reordering_value = true
|
137
|
+
end
|
138
|
+
|
139
|
+
if preload_values[:readonly] || values[:readonly]
|
140
|
+
scope.readonly!
|
141
|
+
end
|
142
|
+
|
143
|
+
if options[:as]
|
144
|
+
# START PATCH
|
145
|
+
# original:
|
146
|
+
# scope.where!(klass.table_name => { reflection.type => model.base_class.sti_name })
|
147
|
+
|
148
|
+
scope.where!(klass.table_name => { reflection.type => ActiveRecord::Base.store_base_sti_class ? model.base_class.sti_name : model.sti_name })
|
149
|
+
|
150
|
+
# END PATCH
|
151
|
+
end
|
152
|
+
|
153
|
+
scope.unscope_values = Array(values[:unscope]) + Array(preload_values[:unscope])
|
154
|
+
klass.default_scoped.merge(scope)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
module ThroughAssociation
|
159
|
+
private
|
160
|
+
|
161
|
+
def through_scope
|
162
|
+
scope = through_reflection.klass.unscoped
|
163
|
+
|
164
|
+
if options[:source_type]
|
165
|
+
# BEGIN PATCH
|
166
|
+
# original: scope.where! reflection.foreign_type => options[:source_type]
|
167
|
+
|
168
|
+
adjusted_foreign_type =
|
169
|
+
if ActiveRecord::Base.store_base_sti_class
|
170
|
+
options[:source_type]
|
171
|
+
else
|
172
|
+
([options[:source_type].constantize] + options[:source_type].constantize.descendants).map(&:to_s)
|
173
|
+
end
|
174
|
+
|
175
|
+
scope.where! reflection.foreign_type => adjusted_foreign_type
|
176
|
+
|
177
|
+
# END PATCH
|
178
|
+
else
|
179
|
+
unless reflection_scope.where_clause.empty?
|
180
|
+
scope.includes_values = Array(reflection_scope.values[:includes] || options[:source])
|
181
|
+
scope.where_clause = reflection_scope.where_clause
|
182
|
+
end
|
183
|
+
|
184
|
+
scope.references! reflection_scope.values[:references]
|
185
|
+
if scope.eager_loading? && order_values = reflection_scope.values[:order]
|
186
|
+
scope = scope.order(order_values)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
scope
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
class AssociationScope
|
196
|
+
|
197
|
+
def self.get_bind_values(owner, chain)
|
198
|
+
binds = []
|
199
|
+
last_reflection = chain.last
|
200
|
+
|
201
|
+
binds << last_reflection.join_id_for(owner)
|
202
|
+
if last_reflection.type
|
203
|
+
# START PATCH
|
204
|
+
# original: binds << owner.class.base_class.name
|
205
|
+
binds << (ActiveRecord::Base.store_base_sti_class ? owner.class.base_class.name : owner.class.name)
|
206
|
+
# END PATCH
|
207
|
+
end
|
208
|
+
|
209
|
+
chain.each_cons(2).each do |reflection, next_reflection|
|
210
|
+
if reflection.type
|
211
|
+
# START PATCH
|
212
|
+
# original: binds << next_reflection.klass.base_class.name
|
213
|
+
binds << (ActiveRecord::Base.store_base_sti_class ? next_reflection.klass.base_class.name : next_reflection.klass.name)
|
214
|
+
# END PATCH
|
215
|
+
end
|
216
|
+
end
|
217
|
+
binds
|
218
|
+
end
|
219
|
+
|
220
|
+
private
|
221
|
+
|
222
|
+
def next_chain_scope(scope, table, reflection, foreign_table, next_reflection)
|
223
|
+
join_keys = reflection.join_keys
|
224
|
+
key = join_keys.key
|
225
|
+
foreign_key = join_keys.foreign_key
|
226
|
+
|
227
|
+
constraint = table[key].eq(foreign_table[foreign_key])
|
228
|
+
|
229
|
+
if reflection.type
|
230
|
+
# BEGIN PATCH
|
231
|
+
# original:
|
232
|
+
# value = transform_value(next_reflection.klass.base_class.name)
|
233
|
+
# scope = scope.where(table.name => { reflection.type => value })
|
234
|
+
if ActiveRecord::Base.store_base_sti_class
|
235
|
+
value = transform_value(next_reflection.klass.base_class.name)
|
236
|
+
else
|
237
|
+
klass = next_reflection.klass
|
238
|
+
value = ([klass] + klass.descendants).map(&:name)
|
239
|
+
end
|
240
|
+
scope = scope.where(table.name => { reflection.type => value })
|
241
|
+
# END PATCH
|
242
|
+
end
|
243
|
+
|
244
|
+
scope = scope.joins(join(foreign_table, constraint))
|
245
|
+
end
|
246
|
+
|
247
|
+
def last_chain_scope(scope, table, reflection, owner)
|
248
|
+
join_keys = reflection.join_keys
|
249
|
+
key = join_keys.key
|
250
|
+
foreign_key = join_keys.foreign_key
|
251
|
+
|
252
|
+
value = transform_value(owner[foreign_key])
|
253
|
+
scope = scope.where(table.name => { key => value })
|
254
|
+
|
255
|
+
if reflection.type
|
256
|
+
# BEGIN PATCH
|
257
|
+
# polymorphic_type = transform_value(owner.class.base_class.name)
|
258
|
+
polymorphic_type = transform_value(ActiveRecord::Base.store_base_sti_class ? owner.class.base_class.name : owner.class.name)
|
259
|
+
# END PATCH
|
260
|
+
scope = scope.where(table.name => { reflection.type => polymorphic_type })
|
261
|
+
end
|
262
|
+
|
263
|
+
scope
|
264
|
+
end
|
265
|
+
|
266
|
+
end
|
267
|
+
|
268
|
+
module ThroughAssociation
|
269
|
+
private
|
270
|
+
|
271
|
+
def construct_join_attributes(*records)
|
272
|
+
ensure_mutable
|
273
|
+
|
274
|
+
if source_reflection.association_primary_key(reflection.klass) == reflection.klass.primary_key
|
275
|
+
join_attributes = { source_reflection.name => records }
|
276
|
+
else
|
277
|
+
join_attributes = {
|
278
|
+
source_reflection.foreign_key =>
|
279
|
+
records.map { |record|
|
280
|
+
record.send(source_reflection.association_primary_key(reflection.klass))
|
281
|
+
}
|
282
|
+
}
|
283
|
+
end
|
284
|
+
|
285
|
+
if options[:source_type]
|
286
|
+
|
287
|
+
# START PATCH
|
288
|
+
# original:
|
289
|
+
# join_attributes[source_reflection.foreign_type] =
|
290
|
+
# records.map { |record| record.class.base_class.name }
|
291
|
+
|
292
|
+
join_attributes[source_reflection.foreign_type] =
|
293
|
+
records.map { |record| ActiveRecord::Base.store_base_sti_class ? record.class.base_class.name : record.class.name }
|
294
|
+
|
295
|
+
# END PATCH
|
296
|
+
end
|
297
|
+
|
298
|
+
if records.count == 1
|
299
|
+
Hash[join_attributes.map { |k, v| [k, v.first] }]
|
300
|
+
else
|
301
|
+
join_attributes
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
class HasManyThroughAssociation
|
307
|
+
private
|
308
|
+
|
309
|
+
def build_through_record(record)
|
310
|
+
@through_records[record.object_id] ||= begin
|
311
|
+
ensure_mutable
|
312
|
+
|
313
|
+
through_record = through_association.build(*options_for_through_record)
|
314
|
+
through_record.send("#{source_reflection.name}=", record)
|
315
|
+
|
316
|
+
# START PATCH
|
317
|
+
if ActiveRecord::Base.store_base_sti_class
|
318
|
+
if options[:source_type]
|
319
|
+
through_record.send("#{source_reflection.foreign_type}=", options[:source_type])
|
320
|
+
end
|
321
|
+
end
|
322
|
+
# END PATCH
|
323
|
+
|
324
|
+
through_record
|
325
|
+
end
|
326
|
+
end
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
module Reflection
|
331
|
+
class PolymorphicReflection
|
332
|
+
def source_type_info
|
333
|
+
type = @previous_reflection.foreign_type
|
334
|
+
source_type = @previous_reflection.options[:source_type]
|
335
|
+
|
336
|
+
# START PATCH
|
337
|
+
adjusted_source_type =
|
338
|
+
if ActiveRecord::Base.store_base_sti_class
|
339
|
+
source_type
|
340
|
+
else
|
341
|
+
([source_type.constantize] + source_type.constantize.descendants).map(&:to_s)
|
342
|
+
end
|
343
|
+
# END PATCH
|
344
|
+
|
345
|
+
lambda { |object| where(type => adjusted_source_type) }
|
346
|
+
end
|
347
|
+
end
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: store_base_sti_class
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- AppFolio
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-05-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -238,16 +238,22 @@ files:
|
|
238
238
|
- gemfiles/rails_4.2.6.gemfile.lock
|
239
239
|
- gemfiles/rails_4.2.7.1.gemfile
|
240
240
|
- gemfiles/rails_4.2.7.gemfile
|
241
|
+
- gemfiles/rails_4.2.8.gemfile
|
241
242
|
- gemfiles/rails_5.0.0.1.gemfile
|
242
243
|
- gemfiles/rails_5.0.0.gemfile
|
243
244
|
- gemfiles/rails_5.0.1.gemfile
|
244
245
|
- gemfiles/rails_5.0.1.gemfile.lock
|
246
|
+
- gemfiles/rails_5.0.2.gemfile
|
247
|
+
- gemfiles/rails_5.0.3.gemfile
|
248
|
+
- gemfiles/rails_5.1.0.gemfile
|
249
|
+
- gemfiles/rails_5.1.1.gemfile
|
245
250
|
- lib/store_base_sti_class.rb
|
246
251
|
- lib/store_base_sti_class/version.rb
|
247
252
|
- lib/store_base_sti_class_for_4_0.rb
|
248
253
|
- lib/store_base_sti_class_for_4_1.rb
|
249
254
|
- lib/store_base_sti_class_for_4_2.rb
|
250
255
|
- lib/store_base_sti_class_for_5_0.rb
|
256
|
+
- lib/store_base_sti_class_for_5_1.rb
|
251
257
|
- store_base_sti_class.gemspec
|
252
258
|
- storebasestiname_unittest.sql
|
253
259
|
homepage: http://github.com/appfolio/store_base_sti_class
|
@@ -270,7 +276,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
270
276
|
version: '0'
|
271
277
|
requirements: []
|
272
278
|
rubyforge_project:
|
273
|
-
rubygems_version: 2.
|
279
|
+
rubygems_version: 2.6.11
|
274
280
|
signing_key:
|
275
281
|
specification_version: 4
|
276
282
|
summary: Modifies ActiveRecord 4.0.x - 5.0.x with the ability to store the actual
|