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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +431 -2
- data/README.rdoc +1 -1
- data/lib/active_record/aggregations.rb +4 -2
- data/lib/active_record/association_relation.rb +4 -1
- data/lib/active_record/associations/association.rb +11 -1
- data/lib/active_record/associations/association_scope.rb +1 -1
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +4 -2
- data/lib/active_record/associations/builder/singular_association.rb +10 -1
- data/lib/active_record/associations/collection_association.rb +56 -48
- data/lib/active_record/associations/collection_proxy.rb +38 -20
- data/lib/active_record/associations/has_many_association.rb +1 -7
- data/lib/active_record/associations/has_many_through_association.rb +2 -4
- data/lib/active_record/associations/join_dependency/join_association.rb +6 -11
- data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
- data/lib/active_record/associations/join_dependency.rb +10 -4
- data/lib/active_record/associations/preloader/association.rb +24 -37
- data/lib/active_record/associations/preloader/collection_association.rb +0 -1
- data/lib/active_record/associations/preloader/singular_association.rb +0 -1
- data/lib/active_record/associations/preloader/through_association.rb +10 -4
- data/lib/active_record/associations/singular_association.rb +8 -2
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/associations.rb +38 -17
- data/lib/active_record/attribute.rb +3 -3
- data/lib/active_record/attribute_methods/primary_key.rb +14 -1
- data/lib/active_record/attribute_methods/read.rb +1 -1
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +2 -2
- data/lib/active_record/attribute_methods.rb +3 -7
- data/lib/active_record/attribute_set/builder.rb +37 -13
- data/lib/active_record/attribute_set.rb +2 -0
- data/lib/active_record/attributes.rb +3 -3
- data/lib/active_record/autosave_association.rb +15 -11
- data/lib/active_record/base.rb +1 -1
- data/lib/active_record/collection_cache_key.rb +16 -6
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +41 -33
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +37 -2
- data/lib/active_record/connection_adapters/abstract/quoting.rb +14 -5
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +11 -14
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +68 -56
- data/lib/active_record/connection_adapters/abstract_adapter.rb +36 -12
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +63 -60
- data/lib/active_record/connection_adapters/column.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +8 -25
- data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +2 -6
- data/lib/active_record/connection_adapters/postgresql/column.rb +28 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +8 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +12 -2
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +10 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +32 -3
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +18 -8
- data/lib/active_record/connection_adapters/postgresql/utils.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +25 -19
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +4 -4
- data/lib/active_record/core.rb +6 -4
- data/lib/active_record/enum.rb +8 -5
- data/lib/active_record/explain.rb +20 -9
- data/lib/active_record/fixtures.rb +5 -5
- data/lib/active_record/gem_version.rb +2 -2
- data/lib/active_record/integration.rb +13 -10
- data/lib/active_record/log_subscriber.rb +19 -17
- data/lib/active_record/migration.rb +35 -14
- data/lib/active_record/model_schema.rb +161 -52
- data/lib/active_record/no_touching.rb +4 -0
- data/lib/active_record/persistence.rb +41 -20
- data/lib/active_record/query_cache.rb +15 -17
- data/lib/active_record/querying.rb +3 -3
- data/lib/active_record/railties/controller_runtime.rb +1 -1
- data/lib/active_record/railties/databases.rake +9 -21
- data/lib/active_record/reflection.rb +20 -0
- data/lib/active_record/relation/batches.rb +10 -10
- data/lib/active_record/relation/calculations.rb +16 -12
- data/lib/active_record/relation/delegation.rb +2 -1
- data/lib/active_record/relation/finder_methods.rb +13 -11
- data/lib/active_record/relation/query_methods.rb +3 -3
- data/lib/active_record/relation.rb +12 -5
- data/lib/active_record/result.rb +7 -1
- data/lib/active_record/sanitization.rb +11 -1
- data/lib/active_record/schema_dumper.rb +10 -17
- data/lib/active_record/scoping/default.rb +5 -1
- data/lib/active_record/scoping/named.rb +18 -6
- data/lib/active_record/scoping.rb +4 -3
- data/lib/active_record/serialization.rb +1 -1
- data/lib/active_record/statement_cache.rb +2 -2
- data/lib/active_record/table_metadata.rb +4 -3
- data/lib/active_record/tasks/database_tasks.rb +14 -11
- data/lib/active_record/tasks/postgresql_database_tasks.rb +1 -1
- data/lib/active_record/touch_later.rb +6 -1
- data/lib/active_record/transactions.rb +1 -1
- data/lib/active_record/type/internal/abstract_json.rb +5 -1
- data/lib/active_record/validations/uniqueness.rb +3 -4
- data/lib/active_record.rb +3 -2
- data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -1
- data/lib/rails/generators/active_record/migration.rb +8 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +1 -1
- metadata +7 -8
@@ -39,13 +39,8 @@ module ActiveRecord
|
|
39
39
|
reload
|
40
40
|
end
|
41
41
|
|
42
|
-
|
43
|
-
|
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.
|
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
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
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 !
|
317
|
+
elsif !association_scope.group_values.empty?
|
316
318
|
load_target.size
|
317
|
-
elsif !
|
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
|
427
|
-
|
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
|
451
|
+
sc.execute(binds, klass, klass.connection, &block)
|
470
452
|
end
|
471
453
|
|
472
454
|
def find_target
|
473
|
-
|
474
|
-
|
475
|
-
|
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
|
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,
|
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
|
587
|
-
result &&= insert_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
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
42
|
-
|
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
|
59
|
-
|
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
|
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
|
@@ -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
|
-
|
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.
|
130
|
+
@reflection_scope ||= reflection.scope_for(klass)
|
117
131
|
end
|
118
132
|
|
119
133
|
def build_scope
|
120
|
-
scope = klass.
|
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
|
151
|
-
scope.where!(
|
136
|
+
if reflection.type
|
137
|
+
scope.where!(reflection.type => model.base_class.sti_name)
|
152
138
|
end
|
153
139
|
|
154
|
-
scope.
|
155
|
-
|
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
|
@@ -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(
|
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!
|
95
|
-
if scope.eager_loading? && order_values =
|
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 `
|
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.
|
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
|
)
|