store_base_sti_class 2.0.1 → 2.0.2

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
  SHA256:
3
- metadata.gz: d905b8e881303f37a959af003a8ae10b9a8c47d936a6adb9afc75bf149dbbd68
4
- data.tar.gz: 53baeb1bf2222de935343215b1bfa036d3cbd4c26ae6087ead371e0918e11754
3
+ metadata.gz: 59deb36c4e242478eb3aea835560dd54845a59120e798e7c3d2945609da51fc7
4
+ data.tar.gz: c2320ddcb07a37711a13dfe9d700da253c419f85a9aebec37a7c33c468fa0ac4
5
5
  SHA512:
6
- metadata.gz: 285c2c32254eb69039e4cc5337065dcde7f1a99f65fdc6902e1027e6dbd380a36bd488ae87c0e5b2c718d463ce0f4a5fb82f1993246bab4f7ccee0ca2914c2ab
7
- data.tar.gz: 9be85dd36e7ed71a298d95dc434940e73a05de94d798d21cf46d9b805a683129272ee07688e684c056a46bc7ce9321e06a6f2ece71f2f4219eeab11f902ef1f9
6
+ metadata.gz: 03e0e8037ed8d2642e239be605ea68e7fdd808c94e76741767c2d822b3045b814c04e24dff970188fd9a283e735eda67cd4f5334b347b9dab1f3d02fbd5fa957
7
+ data.tar.gz: 8314c4ff6de5199bdad4605ef5a042cdec5935f0e3102ed99637dd7e5d90c4616d8571eec34e64da758207e14834eb98ef05a3aa99503e8efbac3f408dc2af6c
data/Appraisals CHANGED
@@ -1,15 +1,15 @@
1
1
  RAILS_VERSIONS = %w[
2
- 4.2.11
3
2
  5.0.7
4
- 5.1.6
3
+ 5.1.7
5
4
  5.2.3
6
5
  5.2.4
7
- 6.0.1
6
+ 6.0.3
7
+ 6.1.0
8
8
  ].freeze
9
9
 
10
10
  RAILS_VERSIONS.each do |version|
11
11
  appraise "rails_#{version}" do
12
12
  gem 'activerecord', version
13
- gem 'sqlite3', version == '6.0.1' ? '~> 1.4.0' : '~> 1.3.0'
13
+ gem 'sqlite3', ['6.0.3', '6.1.0'].include?(version) ? '~> 1.4.0' : '~> 1.3.0'
14
14
  end
15
15
  end
@@ -1,37 +1,36 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- store_base_sti_class (2.0.0)
4
+ store_base_sti_class (2.0.2)
5
5
  activerecord (>= 4.0)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- activemodel (6.0.1)
11
- activesupport (= 6.0.1)
12
- activerecord (6.0.1)
13
- activemodel (= 6.0.1)
14
- activesupport (= 6.0.1)
15
- activesupport (6.0.1)
10
+ activemodel (6.1.0)
11
+ activesupport (= 6.1.0)
12
+ activerecord (6.1.0)
13
+ activemodel (= 6.1.0)
14
+ activesupport (= 6.1.0)
15
+ activesupport (6.1.0)
16
16
  concurrent-ruby (~> 1.0, >= 1.0.2)
17
- i18n (>= 0.7, < 2)
18
- minitest (~> 5.1)
19
- tzinfo (~> 1.1)
20
- zeitwerk (~> 2.2)
21
- appraisal (2.2.0)
17
+ i18n (>= 1.6, < 2)
18
+ minitest (>= 5.1)
19
+ tzinfo (~> 2.0)
20
+ zeitwerk (~> 2.3)
21
+ appraisal (2.3.0)
22
22
  bundler
23
23
  rake
24
24
  thor (>= 0.14.0)
25
- concurrent-ruby (1.1.5)
26
- i18n (1.7.0)
25
+ concurrent-ruby (1.1.7)
26
+ i18n (1.8.5)
27
27
  concurrent-ruby (~> 1.0)
28
- minitest (5.13.0)
28
+ minitest (5.14.2)
29
29
  rake (13.0.1)
30
- thor (0.20.3)
31
- thread_safe (0.3.6)
32
- tzinfo (1.2.5)
33
- thread_safe (~> 0.1)
34
- zeitwerk (2.2.1)
30
+ thor (1.0.1)
31
+ tzinfo (2.0.3)
32
+ concurrent-ruby (~> 1.0)
33
+ zeitwerk (2.4.2)
35
34
 
36
35
  PLATFORMS
37
36
  ruby
@@ -43,4 +42,4 @@ DEPENDENCIES
43
42
  store_base_sti_class!
44
43
 
45
44
  BUNDLED WITH
46
- 1.17.2
45
+ 2.1.4
data/README.md CHANGED
@@ -1,4 +1,5 @@
1
- [![Build Status](https://travis-ci.org/appfolio/store_base_sti_class.svg?branch=master)](https://travis-ci.org/appfolio/store_base_sti_class)
1
+ [![CI](https://github.com/appfolio/store_base_sti_class/workflows/CI/badge.svg)](https://github.com/appfolio/store_base_sti_class/actions)
2
+
2
3
  ## Description
3
4
 
4
5
  Given the following class definitions:
@@ -79,6 +80,21 @@ It currently works with ActiveRecord 4.2.x through 6.0.x. If you need support
79
80
  for ActiveRecord 3.x, use a pre-1.0 version of the gem, or ActiveRecord < 4.2
80
81
  use a pre-2.0 version of the gem.
81
82
 
83
+ ## Conflicts
84
+
85
+ This gem produces known conflicts with these other gems:
86
+
87
+ ### friendly_id
88
+
89
+ When using [friendly_id](https://github.com/norman/friendly_id) >= 5.2.5 with the [History module](https://norman.github.io/friendly_id/FriendlyId/History.html) enabled, duplicate slugs will be generated for STI subclasses with the same sluggable identifier (ex: name). This will either cause saves to fail if you have the proper indexes in place, or will cause slug lookups to be non-deterministic, either of which is undesirable.
90
+
91
+ ## History
92
+
93
+ * https://github.com/rails/rails/issues/724
94
+ * https://github.com/rails/rails/issues/5441#issuecomment-4563865
95
+ * https://github.com/rails/rails/issues/4729#issuecomment-5729297
96
+ * https://github.com/rails/rails/issues/5441#issuecomment-264871920
97
+
82
98
  ## Copyright
83
99
 
84
100
  Copyright (c) 2011-2019 AppFolio, inc. See LICENSE.txt for
@@ -2,7 +2,7 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "activerecord", "5.1.6"
5
+ gem "activerecord", "5.1.7"
6
6
  gem "sqlite3", "~> 1.3.0"
7
7
 
8
8
  gemspec path: "../"
@@ -2,7 +2,7 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "activerecord", "6.0.1"
5
+ gem "activerecord", "6.0.3"
6
6
  gem "sqlite3", "~> 1.4.0"
7
7
 
8
8
  gemspec path: "../"
@@ -2,7 +2,7 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "activerecord", "4.2.11"
6
- gem "sqlite3", "~> 1.3.0"
5
+ gem "activerecord", "6.1.0"
6
+ gem "sqlite3", "~> 1.4.0"
7
7
 
8
8
  gemspec path: "../"
@@ -1,8 +1,6 @@
1
1
  require 'active_record'
2
2
 
3
- if ActiveRecord::VERSION::STRING =~ /^4\.2/
4
- require 'store_base_sti_class_for_4_2'
5
- elsif ActiveRecord::VERSION::STRING =~ /^5\.0/
3
+ if ActiveRecord::VERSION::STRING =~ /^5\.0/
6
4
  require 'store_base_sti_class_for_5_0'
7
5
  elsif ActiveRecord::VERSION::STRING =~ /^5\.1/
8
6
  require 'store_base_sti_class_for_5_1'
@@ -10,6 +8,8 @@ elsif ActiveRecord::VERSION::STRING =~ /^5\.2/
10
8
  require 'store_base_sti_class_for_5_2'
11
9
  elsif ActiveRecord::VERSION::STRING =~ /^6\.0/
12
10
  require 'store_base_sti_class_for_6_0'
11
+ elsif ActiveRecord::VERSION::STRING =~ /^6\.1/
12
+ require 'store_base_sti_class_for_6_1'
13
13
  end
14
14
 
15
15
  module StoreBaseSTIClass
@@ -1,3 +1,3 @@
1
1
  module StoreBaseSTIClass
2
- VERSION = '2.0.1'.freeze
2
+ VERSION = '2.0.2'.freeze
3
3
  end
@@ -0,0 +1,156 @@
1
+ require 'active_record/associations/join_dependency/join_part'
2
+
3
+ if ActiveRecord::VERSION::STRING =~ /^6\.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 Inheritance
12
+ module ClassMethods
13
+ def polymorphic_name
14
+ ActiveRecord::Base.store_base_sti_class ? base_class.name : name
15
+ end
16
+ end
17
+ end
18
+
19
+ module Associations
20
+ class Preloader
21
+ class ThroughAssociation < Association
22
+ private
23
+
24
+ def through_scope
25
+ scope = through_reflection.klass.unscoped
26
+ options = reflection.options
27
+
28
+ values = reflection_scope.values
29
+ if annotations = values[:annotate]
30
+ scope.annotate!(*annotations)
31
+ end
32
+
33
+ if options[:source_type]
34
+ # BEGIN PATCH
35
+ # original:
36
+ # scope.where! reflection.foreign_type => options[:source_type]
37
+
38
+ adjusted_foreign_type =
39
+ if ActiveRecord::Base.store_base_sti_class
40
+ options[:source_type]
41
+ else
42
+ ([options[:source_type].constantize] + options[:source_type].constantize.descendants).map(&:to_s)
43
+ end
44
+
45
+ scope.where! reflection.foreign_type => adjusted_foreign_type
46
+ # END PATCH
47
+
48
+ elsif !reflection_scope.where_clause.empty?
49
+ scope.where_clause = reflection_scope.where_clause
50
+
51
+ if includes = values[:includes]
52
+ scope.includes!(source_reflection.name => includes)
53
+ else
54
+ scope.includes!(source_reflection.name)
55
+ end
56
+
57
+ if values[:references] && !values[:references].empty?
58
+ scope.references_values |= values[:references]
59
+ else
60
+ scope.references!(source_reflection.table_name)
61
+ end
62
+
63
+ if joins = values[:joins]
64
+ scope.joins!(source_reflection.name => joins)
65
+ end
66
+
67
+ if left_outer_joins = values[:left_outer_joins]
68
+ scope.left_outer_joins!(source_reflection.name => left_outer_joins)
69
+ end
70
+
71
+ if scope.eager_loading? && order_values = values[:order]
72
+ scope = scope.order(order_values)
73
+ end
74
+ end
75
+
76
+ scope
77
+ end
78
+ end
79
+ end
80
+
81
+ class AssociationScope
82
+ private
83
+
84
+ def next_chain_scope(scope, reflection, next_reflection)
85
+ primary_key = reflection.join_primary_key
86
+ foreign_key = reflection.join_foreign_key
87
+
88
+ table = reflection.aliased_table
89
+ foreign_table = next_reflection.aliased_table
90
+ constraint = table[primary_key].eq(foreign_table[foreign_key])
91
+
92
+ if reflection.type
93
+ # BEGIN PATCH
94
+ # original:
95
+ # value = transform_value(next_reflection.klass.polymorphic_name)
96
+ # scope = apply_scope(scope, table, reflection.type, value)
97
+
98
+ if ActiveRecord::Base.store_base_sti_class
99
+ value = transform_value(next_reflection.klass.polymorphic_name)
100
+ else
101
+ klass = next_reflection.klass
102
+ value = ([klass] + klass.descendants).map(&:name)
103
+ end
104
+ scope = apply_scope(scope, table, reflection.type, value)
105
+ # END PATCH
106
+ end
107
+
108
+ scope.joins!(join(foreign_table, constraint))
109
+ end
110
+
111
+ end
112
+
113
+ class HasManyThroughAssociation
114
+ private
115
+
116
+ def build_through_record(record)
117
+ @through_records[record.object_id] ||= begin
118
+ ensure_mutable
119
+
120
+ attributes = through_scope_attributes
121
+ attributes[source_reflection.name] = record
122
+
123
+ # START PATCH
124
+ if ActiveRecord::Base.store_base_sti_class
125
+ attributes[source_reflection.foreign_type] = options[:source_type] if options[:source_type]
126
+ end
127
+ # END PATCH
128
+
129
+ through_association.build(attributes)
130
+ end
131
+ end
132
+ end
133
+ end
134
+
135
+ module Reflection
136
+ class PolymorphicReflection
137
+ def source_type_scope
138
+ type = @previous_reflection.foreign_type
139
+ source_type = @previous_reflection.options[:source_type]
140
+
141
+ # START PATCH
142
+ adjusted_source_type =
143
+ if ActiveRecord::Base.store_base_sti_class
144
+ source_type
145
+ else
146
+ ([source_type.constantize] + source_type.constantize.descendants).map(&:to_s)
147
+ end
148
+ # END PATCH
149
+
150
+ lambda { |object| where(type => adjusted_source_type) }
151
+ end
152
+ end
153
+ end
154
+ end
155
+
156
+ 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: 2.0.1
4
+ version: 2.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - AppFolio
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-12-12 00:00:00.000000000 Z
11
+ date: 2020-12-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -84,25 +84,25 @@ files:
84
84
  - LICENSE.txt
85
85
  - README.md
86
86
  - Rakefile
87
- - gemfiles/rails_4.2.11.gemfile
88
87
  - gemfiles/rails_5.0.7.gemfile
89
- - gemfiles/rails_5.1.6.gemfile
88
+ - gemfiles/rails_5.1.7.gemfile
90
89
  - gemfiles/rails_5.2.3.gemfile
91
90
  - gemfiles/rails_5.2.4.gemfile
92
- - gemfiles/rails_6.0.1.gemfile
91
+ - gemfiles/rails_6.0.3.gemfile
92
+ - gemfiles/rails_6.1.0.gemfile
93
93
  - lib/store_base_sti_class.rb
94
94
  - lib/store_base_sti_class/version.rb
95
- - lib/store_base_sti_class_for_4_2.rb
96
95
  - lib/store_base_sti_class_for_5_0.rb
97
96
  - lib/store_base_sti_class_for_5_1.rb
98
97
  - lib/store_base_sti_class_for_5_2.rb
99
98
  - lib/store_base_sti_class_for_6_0.rb
99
+ - lib/store_base_sti_class_for_6_1.rb
100
100
  - store_base_sti_class.gemspec
101
101
  homepage: http://github.com/appfolio/store_base_sti_class
102
102
  licenses:
103
103
  - MIT
104
104
  metadata: {}
105
- post_install_message:
105
+ post_install_message:
106
106
  rdoc_options: []
107
107
  require_paths:
108
108
  - lib
@@ -117,8 +117,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
117
117
  - !ruby/object:Gem::Version
118
118
  version: '0'
119
119
  requirements: []
120
- rubygems_version: 3.0.3
121
- signing_key:
120
+ rubygems_version: 3.1.4
121
+ signing_key:
122
122
  specification_version: 4
123
123
  summary: Modifies ActiveRecord 4.2.x - 6.0.x with the ability to store the actual
124
124
  class (instead of the base class) in polymorhic _type columns when using STI
@@ -1,360 +0,0 @@
1
- require 'active_record/associations/join_dependency/join_part'
2
-
3
- if ActiveRecord::VERSION::STRING =~ /^4\.2/
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
-
14
- def creation_attributes
15
- attributes = {}
16
-
17
- if (reflection.has_one? || reflection.collection?) && !options[:through]
18
- attributes[reflection.foreign_key] = owner[reflection.active_record_primary_key]
19
-
20
- if reflection.options[:as]
21
- # START PATCH
22
- # original:
23
- # attributes[reflection.type] = owner.class.base_class.name
24
-
25
- attributes[reflection.type] = ActiveRecord::Base.store_base_sti_class ? owner.class.base_class.name : owner.class.name
26
- # END PATCH
27
- end
28
- end
29
-
30
- attributes
31
- end
32
- end
33
-
34
- class JoinDependency # :nodoc:
35
- class JoinAssociation < JoinPart # :nodoc:
36
- def join_constraints(foreign_table, foreign_klass, node, join_type, tables, scope_chain, chain)
37
- joins = []
38
- bind_values = []
39
- tables = tables.reverse
40
-
41
- scope_chain_index = 0
42
- scope_chain = scope_chain.reverse
43
-
44
- # The chain starts with the target table, but we want to end with it here (makes
45
- # more sense in this context), so we reverse
46
- chain.reverse_each do |reflection|
47
- table = tables.shift
48
- klass = reflection.klass
49
-
50
- join_keys = reflection.join_keys(klass)
51
- key = join_keys.key
52
- foreign_key = join_keys.foreign_key
53
-
54
- constraint = build_constraint(klass, table, key, foreign_table, foreign_key)
55
-
56
- scope_chain_items = scope_chain[scope_chain_index].map do |item|
57
- if item.is_a?(Relation)
58
- item
59
- else
60
- ActiveRecord::Relation.create(klass, table).instance_exec(node, &item)
61
- end
62
- end
63
- scope_chain_index += 1
64
-
65
- scope_chain_items.concat [klass.send(:build_default_scope, ActiveRecord::Relation.create(klass, table))].compact
66
-
67
- rel = scope_chain_items.inject(scope_chain_items.shift) do |left, right|
68
- left.merge right
69
- end
70
-
71
- if rel && !rel.arel.constraints.empty?
72
- bind_values.concat rel.bind_values
73
- constraint = constraint.and rel.arel.constraints
74
- end
75
-
76
- if reflection.type
77
- # START PATCH
78
- # original:
79
- # value = foreign_klass.base_class.name
80
- value = ActiveRecord::Base.store_base_sti_class ? foreign_klass.base_class.name : foreign_klass.name
81
- # END PATCH
82
- column = klass.columns_hash[reflection.type.to_s]
83
-
84
- substitute = klass.connection.substitute_at(column)
85
- bind_values.push [column, value]
86
- constraint = constraint.and table[reflection.type].eq substitute
87
- end
88
-
89
- joins << table.create_join(table, table.create_on(constraint), join_type)
90
-
91
- # The current table in this iteration becomes the foreign table in the next
92
- foreign_table, foreign_klass = table, klass
93
- end
94
-
95
- JoinInformation.new joins, bind_values
96
- end
97
- end
98
- end
99
-
100
- class BelongsToPolymorphicAssociation
101
- private
102
-
103
- def replace_keys(record)
104
- super
105
-
106
- # START PATCH
107
- # original:
108
- # owner[reflection.foreign_type] = record.class.base_class.name
109
-
110
- owner[reflection.foreign_type] = ActiveRecord::Base.store_base_sti_class ? record.class.base_class.name : record.class.name
111
-
112
- # END PATCH
113
- end
114
- end
115
-
116
- class Preloader
117
- class Association
118
-
119
- def build_scope
120
- scope = klass.unscoped
121
-
122
- values = reflection_scope.values
123
- reflection_binds = reflection_scope.bind_values
124
- preload_values = preload_scope.values
125
- preload_binds = preload_scope.bind_values
126
-
127
- scope.where_values = Array(values[:where]) + Array(preload_values[:where])
128
- scope.references_values = Array(values[:references]) + Array(preload_values[:references])
129
- scope.bind_values = (reflection_binds + preload_binds)
130
-
131
- scope._select! preload_values[:select] || values[:select] || table[Arel.star]
132
- scope.includes! preload_values[:includes] || values[:includes]
133
- scope.joins! preload_values[:joins] || values[:joins]
134
- scope.order! preload_values[:order] || values[:order]
135
-
136
- if preload_values[:readonly] || values[:readonly]
137
- scope.readonly!
138
- end
139
-
140
- if options[:as]
141
- # START PATCH
142
- # original:
143
- # scope.where!(klass.table_name => { reflection.type => model.base_class.sti_name })
144
-
145
- scope.where!(klass.table_name => { reflection.type => ActiveRecord::Base.store_base_sti_class ? model.base_class.sti_name : model.sti_name })
146
-
147
- # END PATCH
148
- end
149
-
150
- scope.unscope_values = Array(values[:unscope])
151
- klass.default_scoped.merge(scope)
152
- end
153
- end
154
-
155
- module ThroughAssociation
156
- private
157
-
158
- def through_scope
159
- scope = through_reflection.klass.unscoped
160
-
161
- if options[:source_type]
162
- # BEGIN PATCH
163
- # original: scope.where! reflection.foreign_type => options[:source_type]
164
-
165
- adjusted_foreign_type = if ActiveRecord::Base.store_base_sti_class
166
- options[:source_type]
167
- else
168
- ([options[:source_type].constantize] + options[:source_type].constantize.descendants).map(&:to_s)
169
- end
170
-
171
- scope.where! reflection.foreign_type => adjusted_foreign_type
172
-
173
- # END PATCH
174
- else
175
- unless reflection_scope.where_values.empty?
176
- scope.includes_values = Array(reflection_scope.values[:includes] || options[:source])
177
- scope.where_values = reflection_scope.values[:where]
178
- scope.bind_values = reflection_scope.bind_values
179
- end
180
-
181
- scope.references! reflection_scope.values[:references]
182
- scope = scope.order reflection_scope.values[:order] if scope.eager_loading?
183
- end
184
-
185
- scope
186
- end
187
- end
188
- end
189
-
190
- class AssociationScope
191
- def self.get_bind_values(owner, chain)
192
- binds = []
193
- last_reflection = chain.last
194
-
195
- binds << last_reflection.join_id_for(owner)
196
- if last_reflection.type
197
- # START PATCH
198
- # original: binds << owner.class.base_class.name
199
- binds << (ActiveRecord::Base.store_base_sti_class ? owner.class.base_class.name : owner.class.name)
200
- # END PATCH
201
- end
202
-
203
- chain.each_cons(2).each do |reflection, next_reflection|
204
- if reflection.type
205
- # START PATCH
206
- # original: binds << next_reflection.klass.base_class.name
207
- binds << (ActiveRecord::Base.store_base_sti_class ? next_reflection.klass.base_class.name : next_reflection.klass.name)
208
- # END PATCH
209
- end
210
- end
211
- binds
212
- end
213
-
214
- def next_chain_scope(scope, table, reflection, tracker, assoc_klass, foreign_table, next_reflection)
215
- join_keys = reflection.join_keys(assoc_klass)
216
- key = join_keys.key
217
- foreign_key = join_keys.foreign_key
218
-
219
- constraint = table[key].eq(foreign_table[foreign_key])
220
-
221
- if reflection.type
222
- # BEGIN PATCH
223
- # original:
224
- # value = next_reflection.klass.base_class.name
225
- # bind_val = bind scope, table.table_name, reflection.type, value, tracker
226
- # scope = scope.where(table[reflection.type].eq(bind_val))
227
- if ActiveRecord::Base.store_base_sti_class
228
- value = next_reflection.klass.base_class.name
229
- bind_val = bind scope, table.table_name, reflection.type, value, tracker
230
- scope = scope.where(table[reflection.type].eq(bind_val))
231
- else
232
- value = next_reflection.klass.name
233
- klass = next_reflection.klass
234
- scope = scope.where(table[reflection.type].in(([klass] + klass.descendants).map(&:name)))
235
- end
236
- # END PATCH
237
-
238
- end
239
-
240
- scope = scope.joins(join(foreign_table, constraint))
241
- end
242
-
243
- def last_chain_scope(scope, table, reflection, owner, tracker, assoc_klass)
244
- join_keys = reflection.join_keys(assoc_klass)
245
- key = join_keys.key
246
- foreign_key = join_keys.foreign_key
247
-
248
- bind_val = bind scope, table.table_name, key.to_s, owner[foreign_key], tracker
249
- scope = scope.where(table[key].eq(bind_val))
250
-
251
- if reflection.type
252
- # BEGIN PATCH
253
- # original: owner.class.base_class.name
254
- value = ActiveRecord::Base.store_base_sti_class ? owner.class.base_class.name : owner.class.name
255
- # END PATCH
256
- bind_val = bind scope, table.table_name, reflection.type, value, tracker
257
- scope = scope.where(table[reflection.type].eq(bind_val))
258
- else
259
- scope
260
- end
261
- end
262
-
263
- end
264
-
265
- module ThroughAssociation
266
- def construct_join_attributes(*records)
267
- ensure_mutable
268
-
269
- if source_reflection.association_primary_key(reflection.klass) == reflection.klass.primary_key
270
- join_attributes = { source_reflection.name => records }
271
- else
272
- join_attributes = {
273
- source_reflection.foreign_key =>
274
- records.map { |record|
275
- record.send(source_reflection.association_primary_key(reflection.klass))
276
- }
277
- }
278
- end
279
-
280
- if options[:source_type]
281
-
282
- # START PATCH
283
- # original:
284
- # join_attributes[source_reflection.foreign_type] =
285
- # records.map { |record| record.class.base_class.name }
286
-
287
- join_attributes[source_reflection.foreign_type] =
288
- records.map { |record| ActiveRecord::Base.store_base_sti_class ? record.class.base_class.name : record.class.name }
289
-
290
- # END PATCH
291
- end
292
-
293
- if records.count == 1
294
- Hash[join_attributes.map { |k, v| [k, v.first] }]
295
- else
296
- join_attributes
297
- end
298
- end
299
-
300
- end
301
-
302
- class HasManyThroughAssociation
303
-
304
- def build_through_record(record)
305
- @through_records[record.object_id] ||= begin
306
- ensure_mutable
307
-
308
- through_record = through_association.build(*options_for_through_record)
309
- through_record.send("#{source_reflection.name}=", record)
310
-
311
- # START PATCH
312
- if ActiveRecord::Base.store_base_sti_class
313
- if options[:source_type]
314
- through_record.send("#{source_reflection.foreign_type}=", options[:source_type])
315
- end
316
- end
317
- # END PATCH
318
-
319
- through_record
320
- end
321
- end
322
- end
323
- end
324
-
325
- module Reflection
326
- class ThroughReflection
327
- def scope_chain
328
- @scope_chain ||= begin
329
- scope_chain = source_reflection.scope_chain.map(&:dup)
330
-
331
- # Add to it the scope from this reflection (if any)
332
- scope_chain.first << scope if scope
333
-
334
- through_scope_chain = through_reflection.scope_chain.map(&:dup)
335
-
336
- if options[:source_type]
337
- type = foreign_type
338
- # START PATCH
339
- # original: source_type = options[:source_type]
340
- source_type = if ActiveRecord::Base.store_base_sti_class
341
- options[:source_type]
342
- else
343
- ([options[:source_type].constantize] + options[:source_type].constantize.descendants).map(&:to_s)
344
- end
345
- # END PATCH
346
- through_scope_chain.first << lambda { |object|
347
- where(type => source_type)
348
- }
349
- end
350
-
351
- # Recursively fill out the rest of the array from the through reflection
352
- scope_chain + through_scope_chain
353
- end
354
- end
355
- end
356
-
357
- end
358
- end
359
-
360
- end