store_base_sti_class 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8a8f045c90c480e658eb8ac2a877d4bfb31fd01c
4
- data.tar.gz: 9f1e796ef7836c594fea2e9a107939771e2669dd
3
+ metadata.gz: 82287e5bc596474535ed2f815cb34cbfe2abb089
4
+ data.tar.gz: 3f1999f09ccaa5f380cb4230f4cba6eb81c2dc2e
5
5
  SHA512:
6
- metadata.gz: 39a2df8993be2a04d27b318dadd3d3bc23005c418828e587592f67946b2c144caebe0101606f722b196537a654d648d332e16ddc58a30504c132aec176fd7cf7
7
- data.tar.gz: a901606a746a6c093e0086a5886d101099ae4d8a5aefca9f27cc6c5eeb99cfbd093b60192fc309f0094dafff3ff53ac405c0ccdf2f2d29522b84ee41b4124d6b
6
+ metadata.gz: fccef96be8809df757d5936781d2fe4811b5d4fd56d5b53fd026448c35d86288f4c10327b1562b4478e360f7e38f2c8406a7b3995b2364ffff05cfaf231b8d00
7
+ data.tar.gz: 94e2b0a7c09cfcd051f791077636c9d0301687cd713ce0d899efc39994fbf07e5604e9f38a3ecd02ec008774f43694f5ed354103983e193fc1d7e0f25bade606
data/Appraisals CHANGED
@@ -44,9 +44,14 @@ RAILS_VERSIONS = %w(
44
44
  4.2.6
45
45
  4.2.7
46
46
  4.2.7.1
47
+ 4.2.8
47
48
  5.0.0
48
49
  5.0.0.1
49
50
  5.0.1
51
+ 5.0.2
52
+ 5.0.3
53
+ 5.1.0
54
+ 5.1.1
50
55
  )
51
56
 
52
57
  RAILS_VERSIONS.each do |version|
data/Gemfile.lock CHANGED
@@ -1,39 +1,36 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- store_base_sti_class (1.0.0)
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 (4.2.6)
11
- activesupport (= 4.2.6)
12
- builder (~> 3.1)
13
- activerecord (4.2.6)
14
- activemodel (= 4.2.6)
15
- activesupport (= 4.2.6)
16
- arel (~> 6.0)
17
- activesupport (4.2.6)
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 (6.0.4)
28
- builder (3.2.3)
29
- i18n (0.8.0)
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.5)
36
- tzinfo (1.2.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
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "4.2.8"
6
+
7
+ gemspec :path => "../"
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "5.0.2"
6
+
7
+ gemspec :path => "../"
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "5.0.3"
6
+
7
+ gemspec :path => "../"
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "5.1.0"
6
+
7
+ gemspec :path => "../"
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "5.1.1"
6
+
7
+ gemspec :path => "../"
@@ -1,3 +1,3 @@
1
1
  module StoreBaseSTIClass
2
- VERSION = '1.0.0'.freeze
2
+ VERSION = '1.1.0'.freeze
3
3
  end
@@ -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.0.0
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-02-18 00:00:00.000000000 Z
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.5.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