activerecord 5.1.0.beta1 → 5.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +93 -6
  3. data/lib/active_record/associations.rb +4 -0
  4. data/lib/active_record/associations/association_scope.rb +8 -8
  5. data/lib/active_record/associations/belongs_to_association.rb +4 -0
  6. data/lib/active_record/associations/builder/belongs_to.rb +8 -1
  7. data/lib/active_record/associations/collection_proxy.rb +5 -4
  8. data/lib/active_record/associations/join_dependency.rb +1 -1
  9. data/lib/active_record/associations/join_dependency/join_association.rb +4 -23
  10. data/lib/active_record/attribute_methods/dirty.rb +3 -3
  11. data/lib/active_record/connection_adapters/abstract/quoting.rb +20 -3
  12. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +3 -7
  13. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +30 -16
  14. data/lib/active_record/connection_adapters/abstract_adapter.rb +8 -5
  15. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +16 -80
  16. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +33 -0
  17. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +2 -0
  18. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
  19. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +56 -96
  20. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
  21. data/lib/active_record/connection_adapters/postgresql_adapter.rb +4 -12
  22. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +32 -0
  23. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +4 -51
  24. data/lib/active_record/core.rb +0 -1
  25. data/lib/active_record/gem_version.rb +1 -1
  26. data/lib/active_record/locking/optimistic.rb +2 -6
  27. data/lib/active_record/migration.rb +32 -17
  28. data/lib/active_record/null_relation.rb +1 -1
  29. data/lib/active_record/querying.rb +1 -1
  30. data/lib/active_record/railties/databases.rake +3 -19
  31. data/lib/active_record/reflection.rb +67 -16
  32. data/lib/active_record/relation.rb +0 -4
  33. data/lib/active_record/relation/calculations.rb +7 -10
  34. data/lib/active_record/relation/delegation.rb +2 -2
  35. data/lib/active_record/relation/finder_methods.rb +102 -100
  36. data/lib/active_record/relation/query_methods.rb +6 -1
  37. data/lib/active_record/result.rb +12 -1
  38. data/lib/active_record/sanitization.rb +1 -2
  39. data/lib/active_record/schema_dumper.rb +1 -1
  40. data/lib/active_record/schema_migration.rb +5 -1
  41. data/lib/active_record/tasks/postgresql_database_tasks.rb +20 -0
  42. data/lib/active_record/transactions.rb +1 -1
  43. data/lib/active_record/type/decimal_without_scale.rb +4 -0
  44. data/lib/active_record/type/serialized.rb +2 -0
  45. data/lib/rails/generators/active_record/migration.rb +1 -1
  46. metadata +8 -6
@@ -1,6 +1,8 @@
1
1
  module ActiveRecord
2
2
  module ConnectionAdapters
3
3
  class PostgreSQLTypeMetadata < DelegateClass(SqlTypeMetadata)
4
+ undef to_yaml if method_defined?(:to_yaml)
5
+
4
6
  attr_reader :oid, :fmod, :array
5
7
 
6
8
  def initialize(type_metadata, oid: nil, fmod: nil)
@@ -3,6 +3,7 @@ gem "pg", "~> 0.18"
3
3
  require "pg"
4
4
 
5
5
  require "active_record/connection_adapters/abstract_adapter"
6
+ require "active_record/connection_adapters/statement_pool"
6
7
  require "active_record/connection_adapters/postgresql/column"
7
8
  require "active_record/connection_adapters/postgresql/database_statements"
8
9
  require "active_record/connection_adapters/postgresql/explain_pretty_printer"
@@ -15,7 +16,6 @@ require "active_record/connection_adapters/postgresql/schema_dumper"
15
16
  require "active_record/connection_adapters/postgresql/schema_statements"
16
17
  require "active_record/connection_adapters/postgresql/type_metadata"
17
18
  require "active_record/connection_adapters/postgresql/utils"
18
- require "active_record/connection_adapters/statement_pool"
19
19
 
20
20
  module ActiveRecord
21
21
  module ConnectionHandling # :nodoc:
@@ -215,7 +215,7 @@ module ActiveRecord
215
215
 
216
216
  # @local_tz is initialized as nil to avoid warnings when connect tries to use it
217
217
  @local_tz = nil
218
- @table_alias_length = nil
218
+ @max_identifier_length = nil
219
219
 
220
220
  connect
221
221
  add_pg_encoders
@@ -281,11 +281,6 @@ module ActiveRecord
281
281
  NATIVE_DATABASE_TYPES
282
282
  end
283
283
 
284
- # Returns true, since this connection adapter supports migrations.
285
- def supports_migrations?
286
- true
287
- end
288
-
289
284
  def set_standard_conforming_strings
290
285
  execute("SET standard_conforming_strings = on", "SCHEMA")
291
286
  end
@@ -363,8 +358,9 @@ module ActiveRecord
363
358
 
364
359
  # Returns the configured supported identifier length supported by PostgreSQL
365
360
  def table_alias_length
366
- @table_alias_length ||= query("SHOW max_identifier_length", "SCHEMA")[0][0].to_i
361
+ @max_identifier_length ||= select_value("SHOW max_identifier_length", "SCHEMA").to_i
367
362
  end
363
+ alias index_name_length table_alias_length
368
364
 
369
365
  # Set the authorized user for this session
370
366
  def session_auth=(user)
@@ -376,10 +372,6 @@ module ActiveRecord
376
372
  @use_insert_returning
377
373
  end
378
374
 
379
- def valid_type?(type)
380
- !native_database_types[type].nil?
381
- end
382
-
383
375
  def update_table_definition(table_name, base) #:nodoc:
384
376
  PostgreSQL::Table.new(table_name, base)
385
377
  end
@@ -0,0 +1,32 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module SQLite3
4
+ module SchemaStatements # :nodoc:
5
+ private
6
+ def data_source_sql(name = nil, type: nil)
7
+ scope = quoted_scope(name, type: type)
8
+ scope[:type] ||= "'table','view'"
9
+
10
+ sql = "SELECT name FROM sqlite_master WHERE name <> 'sqlite_sequence'"
11
+ sql << " AND name = #{scope[:name]}" if scope[:name]
12
+ sql << " AND type IN (#{scope[:type]})"
13
+ sql
14
+ end
15
+
16
+ def quoted_scope(name = nil, type: nil)
17
+ type = \
18
+ case type
19
+ when "BASE TABLE"
20
+ "'table'"
21
+ when "VIEW"
22
+ "'view'"
23
+ end
24
+ scope = {}
25
+ scope[:name] = quote(name) if name
26
+ scope[:type] = type if type
27
+ scope
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -5,6 +5,7 @@ require "active_record/connection_adapters/sqlite3/quoting"
5
5
  require "active_record/connection_adapters/sqlite3/schema_creation"
6
6
  require "active_record/connection_adapters/sqlite3/schema_definitions"
7
7
  require "active_record/connection_adapters/sqlite3/schema_dumper"
8
+ require "active_record/connection_adapters/sqlite3/schema_statements"
8
9
 
9
10
  gem "sqlite3", "~> 1.3.6"
10
11
  require "sqlite3"
@@ -55,6 +56,7 @@ module ActiveRecord
55
56
 
56
57
  include SQLite3::Quoting
57
58
  include SQLite3::ColumnDumper
59
+ include SQLite3::SchemaStatements
58
60
 
59
61
  NATIVE_DATABASE_TYPES = {
60
62
  primary_key: "INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL",
@@ -117,11 +119,6 @@ module ActiveRecord
117
119
  true
118
120
  end
119
121
 
120
- # Returns true, since this connection adapter supports migrations.
121
- def supports_migrations? #:nodoc:
122
- true
123
- end
124
-
125
122
  def requires_reloading?
126
123
  true
127
124
  end
@@ -163,10 +160,6 @@ module ActiveRecord
163
160
  true
164
161
  end
165
162
 
166
- def valid_type?(type)
167
- true
168
- end
169
-
170
163
  # Returns 62. SQLite supports index names up to 64
171
164
  # characters. The rest is used by Rails internally to perform
172
165
  # temporary rename operations
@@ -274,45 +267,6 @@ module ActiveRecord
274
267
 
275
268
  # SCHEMA STATEMENTS ========================================
276
269
 
277
- def tables # :nodoc:
278
- select_values("SELECT name FROM sqlite_master WHERE type = 'table' AND name <> 'sqlite_sequence'", "SCHEMA")
279
- end
280
-
281
- def data_sources # :nodoc:
282
- select_values("SELECT name FROM sqlite_master WHERE type IN ('table','view') AND name <> 'sqlite_sequence'", "SCHEMA")
283
- end
284
-
285
- def views # :nodoc:
286
- select_values("SELECT name FROM sqlite_master WHERE type = 'view' AND name <> 'sqlite_sequence'", "SCHEMA")
287
- end
288
-
289
- def table_exists?(table_name) # :nodoc:
290
- return false unless table_name.present?
291
-
292
- sql = "SELECT name FROM sqlite_master WHERE type = 'table' AND name <> 'sqlite_sequence'"
293
- sql << " AND name = #{quote(table_name)}"
294
-
295
- select_values(sql, "SCHEMA").any?
296
- end
297
-
298
- def data_source_exists?(table_name) # :nodoc:
299
- return false unless table_name.present?
300
-
301
- sql = "SELECT name FROM sqlite_master WHERE type IN ('table','view') AND name <> 'sqlite_sequence'"
302
- sql << " AND name = #{quote(table_name)}"
303
-
304
- select_values(sql, "SCHEMA").any?
305
- end
306
-
307
- def view_exists?(view_name) # :nodoc:
308
- return false unless view_name.present?
309
-
310
- sql = "SELECT name FROM sqlite_master WHERE type = 'view' AND name <> 'sqlite_sequence'"
311
- sql << " AND name = #{quote(view_name)}"
312
-
313
- select_values(sql, "SCHEMA").any?
314
- end
315
-
316
270
  def new_column_from_field(table_name, field) # :nondoc:
317
271
  case field["dflt_value"]
318
272
  when /^null$/i
@@ -420,11 +374,10 @@ module ActiveRecord
420
374
 
421
375
  def change_column(table_name, column_name, type, options = {}) #:nodoc:
422
376
  alter_table(table_name) do |definition|
423
- include_default = options_include_default?(options)
424
377
  definition[column_name].instance_eval do
425
378
  self.type = type
426
379
  self.limit = options[:limit] if options.include?(:limit)
427
- self.default = options[:default] if include_default
380
+ self.default = options[:default] if options.include?(:default)
428
381
  self.null = options[:null] if options.include?(:null)
429
382
  self.precision = options[:precision] if options.include?(:precision)
430
383
  self.scale = options[:scale] if options.include?(:scale)
@@ -545,7 +498,7 @@ module ActiveRecord
545
498
  end
546
499
 
547
500
  def sqlite_version
548
- @sqlite_version ||= SQLite3Adapter::Version.new(select_value("select sqlite_version(*)"))
501
+ @sqlite_version ||= SQLite3Adapter::Version.new(select_value("SELECT sqlite_version(*)"))
549
502
  end
550
503
 
551
504
  def translate_exception(exception, message)
@@ -559,7 +559,6 @@ module ActiveRecord
559
559
  @marked_for_destruction = false
560
560
  @destroyed_by_association = nil
561
561
  @new_record = true
562
- @txn = nil
563
562
  @_start_transaction_state = {}
564
563
  @transaction_state = nil
565
564
  end
@@ -8,7 +8,7 @@ module ActiveRecord
8
8
  MAJOR = 5
9
9
  MINOR = 1
10
10
  TINY = 0
11
- PRE = "beta1"
11
+ PRE = "rc1"
12
12
 
13
13
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
14
14
  end
@@ -47,8 +47,6 @@ module ActiveRecord
47
47
  # self.locking_column = :lock_person
48
48
  # end
49
49
  #
50
- # Please note that the optimistic locking will be ignored if you update the
51
- # locking column's value.
52
50
  module Optimistic
53
51
  extend ActiveSupport::Concern
54
52
 
@@ -80,13 +78,11 @@ module ActiveRecord
80
78
 
81
79
  def _update_record(attribute_names = self.attribute_names)
82
80
  return super unless locking_enabled?
83
-
84
- lock_col = self.class.locking_column
85
-
86
- return super if attribute_names.include?(lock_col)
87
81
  return 0 if attribute_names.empty?
88
82
 
89
83
  begin
84
+ lock_col = self.class.locking_column
85
+
90
86
  previous_lock_value = read_attribute_before_type_cast(lock_col)
91
87
 
92
88
  increment_lock
@@ -548,12 +548,10 @@ module ActiveRecord
548
548
  end
549
549
 
550
550
  def call(env)
551
- if connection.supports_migrations?
552
- mtime = ActiveRecord::Migrator.last_migration.mtime.to_i
553
- if @last_check < mtime
554
- ActiveRecord::Migration.check_pending!(connection)
555
- @last_check = mtime
556
- end
551
+ mtime = ActiveRecord::Migrator.last_migration.mtime.to_i
552
+ if @last_check < mtime
553
+ ActiveRecord::Migration.check_pending!(connection)
554
+ @last_check = mtime
557
555
  end
558
556
  @app.call(env)
559
557
  end
@@ -1027,10 +1025,11 @@ module ActiveRecord
1027
1025
  def schema_migrations_table_name
1028
1026
  SchemaMigration.table_name
1029
1027
  end
1028
+ deprecate :schema_migrations_table_name
1030
1029
 
1031
1030
  def get_all_versions(connection = Base.connection)
1032
- if connection.table_exists?(schema_migrations_table_name)
1033
- SchemaMigration.all.map { |x| x.version.to_i }.sort
1031
+ if SchemaMigration.table_exists?
1032
+ SchemaMigration.all_versions.map(&:to_i)
1034
1033
  else
1035
1034
  []
1036
1035
  end
@@ -1058,10 +1057,6 @@ module ActiveRecord
1058
1057
  Array(@migrations_paths)
1059
1058
  end
1060
1059
 
1061
- def match_to_migration_filename?(filename) # :nodoc:
1062
- Migration::MigrationFilenameRegexp.match?(File.basename(filename))
1063
- end
1064
-
1065
1060
  def parse_migration_filename(filename) # :nodoc:
1066
1061
  File.basename(filename).scan(Migration::MigrationFilenameRegexp).first
1067
1062
  end
@@ -1069,9 +1064,7 @@ module ActiveRecord
1069
1064
  def migrations(paths)
1070
1065
  paths = Array(paths)
1071
1066
 
1072
- files = Dir[*paths.map { |p| "#{p}/**/[0-9]*_*.rb" }]
1073
-
1074
- migrations = files.map do |file|
1067
+ migrations = migration_files(paths).map do |file|
1075
1068
  version, name, scope = parse_migration_filename(file)
1076
1069
  raise IllegalMigrationNameError.new(file) unless version
1077
1070
  version = version.to_i
@@ -1083,6 +1076,30 @@ module ActiveRecord
1083
1076
  migrations.sort_by(&:version)
1084
1077
  end
1085
1078
 
1079
+ def migrations_status(paths)
1080
+ paths = Array(paths)
1081
+
1082
+ db_list = ActiveRecord::SchemaMigration.normalized_versions
1083
+
1084
+ file_list = migration_files(paths).map do |file|
1085
+ version, name, scope = parse_migration_filename(file)
1086
+ raise IllegalMigrationNameError.new(file) unless version
1087
+ version = ActiveRecord::SchemaMigration.normalize_migration_number(version)
1088
+ status = db_list.delete(version) ? "up" : "down"
1089
+ [status, version, (name + scope).humanize]
1090
+ end.compact
1091
+
1092
+ db_list.map! do |version|
1093
+ ["up", version, "********** NO FILE **********"]
1094
+ end
1095
+
1096
+ (db_list + file_list).sort_by { |_, version, _| version }
1097
+ end
1098
+
1099
+ def migration_files(paths)
1100
+ Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
1101
+ end
1102
+
1086
1103
  private
1087
1104
 
1088
1105
  def move(direction, migrations_paths, steps)
@@ -1098,8 +1115,6 @@ module ActiveRecord
1098
1115
  end
1099
1116
 
1100
1117
  def initialize(direction, migrations, target_version = nil)
1101
- raise StandardError.new("This database does not yet support migrations") unless Base.connection.supports_migrations?
1102
-
1103
1118
  @direction = direction
1104
1119
  @target_version = target_version
1105
1120
  @migrated_versions = nil
@@ -4,7 +4,7 @@ module ActiveRecord
4
4
  []
5
5
  end
6
6
 
7
- def delete_all(_conditions = nil)
7
+ def delete_all
8
8
  0
9
9
  end
10
10
 
@@ -9,7 +9,7 @@ module ActiveRecord
9
9
  delegate :find_each, :find_in_batches, :in_batches, to: :all
10
10
  delegate :select, :group, :order, :except, :reorder, :limit, :offset, :joins, :left_joins, :left_outer_joins, :or,
11
11
  :where, :rewhere, :preload, :eager_load, :includes, :from, :lock, :readonly,
12
- :having, :create_with, :uniq, :distinct, :references, :none, :unscope, :merge, to: :all
12
+ :having, :create_with, :distinct, :references, :none, :unscope, :merge, to: :all
13
13
  delegate :count, :average, :minimum, :maximum, :sum, :calculate, to: :all
14
14
  delegate :pluck, :ids, to: :all
15
15
 
@@ -110,28 +110,13 @@ db_namespace = namespace :db do
110
110
  unless ActiveRecord::SchemaMigration.table_exists?
111
111
  abort "Schema migrations table does not exist yet."
112
112
  end
113
- db_list = ActiveRecord::SchemaMigration.normalized_versions
114
-
115
- file_list =
116
- ActiveRecord::Tasks::DatabaseTasks.migrations_paths.flat_map do |path|
117
- Dir.foreach(path).map do |file|
118
- next unless ActiveRecord::Migrator.match_to_migration_filename?(file)
119
-
120
- version, name, scope = ActiveRecord::Migrator.parse_migration_filename(file)
121
- version = ActiveRecord::SchemaMigration.normalize_migration_number(version)
122
- status = db_list.delete(version) ? "up" : "down"
123
- [status, version, (name + scope).humanize]
124
- end.compact
125
- end
126
113
 
127
- db_list.map! do |version|
128
- ["up", version, "********** NO FILE **********"]
129
- end
130
114
  # output
131
115
  puts "\ndatabase: #{ActiveRecord::Base.connection_config[:database]}\n\n"
132
116
  puts "#{'Status'.center(8)} #{'Migration ID'.ljust(14)} Migration Name"
133
117
  puts "-" * 50
134
- (db_list + file_list).sort_by { |_, version, _| version }.each do |status, version, name|
118
+ paths = ActiveRecord::Tasks::DatabaseTasks.migrations_paths
119
+ ActiveRecord::Migrator.migrations_status(paths).each do |status, version, name|
135
120
  puts "#{status.center(8)} #{version.ljust(14)} #{name}"
136
121
  end
137
122
  puts
@@ -288,8 +273,7 @@ db_namespace = namespace :db do
288
273
  current_config = ActiveRecord::Tasks::DatabaseTasks.current_config
289
274
  ActiveRecord::Tasks::DatabaseTasks.structure_dump(current_config, filename)
290
275
 
291
- if ActiveRecord::Base.connection.supports_migrations? &&
292
- ActiveRecord::SchemaMigration.table_exists?
276
+ if ActiveRecord::SchemaMigration.table_exists?
293
277
  File.open(filename, "a") do |f|
294
278
  f.puts ActiveRecord::Base.connection.dump_schema_information
295
279
  f.print "\n"
@@ -172,8 +172,8 @@ module ActiveRecord
172
172
 
173
173
  JoinKeys = Struct.new(:key, :foreign_key) # :nodoc:
174
174
 
175
- def join_keys(association_klass)
176
- JoinKeys.new(foreign_key, active_record_primary_key)
175
+ def join_keys
176
+ get_join_keys klass
177
177
  end
178
178
 
179
179
  # Returns a list of scopes that should be applied for this Reflection
@@ -187,6 +187,30 @@ module ActiveRecord
187
187
  end
188
188
  deprecate :scope_chain
189
189
 
190
+ def join_scopes(table, predicate_builder) # :nodoc:
191
+ if scope
192
+ [ActiveRecord::Relation.create(klass, table, predicate_builder)
193
+ .instance_exec(&scope)]
194
+ else
195
+ []
196
+ end
197
+ end
198
+
199
+ def klass_join_scope(table, predicate_builder) # :nodoc:
200
+ if klass.current_scope
201
+ klass.current_scope.clone.tap { |scope|
202
+ scope.joins_values = []
203
+ }
204
+ else
205
+ relation = ActiveRecord::Relation.create(
206
+ klass,
207
+ table,
208
+ predicate_builder,
209
+ )
210
+ klass.send(:build_default_scope, relation)
211
+ end
212
+ end
213
+
190
214
  def constraints
191
215
  chain.map(&:scopes).flatten
192
216
  end
@@ -260,6 +284,20 @@ module ActiveRecord
260
284
  def chain
261
285
  collect_join_chain
262
286
  end
287
+
288
+ def get_join_keys(association_klass)
289
+ JoinKeys.new(join_pk(association_klass), join_fk)
290
+ end
291
+
292
+ private
293
+
294
+ def join_pk(_)
295
+ foreign_key
296
+ end
297
+
298
+ def join_fk
299
+ active_record_primary_key
300
+ end
263
301
  end
264
302
 
265
303
  # Base class for AggregateReflection and AssociationReflection. Objects of
@@ -687,11 +725,6 @@ module ActiveRecord
687
725
  end
688
726
  end
689
727
 
690
- def join_keys(association_klass)
691
- key = polymorphic? ? association_primary_key(association_klass) : association_primary_key
692
- JoinKeys.new(key, foreign_key)
693
- end
694
-
695
728
  def join_id_for(owner) # :nodoc:
696
729
  owner[foreign_key]
697
730
  end
@@ -701,6 +734,14 @@ module ActiveRecord
701
734
  def calculate_constructable(macro, options)
702
735
  !polymorphic?
703
736
  end
737
+
738
+ def join_fk
739
+ foreign_key
740
+ end
741
+
742
+ def join_pk(klass)
743
+ polymorphic? ? association_primary_key(klass) : association_primary_key
744
+ end
704
745
  end
705
746
 
706
747
  class HasAndBelongsToManyReflection < AssociationReflection # :nodoc:
@@ -720,7 +761,7 @@ module ActiveRecord
720
761
  class ThroughReflection < AbstractReflection #:nodoc:
721
762
  attr_reader :delegate_reflection
722
763
  delegate :foreign_key, :foreign_type, :association_foreign_key,
723
- :active_record_primary_key, :type, to: :source_reflection
764
+ :active_record_primary_key, :type, :get_join_keys, to: :source_reflection
724
765
 
725
766
  def initialize(delegate_reflection)
726
767
  @delegate_reflection = delegate_reflection
@@ -806,6 +847,10 @@ module ActiveRecord
806
847
  source_reflection.scopes + super
807
848
  end
808
849
 
850
+ def join_scopes(table, predicate_builder) # :nodoc:
851
+ source_reflection.join_scopes(table, predicate_builder) + super
852
+ end
853
+
809
854
  def source_type_scope
810
855
  through_reflection.klass.where(foreign_type => options[:source_type])
811
856
  end
@@ -816,10 +861,6 @@ module ActiveRecord
816
861
  through_reflection.has_scope?
817
862
  end
818
863
 
819
- def join_keys(association_klass)
820
- source_reflection.join_keys(association_klass)
821
- end
822
-
823
864
  # A through association is nested if there would be more than one join table
824
865
  def nested?
825
866
  source_reflection.through_reflection? || through_reflection.through_reflection?
@@ -954,6 +995,7 @@ module ActiveRecord
954
995
  end
955
996
 
956
997
  private
998
+
957
999
  def actual_source_reflection # FIXME: this is a horrible name
958
1000
  source_reflection.send(:actual_source_reflection)
959
1001
  end
@@ -990,6 +1032,15 @@ module ActiveRecord
990
1032
  end
991
1033
  end
992
1034
 
1035
+ def join_scopes(table, predicate_builder) # :nodoc:
1036
+ scopes = @previous_reflection.join_scopes(table, predicate_builder) + super
1037
+ if @previous_reflection.options[:source_type]
1038
+ scopes + [@previous_reflection.source_type_scope]
1039
+ else
1040
+ scopes
1041
+ end
1042
+ end
1043
+
993
1044
  def klass
994
1045
  @reflection.klass
995
1046
  end
@@ -1006,10 +1057,6 @@ module ActiveRecord
1006
1057
  @reflection.plural_name
1007
1058
  end
1008
1059
 
1009
- def join_keys(association_klass)
1010
- @reflection.join_keys(association_klass)
1011
- end
1012
-
1013
1060
  def type
1014
1061
  @reflection.type
1015
1062
  end
@@ -1023,6 +1070,10 @@ module ActiveRecord
1023
1070
  source_type = @previous_reflection.options[:source_type]
1024
1071
  lambda { |object| where(type => source_type) }
1025
1072
  end
1073
+
1074
+ def get_join_keys(association_klass)
1075
+ @reflection.get_join_keys(association_klass)
1076
+ end
1026
1077
  end
1027
1078
 
1028
1079
  class RuntimeReflection < PolymorphicReflection # :nodoc: