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 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