store_base_sti_class 2.0.1 → 2.0.2

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