activerecord 5.0.0 → 5.0.7.2

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 (101) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +431 -2
  3. data/README.rdoc +1 -1
  4. data/lib/active_record/aggregations.rb +4 -2
  5. data/lib/active_record/association_relation.rb +4 -1
  6. data/lib/active_record/associations/association.rb +11 -1
  7. data/lib/active_record/associations/association_scope.rb +1 -1
  8. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +4 -2
  9. data/lib/active_record/associations/builder/singular_association.rb +10 -1
  10. data/lib/active_record/associations/collection_association.rb +56 -48
  11. data/lib/active_record/associations/collection_proxy.rb +38 -20
  12. data/lib/active_record/associations/has_many_association.rb +1 -7
  13. data/lib/active_record/associations/has_many_through_association.rb +2 -4
  14. data/lib/active_record/associations/join_dependency/join_association.rb +6 -11
  15. data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
  16. data/lib/active_record/associations/join_dependency.rb +10 -4
  17. data/lib/active_record/associations/preloader/association.rb +24 -37
  18. data/lib/active_record/associations/preloader/collection_association.rb +0 -1
  19. data/lib/active_record/associations/preloader/singular_association.rb +0 -1
  20. data/lib/active_record/associations/preloader/through_association.rb +10 -4
  21. data/lib/active_record/associations/singular_association.rb +8 -2
  22. data/lib/active_record/associations/through_association.rb +1 -1
  23. data/lib/active_record/associations.rb +38 -17
  24. data/lib/active_record/attribute.rb +3 -3
  25. data/lib/active_record/attribute_methods/primary_key.rb +14 -1
  26. data/lib/active_record/attribute_methods/read.rb +1 -1
  27. data/lib/active_record/attribute_methods/time_zone_conversion.rb +2 -2
  28. data/lib/active_record/attribute_methods.rb +3 -7
  29. data/lib/active_record/attribute_set/builder.rb +37 -13
  30. data/lib/active_record/attribute_set.rb +2 -0
  31. data/lib/active_record/attributes.rb +3 -3
  32. data/lib/active_record/autosave_association.rb +15 -11
  33. data/lib/active_record/base.rb +1 -1
  34. data/lib/active_record/collection_cache_key.rb +16 -6
  35. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +41 -33
  36. data/lib/active_record/connection_adapters/abstract/database_statements.rb +1 -1
  37. data/lib/active_record/connection_adapters/abstract/query_cache.rb +37 -2
  38. data/lib/active_record/connection_adapters/abstract/quoting.rb +14 -5
  39. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +11 -14
  40. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +68 -56
  41. data/lib/active_record/connection_adapters/abstract_adapter.rb +36 -12
  42. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +63 -60
  43. data/lib/active_record/connection_adapters/column.rb +1 -1
  44. data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
  45. data/lib/active_record/connection_adapters/mysql/database_statements.rb +8 -25
  46. data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
  47. data/lib/active_record/connection_adapters/mysql2_adapter.rb +2 -6
  48. data/lib/active_record/connection_adapters/postgresql/column.rb +28 -1
  49. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +8 -0
  50. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +12 -2
  51. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
  52. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
  53. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +10 -0
  54. data/lib/active_record/connection_adapters/postgresql/quoting.rb +32 -3
  55. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +18 -8
  56. data/lib/active_record/connection_adapters/postgresql/utils.rb +2 -2
  57. data/lib/active_record/connection_adapters/postgresql_adapter.rb +25 -19
  58. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +1 -1
  59. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +4 -4
  60. data/lib/active_record/core.rb +6 -4
  61. data/lib/active_record/enum.rb +8 -5
  62. data/lib/active_record/explain.rb +20 -9
  63. data/lib/active_record/fixtures.rb +5 -5
  64. data/lib/active_record/gem_version.rb +2 -2
  65. data/lib/active_record/integration.rb +13 -10
  66. data/lib/active_record/log_subscriber.rb +19 -17
  67. data/lib/active_record/migration.rb +35 -14
  68. data/lib/active_record/model_schema.rb +161 -52
  69. data/lib/active_record/no_touching.rb +4 -0
  70. data/lib/active_record/persistence.rb +41 -20
  71. data/lib/active_record/query_cache.rb +15 -17
  72. data/lib/active_record/querying.rb +3 -3
  73. data/lib/active_record/railties/controller_runtime.rb +1 -1
  74. data/lib/active_record/railties/databases.rake +9 -21
  75. data/lib/active_record/reflection.rb +20 -0
  76. data/lib/active_record/relation/batches.rb +10 -10
  77. data/lib/active_record/relation/calculations.rb +16 -12
  78. data/lib/active_record/relation/delegation.rb +2 -1
  79. data/lib/active_record/relation/finder_methods.rb +13 -11
  80. data/lib/active_record/relation/query_methods.rb +3 -3
  81. data/lib/active_record/relation.rb +12 -5
  82. data/lib/active_record/result.rb +7 -1
  83. data/lib/active_record/sanitization.rb +11 -1
  84. data/lib/active_record/schema_dumper.rb +10 -17
  85. data/lib/active_record/scoping/default.rb +5 -1
  86. data/lib/active_record/scoping/named.rb +18 -6
  87. data/lib/active_record/scoping.rb +4 -3
  88. data/lib/active_record/serialization.rb +1 -1
  89. data/lib/active_record/statement_cache.rb +2 -2
  90. data/lib/active_record/table_metadata.rb +4 -3
  91. data/lib/active_record/tasks/database_tasks.rb +14 -11
  92. data/lib/active_record/tasks/postgresql_database_tasks.rb +1 -1
  93. data/lib/active_record/touch_later.rb +6 -1
  94. data/lib/active_record/transactions.rb +1 -1
  95. data/lib/active_record/type/internal/abstract_json.rb +5 -1
  96. data/lib/active_record/validations/uniqueness.rb +3 -4
  97. data/lib/active_record.rb +3 -2
  98. data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -1
  99. data/lib/rails/generators/active_record/migration.rb +8 -0
  100. data/lib/rails/generators/active_record/model/model_generator.rb +1 -1
  101. metadata +7 -8
@@ -39,13 +39,8 @@ module ActiveRecord
39
39
  reload
40
40
  end
41
41
 
42
- if null_scope?
43
- # Cache the proxy separately before the owner has an id
44
- # or else a post-save proxy will still lack the id
45
- @null_proxy ||= CollectionProxy.create(klass, self)
46
- else
47
- @proxy ||= CollectionProxy.create(klass, self)
48
- end
42
+ @proxy ||= CollectionProxy.create(klass, self)
43
+ @proxy.reset_scope
49
44
  end
50
45
 
51
46
  # Implements the writer method, e.g. foo.items= for Foo.has_many :items
@@ -69,13 +64,20 @@ module ActiveRecord
69
64
 
70
65
  # Implements the ids writer method, e.g. foo.item_ids= for Foo.has_many :items
71
66
  def ids_writer(ids)
72
- pk_type = reflection.primary_key_type
67
+ pk_type = reflection.association_primary_key_type
73
68
  ids = Array(ids).reject(&:blank?)
74
69
  ids.map! { |i| pk_type.cast(i) }
75
- records = klass.where(reflection.association_primary_key => ids).index_by do |r|
76
- r.send(reflection.association_primary_key)
77
- end.values_at(*ids)
78
- replace(records)
70
+
71
+ primary_key = reflection.association_primary_key
72
+ records = klass.where(primary_key => ids).index_by do |r|
73
+ r.public_send(primary_key)
74
+ end.values_at(*ids).compact
75
+
76
+ if records.size != ids.size
77
+ klass.all.raise_record_not_found_exception!(ids, records.size, ids.size, primary_key)
78
+ else
79
+ replace(records)
80
+ end
79
81
  end
80
82
 
81
83
  def reset
@@ -312,9 +314,9 @@ module ActiveRecord
312
314
  else
313
315
  target.size
314
316
  end
315
- elsif !loaded? && !association_scope.group_values.empty?
317
+ elsif !association_scope.group_values.empty?
316
318
  load_target.size
317
- elsif !loaded? && !association_scope.distinct_value && target.is_a?(Array)
319
+ elsif !association_scope.distinct_value && target.is_a?(Array)
318
320
  unsaved_records = target.select(&:new_record?)
319
321
  unsaved_records.size + count_records
320
322
  else
@@ -423,29 +425,9 @@ module ActiveRecord
423
425
  replace_on_target(record, index, skip_callbacks, &block)
424
426
  end
425
427
 
426
- def replace_on_target(record, index, skip_callbacks)
427
- callback(:before_add, record) unless skip_callbacks
428
-
429
- was_loaded = loaded?
430
- yield(record) if block_given?
431
-
432
- unless !was_loaded && loaded?
433
- if index
434
- @target[index] = record
435
- else
436
- @target << record
437
- end
438
- end
439
-
440
- callback(:after_add, record) unless skip_callbacks
441
- set_inverse_instance(record)
442
-
443
- record
444
- end
445
-
446
- def scope(opts = {})
447
- scope = super()
448
- scope.none! if opts.fetch(:nullify, true) && null_scope?
428
+ def scope
429
+ scope = super
430
+ scope.none! if null_scope?
449
431
  scope
450
432
  end
451
433
 
@@ -454,7 +436,7 @@ module ActiveRecord
454
436
  end
455
437
 
456
438
  private
457
- def get_records
439
+ def get_records(&block)
458
440
  return scope.to_a if skip_statement_cache?
459
441
 
460
442
  conn = klass.connection
@@ -466,13 +448,13 @@ module ActiveRecord
466
448
  end
467
449
 
468
450
  binds = AssociationScope.get_bind_values(owner, reflection.chain)
469
- sc.execute binds, klass, klass.connection
451
+ sc.execute(binds, klass, klass.connection, &block)
470
452
  end
471
453
 
472
454
  def find_target
473
- records = get_records
474
- records.each { |record| set_inverse_instance(record) }
475
- records
455
+ get_records do |record|
456
+ set_inverse_instance(record)
457
+ end
476
458
  end
477
459
 
478
460
  # We have some records loaded from the database (persisted) and some that are
@@ -516,15 +498,19 @@ module ActiveRecord
516
498
  transaction do
517
499
  add_to_target(build_record(attributes)) do |record|
518
500
  yield(record) if block_given?
519
- insert_record(record, true, raise)
501
+ insert_record(record, true, raise) { @_was_loaded = loaded? }
520
502
  end
521
503
  end
522
504
  end
523
505
  end
524
506
 
525
507
  # Do the relevant stuff to insert the given record into the association collection.
526
- def insert_record(record, validate = true, raise = false)
527
- raise NotImplementedError
508
+ def insert_record(record, validate = true, raise = false, &block)
509
+ if raise
510
+ record.save!(validate: validate, &block)
511
+ else
512
+ record.save(validate: validate, &block)
513
+ end
528
514
  end
529
515
 
530
516
  def create_scope
@@ -578,19 +564,41 @@ module ActiveRecord
578
564
  end
579
565
  end
580
566
 
581
- def concat_records(records, should_raise = false)
567
+ def concat_records(records, raise = false)
582
568
  result = true
583
569
 
584
570
  records.each do |record|
585
571
  raise_on_type_mismatch!(record)
586
- add_to_target(record) do |rec|
587
- result &&= insert_record(rec, true, should_raise) unless owner.new_record?
572
+ add_to_target(record) do
573
+ result &&= insert_record(record, true, raise) { @_was_loaded = loaded? } unless owner.new_record?
588
574
  end
589
575
  end
590
576
 
591
577
  result && records
592
578
  end
593
579
 
580
+ def replace_on_target(record, index, skip_callbacks)
581
+ callback(:before_add, record) unless skip_callbacks
582
+
583
+ set_inverse_instance(record)
584
+
585
+ @_was_loaded = true
586
+
587
+ yield(record) if block_given?
588
+
589
+ if index
590
+ target[index] = record
591
+ elsif @_was_loaded || !loaded?
592
+ target << record
593
+ end
594
+
595
+ callback(:after_add, record) unless skip_callbacks
596
+
597
+ record
598
+ ensure
599
+ @_was_loaded = nil
600
+ end
601
+
594
602
  def callback(method, record)
595
603
  callbacks_for(method).each do |callback|
596
604
  callback.call(method, owner, record)
@@ -28,13 +28,12 @@ module ActiveRecord
28
28
  # is computed directly through SQL and does not trigger by itself the
29
29
  # instantiation of the actual post records.
30
30
  class CollectionProxy < Relation
31
- delegate(*(ActiveRecord::Calculations.public_instance_methods - [:count]), to: :scope)
32
- delegate :find_nth, to: :scope
33
-
34
31
  def initialize(klass, association) #:nodoc:
35
32
  @association = association
36
33
  super klass, klass.arel_table, klass.predicate_builder
37
- merge! association.scope(nullify: false)
34
+
35
+ extensions = association.extensions
36
+ extend(*extensions) if extensions.any?
38
37
  end
39
38
 
40
39
  def target
@@ -732,6 +731,14 @@ module ActiveRecord
732
731
  @association.count(column_name)
733
732
  end
734
733
 
734
+ def calculate(operation, column_name)
735
+ null_scope? ? scope.calculate(operation, column_name) : super
736
+ end
737
+
738
+ def pluck(*column_names)
739
+ null_scope? ? scope.pluck(*column_names) : super
740
+ end
741
+
735
742
  # Returns the size of the collection. If the collection hasn't been loaded,
736
743
  # it executes a <tt>SELECT COUNT(*)</tt> query. Else it calls <tt>collection.size</tt>.
737
744
  #
@@ -787,7 +794,7 @@ module ActiveRecord
787
794
  # Returns +true+ if the collection is empty. If the collection has been
788
795
  # loaded it is equivalent
789
796
  # to <tt>collection.size.zero?</tt>. If the collection has not been loaded,
790
- # it is equivalent to <tt>collection.exists?</tt>. If the collection has
797
+ # it is equivalent to <tt>!collection.exists?</tt>. If the collection has
791
798
  # not already been loaded and you are going to fetch the records anyway it
792
799
  # is better to check <tt>collection.length.zero?</tt>.
793
800
  #
@@ -891,27 +898,14 @@ module ActiveRecord
891
898
  !!@association.include?(record)
892
899
  end
893
900
 
894
- def arel #:nodoc:
895
- scope.arel
896
- end
897
-
898
901
  def proxy_association
899
902
  @association
900
903
  end
901
904
 
902
- # We don't want this object to be put on the scoping stack, because
903
- # that could create an infinite loop where we call an @association
904
- # method, which gets the current scope, which is this object, which
905
- # delegates to @association, and so on.
906
- def scoping
907
- @association.scope.scoping { yield }
908
- end
909
-
910
905
  # Returns a <tt>Relation</tt> object for the records in this association
911
906
  def scope
912
- @association.scope
907
+ @scope ||= @association.scope
913
908
  end
914
- alias spawn scope
915
909
 
916
910
  # Equivalent to <tt>Array#==</tt>. Returns +true+ if the two arrays
917
911
  # contain the same number of elements and if each element is equal
@@ -1044,7 +1038,7 @@ module ActiveRecord
1044
1038
  # # => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]
1045
1039
  def reload
1046
1040
  proxy_association.reload
1047
- self
1041
+ reset_scope
1048
1042
  end
1049
1043
 
1050
1044
  # Unloads the association. Returns +self+.
@@ -1066,8 +1060,32 @@ module ActiveRecord
1066
1060
  def reset
1067
1061
  proxy_association.reset
1068
1062
  proxy_association.reset_scope
1063
+ reset_scope
1064
+ end
1065
+
1066
+ def reset_scope # :nodoc:
1067
+ @scope = nil
1069
1068
  self
1070
1069
  end
1070
+
1071
+ delegate_methods = [
1072
+ QueryMethods,
1073
+ SpawnMethods,
1074
+ ].flat_map { |klass|
1075
+ klass.public_instance_methods(false)
1076
+ } - self.public_instance_methods(false) + [:scoping]
1077
+
1078
+ delegate(*delegate_methods, to: :scope)
1079
+
1080
+ private
1081
+
1082
+ def null_scope?
1083
+ @association.null_scope?
1084
+ end
1085
+
1086
+ def exec_queries
1087
+ load_target
1088
+ end
1071
1089
  end
1072
1090
  end
1073
1091
  end
@@ -40,13 +40,7 @@ module ActiveRecord
40
40
 
41
41
  def insert_record(record, validate = true, raise = false)
42
42
  set_owner_attributes(record)
43
- set_inverse_instance(record)
44
-
45
- if raise
46
- record.save!(:validate => validate)
47
- else
48
- record.save(:validate => validate)
49
- end
43
+ super
50
44
  end
51
45
 
52
46
  def empty?
@@ -38,10 +38,8 @@ module ActiveRecord
38
38
  def insert_record(record, validate = true, raise = false)
39
39
  ensure_not_nested
40
40
 
41
- if raise
42
- record.save!(:validate => validate)
43
- else
44
- return unless record.save(:validate => validate)
41
+ if record.new_record? || record.changed?
42
+ return unless super
45
43
  end
46
44
 
47
45
  save_through_record(record)
@@ -54,22 +54,17 @@ module ActiveRecord
54
54
  end
55
55
  scope_chain_index += 1
56
56
 
57
+ relation = ActiveRecord::Relation.create(klass, table, predicate_builder)
58
+ current_scope = klass.current_scope
59
+
57
60
  klass_scope =
58
- if klass.current_scope
59
- klass.current_scope.clone
61
+ if current_scope && current_scope.empty_scope?
62
+ relation
60
63
  else
61
- relation = ActiveRecord::Relation.create(
62
- klass,
63
- table,
64
- predicate_builder,
65
- )
66
64
  klass.send(:build_default_scope, relation)
67
65
  end
68
- scope_chain_items.concat [klass_scope].compact
69
66
 
70
- rel = scope_chain_items.inject(scope_chain_items.shift) do |left, right|
71
- left.merge right
72
- end
67
+ rel = scope_chain_items.inject(klass_scope || scope_chain_items.shift, &:merge!)
73
68
 
74
69
  if rel && !rel.arel.constraints.empty?
75
70
  binds += rel.bound_attributes
@@ -62,8 +62,8 @@ module ActiveRecord
62
62
  hash
63
63
  end
64
64
 
65
- def instantiate(row, aliases)
66
- base_klass.instantiate(extract_record(row, aliases))
65
+ def instantiate(row, aliases, &block)
66
+ base_klass.instantiate(extract_record(row, aliases), &block)
67
67
  end
68
68
  end
69
69
  end
@@ -272,7 +272,11 @@ module ActiveRecord
272
272
  construct(model, node, row, rs, seen, model_cache, aliases)
273
273
  else
274
274
  model = construct_model(ar_parent, node, row, model_cache, id, aliases)
275
- model.readonly!
275
+
276
+ if node.reflection.scope_for(node.base_klass).readonly_value
277
+ model.readonly!
278
+ end
279
+
276
280
  seen[ar_parent.object_id][node.base_klass][id] = model
277
281
  construct(model, node, row, rs, seen, model_cache, aliases)
278
282
  end
@@ -280,17 +284,19 @@ module ActiveRecord
280
284
  end
281
285
 
282
286
  def construct_model(record, node, row, model_cache, id, aliases)
283
- model = model_cache[node][id] ||= node.instantiate(row,
284
- aliases.column_aliases(node))
285
287
  other = record.association(node.reflection.name)
286
288
 
289
+ model = model_cache[node][id] ||=
290
+ node.instantiate(row, aliases.column_aliases(node)) do |m|
291
+ other.set_inverse_instance(m)
292
+ end
293
+
287
294
  if node.reflection.collection?
288
295
  other.target.push(model)
289
296
  else
290
297
  other.target = model
291
298
  end
292
299
 
293
- other.set_inverse_instance(model)
294
300
  model
295
301
  end
296
302
  end
@@ -62,7 +62,12 @@ module ActiveRecord
62
62
  private
63
63
 
64
64
  def associated_records_by_owner(preloader)
65
- records = load_records
65
+ records = load_records do |record|
66
+ owner = owners_by_key[convert_key(record[association_key_name])]
67
+ association = owner.association(reflection.name)
68
+ association.set_inverse_instance(record)
69
+ end
70
+
66
71
  owners.each_with_object({}) do |owner, result|
67
72
  result[owner] = records[convert_key(owner[owner_key_name])] || []
68
73
  end
@@ -79,6 +84,15 @@ module ActiveRecord
79
84
  @owner_keys
80
85
  end
81
86
 
87
+ def owners_by_key
88
+ unless defined?(@owners_by_key)
89
+ @owners_by_key = owners.each_with_object({}) do |owner, h|
90
+ h[convert_key(owner[owner_key_name])] = owner
91
+ end
92
+ end
93
+ @owners_by_key
94
+ end
95
+
82
96
  def key_conversion_required?
83
97
  @key_conversion_required ||= association_key_type != owner_key_type
84
98
  end
@@ -99,13 +113,13 @@ module ActiveRecord
99
113
  @model.type_for_attribute(owner_key_name.to_s).type
100
114
  end
101
115
 
102
- def load_records
116
+ def load_records(&block)
103
117
  return {} if owner_keys.empty?
104
118
  # Some databases impose a limit on the number of ids in a list (in Oracle it's 1000)
105
119
  # Make several smaller queries if necessary or make one query if the adapter supports it
106
120
  slices = owner_keys.each_slice(klass.connection.in_clause_length || owner_keys.size)
107
121
  @preloaded_records = slices.flat_map do |slice|
108
- records_for(slice)
122
+ records_for(slice).load(&block)
109
123
  end
110
124
  @preloaded_records.group_by do |record|
111
125
  convert_key(record[association_key_name])
@@ -113,46 +127,19 @@ module ActiveRecord
113
127
  end
114
128
 
115
129
  def reflection_scope
116
- @reflection_scope ||= reflection.scope ? klass.unscoped.instance_exec(nil, &reflection.scope) : klass.unscoped
130
+ @reflection_scope ||= reflection.scope_for(klass)
117
131
  end
118
132
 
119
133
  def build_scope
120
- scope = klass.unscoped
121
-
122
- values = reflection_scope.values
123
- preload_values = preload_scope.values
124
-
125
- scope.where_clause = reflection_scope.where_clause + preload_scope.where_clause
126
- scope.references_values = Array(values[:references]) + Array(preload_values[:references])
127
-
128
- if preload_values[:select] || values[:select]
129
- scope._select!(preload_values[:select] || values[:select])
130
- end
131
- scope.includes! preload_values[:includes] || values[:includes]
132
- if preload_scope.joins_values.any?
133
- scope.joins!(preload_scope.joins_values)
134
- else
135
- scope.joins!(reflection_scope.joins_values)
136
- end
137
-
138
- if order_values = preload_values[:order] || values[:order]
139
- scope.order!(order_values)
140
- end
141
-
142
- if preload_values[:reordering] || values[:reordering]
143
- scope.reordering_value = true
144
- end
145
-
146
- if preload_values[:readonly] || values[:readonly]
147
- scope.readonly!
148
- end
134
+ scope = klass.scope_for_association
149
135
 
150
- if options[:as]
151
- scope.where!(klass.table_name => { reflection.type => model.base_class.sti_name })
136
+ if reflection.type
137
+ scope.where!(reflection.type => model.base_class.sti_name)
152
138
  end
153
139
 
154
- scope.unscope_values = Array(values[:unscope]) + Array(preload_values[:unscope])
155
- klass.default_scoped.merge(scope)
140
+ scope.merge!(reflection_scope)
141
+ scope.merge!(preload_scope) if preload_scope != NULL_RELATION
142
+ scope
156
143
  end
157
144
  end
158
145
  end
@@ -9,7 +9,6 @@ module ActiveRecord
9
9
  association = owner.association(reflection.name)
10
10
  association.loaded!
11
11
  association.target.concat(records)
12
- records.each { |record| association.set_inverse_instance(record) }
13
12
  end
14
13
  end
15
14
  end
@@ -11,7 +11,6 @@ module ActiveRecord
11
11
 
12
12
  association = owner.association(reflection.name)
13
13
  association.target = record
14
- association.set_inverse_instance(record) if record
15
14
  end
16
15
  end
17
16
 
@@ -79,20 +79,26 @@ module ActiveRecord
79
79
  end
80
80
  end
81
81
 
82
-
83
82
  def through_scope
84
83
  scope = through_reflection.klass.unscoped
84
+ values = reflection_scope.values
85
85
 
86
86
  if options[:source_type]
87
87
  scope.where! reflection.foreign_type => options[:source_type]
88
88
  else
89
89
  unless reflection_scope.where_clause.empty?
90
- scope.includes_values = Array(reflection_scope.values[:includes] || options[:source])
90
+ scope.includes_values = Array(values[:includes] || options[:source])
91
91
  scope.where_clause = reflection_scope.where_clause
92
+ if joins = values[:joins]
93
+ scope.joins!(source_reflection.name => joins)
94
+ end
95
+ if left_outer_joins = values[:left_outer_joins]
96
+ scope.left_outer_joins!(source_reflection.name => left_outer_joins)
97
+ end
92
98
  end
93
99
 
94
- scope.references! reflection_scope.values[:references]
95
- if scope.eager_loading? && order_values = reflection_scope.values[:order]
100
+ scope.references! values[:references]
101
+ if scope.eager_loading? && order_values = values[:order]
96
102
  scope = scope.order(order_values)
97
103
  end
98
104
  end
@@ -6,8 +6,7 @@ module ActiveRecord
6
6
  if force_reload && klass
7
7
  ActiveSupport::Deprecation.warn(<<-MSG.squish)
8
8
  Passing an argument to force an association to reload is now
9
- deprecated and will be removed in Rails 5.1. Please call `reload`
10
- on the parent object instead.
9
+ deprecated and will be removed in Rails 5.1. Please call `reload_#{reflection.name}` instead.
11
10
  MSG
12
11
 
13
12
  klass.uncached { reload }
@@ -38,6 +37,13 @@ module ActiveRecord
38
37
  record
39
38
  end
40
39
 
40
+ # Implements the reload reader method, e.g. foo.reload_bar for
41
+ # Foo.has_one :bar
42
+ def force_reload_reader
43
+ klass.uncached { reload }
44
+ target
45
+ end
46
+
41
47
  private
42
48
 
43
49
  def create_scope
@@ -14,7 +14,7 @@ module ActiveRecord
14
14
  def target_scope
15
15
  scope = super
16
16
  reflection.chain.drop(1).each do |reflection|
17
- relation = reflection.klass.all
17
+ relation = reflection.klass.scope_for_association
18
18
  scope.merge!(
19
19
  relation.except(:select, :create_with, :includes, :preload, :joins, :eager_load)
20
20
  )