activerecord 6.0.0.beta1 → 6.0.0.beta2
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 +4 -4
- data/CHANGELOG.md +99 -2
- data/lib/active_record.rb +7 -0
- data/lib/active_record/associations/association.rb +17 -0
- data/lib/active_record/associations/collection_association.rb +5 -6
- data/lib/active_record/associations/collection_proxy.rb +12 -41
- data/lib/active_record/associations/has_many_association.rb +1 -9
- data/lib/active_record/associations/join_dependency/join_association.rb +11 -6
- data/lib/active_record/associations/preloader/association.rb +3 -4
- data/lib/active_record/associations/preloader/through_association.rb +9 -20
- data/lib/active_record/callbacks.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +25 -12
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +17 -9
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +6 -1
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +5 -2
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +47 -33
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +16 -8
- data/lib/active_record/connection_adapters/abstract/transaction.rb +5 -2
- data/lib/active_record/connection_adapters/abstract_adapter.rb +6 -4
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +28 -65
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +40 -32
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +8 -2
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +59 -1
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +6 -3
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +36 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +98 -89
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +15 -27
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +30 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +27 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +8 -5
- data/lib/active_record/connection_handling.rb +9 -4
- data/lib/active_record/core.rb +13 -1
- data/lib/active_record/database_configurations.rb +30 -10
- data/lib/active_record/database_configurations/hash_config.rb +1 -1
- data/lib/active_record/database_configurations/url_config.rb +9 -4
- data/lib/active_record/errors.rb +17 -12
- data/lib/active_record/gem_version.rb +1 -1
- data/lib/active_record/inheritance.rb +1 -1
- data/lib/active_record/middleware/database_selector.rb +75 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +90 -0
- data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
- data/lib/active_record/migration.rb +1 -1
- data/lib/active_record/migration/compatibility.rb +62 -63
- data/lib/active_record/persistence.rb +6 -6
- data/lib/active_record/querying.rb +2 -3
- data/lib/active_record/railtie.rb +9 -0
- data/lib/active_record/railties/collection_cache_association_loading.rb +3 -3
- data/lib/active_record/reflection.rb +15 -29
- data/lib/active_record/relation.rb +86 -15
- data/lib/active_record/relation/calculations.rb +2 -4
- data/lib/active_record/relation/delegation.rb +1 -1
- data/lib/active_record/relation/finder_methods.rb +8 -4
- data/lib/active_record/relation/query_attribute.rb +5 -3
- data/lib/active_record/relation/query_methods.rb +28 -8
- data/lib/active_record/relation/spawn_methods.rb +1 -1
- data/lib/active_record/relation/where_clause.rb +1 -5
- data/lib/active_record/scoping.rb +6 -7
- data/lib/active_record/scoping/default.rb +1 -8
- data/lib/active_record/scoping/named.rb +9 -1
- data/lib/active_record/test_fixtures.rb +2 -2
- data/lib/active_record/timestamp.rb +9 -3
- data/lib/active_record/validations/uniqueness.rb +3 -1
- data/lib/arel.rb +7 -0
- data/lib/arel/nodes/and.rb +1 -1
- data/lib/arel/nodes/case.rb +1 -1
- metadata +11 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 65ea4dc67676807bb1cec848b592808e9ae0c17428347bc1c54b9d8c7fe7540d
|
4
|
+
data.tar.gz: e0c6e2c537026df44775de8c26e8999ce304bfb77fddd9b8f854758c655540b7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3f5d1751f4b0be87fe91d8aac2216dd3184374b59e84b02d02f5578729bf22a51e73a9b21fc2bbc86a869cdbdd2386f6e25c0aba3424be842de17d2891844f4d
|
7
|
+
data.tar.gz: 1826fca9a8b097f7e4dd896fc08012bf10ce40159d75676838e16cb2dd72dce252eef5f3a4ab2a0a7eef1438c47584b0521d7fd9f573fa5bfb61cbfe11d98d52
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,100 @@
|
|
1
|
+
## Rails 6.0.0.beta2 (February 25, 2019) ##
|
2
|
+
|
3
|
+
* Fix prepared statements caching to be enabled even when query caching is enabled.
|
4
|
+
|
5
|
+
*Ryuta Kamizono*
|
6
|
+
|
7
|
+
* Ensure `update_all` series cares about optimistic locking.
|
8
|
+
|
9
|
+
*Ryuta Kamizono*
|
10
|
+
|
11
|
+
* Don't allow `where` with non numeric string matches to 0 values.
|
12
|
+
|
13
|
+
*Ryuta Kamizono*
|
14
|
+
|
15
|
+
* Introduce `ActiveRecord::Relation#destroy_by` and `ActiveRecord::Relation#delete_by`.
|
16
|
+
|
17
|
+
`destroy_by` allows relation to find all the records matching the condition and perform
|
18
|
+
`destroy_all` on the matched records.
|
19
|
+
|
20
|
+
Example:
|
21
|
+
|
22
|
+
Person.destroy_by(name: 'David')
|
23
|
+
Person.destroy_by(name: 'David', rating: 4)
|
24
|
+
|
25
|
+
david = Person.find_by(name: 'David')
|
26
|
+
david.posts.destroy_by(id: [1, 2, 3])
|
27
|
+
|
28
|
+
`delete_by` allows relation to find all the records matching the condition and perform
|
29
|
+
`delete_all` on the matched records.
|
30
|
+
|
31
|
+
Example:
|
32
|
+
|
33
|
+
Person.delete_by(name: 'David')
|
34
|
+
Person.delete_by(name: 'David', rating: 4)
|
35
|
+
|
36
|
+
david = Person.find_by(name: 'David')
|
37
|
+
david.posts.delete_by(id: [1, 2, 3])
|
38
|
+
|
39
|
+
*Abhay Nikam*
|
40
|
+
|
41
|
+
* Don't allow `where` with invalid value matches to nil values.
|
42
|
+
|
43
|
+
Fixes #33624.
|
44
|
+
|
45
|
+
*Ryuta Kamizono*
|
46
|
+
|
47
|
+
* SQLite3: Implement `add_foreign_key` and `remove_foreign_key`.
|
48
|
+
|
49
|
+
*Ryuta Kamizono*
|
50
|
+
|
51
|
+
* Deprecate using class level querying methods if the receiver scope
|
52
|
+
regarded as leaked. Use `klass.unscoped` to avoid the leaking scope.
|
53
|
+
|
54
|
+
*Ryuta Kamizono*
|
55
|
+
|
56
|
+
* Allow applications to automatically switch connections.
|
57
|
+
|
58
|
+
Adds a middleware and configuration options that can be used in your
|
59
|
+
application to automatically switch between the writing and reading
|
60
|
+
database connections.
|
61
|
+
|
62
|
+
`GET` and `HEAD` requests will read from the replica unless there was
|
63
|
+
a write in the last 2 seconds, otherwise they will read from the primary.
|
64
|
+
Non-get requests will always write to the primary. The middleware accepts
|
65
|
+
an argument for a Resolver class and a Operations class where you are able
|
66
|
+
to change how the auto-switcher works to be most beneficial for your
|
67
|
+
application.
|
68
|
+
|
69
|
+
To use the middleware in your application you can use the following
|
70
|
+
configuration options:
|
71
|
+
|
72
|
+
```
|
73
|
+
config.active_record.database_selector = { delay: 2.seconds }
|
74
|
+
config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver
|
75
|
+
config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session
|
76
|
+
```
|
77
|
+
|
78
|
+
To change the database selection strategy, pass a custom class to the
|
79
|
+
configuration options:
|
80
|
+
|
81
|
+
```
|
82
|
+
config.active_record.database_selector = { delay: 10.seconds }
|
83
|
+
config.active_record.database_resolver = MyResolver
|
84
|
+
config.active_record.database_resolver_context = MyResolver::MyCookies
|
85
|
+
```
|
86
|
+
|
87
|
+
*Eileen M. Uchitelle*
|
88
|
+
|
89
|
+
* MySQL: Support `:size` option to change text and blob size.
|
90
|
+
|
91
|
+
*Ryuta Kamizono*
|
92
|
+
|
93
|
+
* Make `t.timestamps` with precision by default.
|
94
|
+
|
95
|
+
*Ryuta Kamizono*
|
96
|
+
|
97
|
+
|
1
98
|
## Rails 6.0.0.beta1 (January 18, 2019) ##
|
2
99
|
|
3
100
|
* Remove deprecated `#set_state` from the transaction object.
|
@@ -454,8 +551,8 @@
|
|
454
551
|
|
455
552
|
Iterating over the database configurations has also changed. Instead of
|
456
553
|
calling hash methods on the `configurations` hash directly, a new method `configs_for` has
|
457
|
-
been provided that allows you to select the correct configuration. `env_name
|
458
|
-
`spec_name` arguments are optional. For example these return an array of
|
554
|
+
been provided that allows you to select the correct configuration. `env_name` and
|
555
|
+
`spec_name` arguments are optional. For example, these return an array of
|
459
556
|
database config objects for the requested environment and a single database config object
|
460
557
|
will be returned for the requested environment and specification name respectively.
|
461
558
|
|
data/lib/active_record.rb
CHANGED
@@ -74,6 +74,7 @@ module ActiveRecord
|
|
74
74
|
autoload :Translation
|
75
75
|
autoload :Validations
|
76
76
|
autoload :SecureToken
|
77
|
+
autoload :DatabaseSelector, "active_record/middleware/database_selector"
|
77
78
|
|
78
79
|
eager_autoload do
|
79
80
|
autoload :ActiveRecordError, "active_record/errors"
|
@@ -153,6 +154,12 @@ module ActiveRecord
|
|
153
154
|
end
|
154
155
|
end
|
155
156
|
|
157
|
+
module Middleware
|
158
|
+
extend ActiveSupport::Autoload
|
159
|
+
|
160
|
+
autoload :DatabaseSelector, "active_record/middleware/database_selector"
|
161
|
+
end
|
162
|
+
|
156
163
|
module Tasks
|
157
164
|
extend ActiveSupport::Autoload
|
158
165
|
|
@@ -17,6 +17,23 @@ module ActiveRecord
|
|
17
17
|
# CollectionAssociation
|
18
18
|
# HasManyAssociation + ForeignAssociation
|
19
19
|
# HasManyThroughAssociation + ThroughAssociation
|
20
|
+
#
|
21
|
+
# Associations in Active Record are middlemen between the object that
|
22
|
+
# holds the association, known as the <tt>owner</tt>, and the associated
|
23
|
+
# result set, known as the <tt>target</tt>. Association metadata is available in
|
24
|
+
# <tt>reflection</tt>, which is an instance of <tt>ActiveRecord::Reflection::AssociationReflection</tt>.
|
25
|
+
#
|
26
|
+
# For example, given
|
27
|
+
#
|
28
|
+
# class Blog < ActiveRecord::Base
|
29
|
+
# has_many :posts
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# blog = Blog.first
|
33
|
+
#
|
34
|
+
# The association of <tt>blog.posts</tt> has the object +blog+ as its
|
35
|
+
# <tt>owner</tt>, the collection of its posts as <tt>target</tt>, and
|
36
|
+
# the <tt>reflection</tt> object represents a <tt>:has_many</tt> macro.
|
20
37
|
class Association #:nodoc:
|
21
38
|
attr_reader :owner, :target, :reflection
|
22
39
|
|
@@ -109,9 +109,8 @@ module ActiveRecord
|
|
109
109
|
end
|
110
110
|
end
|
111
111
|
|
112
|
-
# Add +records+ to this association.
|
113
|
-
#
|
114
|
-
# +push+ and +concat+ behave identically.
|
112
|
+
# Add +records+ to this association. Since +<<+ flattens its argument list
|
113
|
+
# and inserts each record, +push+ and +concat+ behave identically.
|
115
114
|
def concat(*records)
|
116
115
|
records = records.flatten
|
117
116
|
if owner.new_record?
|
@@ -233,7 +232,7 @@ module ActiveRecord
|
|
233
232
|
# loaded and you are going to fetch the records anyway it is better to
|
234
233
|
# check <tt>collection.length.zero?</tt>.
|
235
234
|
def empty?
|
236
|
-
if loaded? || @association_ids
|
235
|
+
if loaded? || @association_ids || reflection.has_cached_counter?
|
237
236
|
size.zero?
|
238
237
|
else
|
239
238
|
target.empty? && !scope.exists?
|
@@ -347,7 +346,6 @@ module ActiveRecord
|
|
347
346
|
add_to_target(record) do
|
348
347
|
result = insert_record(record, true, raise) {
|
349
348
|
@_was_loaded = loaded?
|
350
|
-
@association_ids = nil
|
351
349
|
}
|
352
350
|
end
|
353
351
|
raise ActiveRecord::Rollback unless result
|
@@ -384,6 +382,7 @@ module ActiveRecord
|
|
384
382
|
|
385
383
|
delete_records(existing_records, method) if existing_records.any?
|
386
384
|
@target -= records
|
385
|
+
@association_ids = nil
|
387
386
|
|
388
387
|
records.each { |record| callback(:after_remove, record) }
|
389
388
|
end
|
@@ -424,7 +423,6 @@ module ActiveRecord
|
|
424
423
|
unless owner.new_record?
|
425
424
|
result &&= insert_record(record, true, raise) {
|
426
425
|
@_was_loaded = loaded?
|
427
|
-
@association_ids = nil
|
428
426
|
}
|
429
427
|
end
|
430
428
|
end
|
@@ -447,6 +445,7 @@ module ActiveRecord
|
|
447
445
|
if index
|
448
446
|
target[index] = record
|
449
447
|
elsif @_was_loaded || !loaded?
|
448
|
+
@association_ids = nil
|
450
449
|
target << record
|
451
450
|
end
|
452
451
|
|
@@ -2,11 +2,8 @@
|
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
module Associations
|
5
|
-
#
|
6
|
-
#
|
7
|
-
# object, known as the <tt>@target</tt>. The kind of association any proxy is
|
8
|
-
# about is available in <tt>@reflection</tt>. That's an instance of the class
|
9
|
-
# ActiveRecord::Reflection::AssociationReflection.
|
5
|
+
# Collection proxies in Active Record are middlemen between an
|
6
|
+
# <tt>association</tt>, and its <tt>target</tt> result set.
|
10
7
|
#
|
11
8
|
# For example, given
|
12
9
|
#
|
@@ -16,14 +13,14 @@ module ActiveRecord
|
|
16
13
|
#
|
17
14
|
# blog = Blog.first
|
18
15
|
#
|
19
|
-
#
|
20
|
-
# <tt
|
21
|
-
#
|
16
|
+
# The collection proxy returned by <tt>blog.posts</tt> is built from a
|
17
|
+
# <tt>:has_many</tt> <tt>association</tt>, and delegates to a collection
|
18
|
+
# of posts as the <tt>target</tt>.
|
22
19
|
#
|
23
|
-
# This class delegates unknown methods to <tt
|
24
|
-
#
|
20
|
+
# This class delegates unknown methods to the <tt>association</tt>'s
|
21
|
+
# relation class via a delegate cache.
|
25
22
|
#
|
26
|
-
# The <tt
|
23
|
+
# The <tt>target</tt> result set is not loaded until needed. For example,
|
27
24
|
#
|
28
25
|
# blog.posts.count
|
29
26
|
#
|
@@ -366,34 +363,6 @@ module ActiveRecord
|
|
366
363
|
@association.create!(attributes, &block)
|
367
364
|
end
|
368
365
|
|
369
|
-
# Add one or more records to the collection by setting their foreign keys
|
370
|
-
# to the association's primary key. Since #<< flattens its argument list and
|
371
|
-
# inserts each record, +push+ and #concat behave identically. Returns +self+
|
372
|
-
# so method calls may be chained.
|
373
|
-
#
|
374
|
-
# class Person < ActiveRecord::Base
|
375
|
-
# has_many :pets
|
376
|
-
# end
|
377
|
-
#
|
378
|
-
# person.pets.size # => 0
|
379
|
-
# person.pets.concat(Pet.new(name: 'Fancy-Fancy'))
|
380
|
-
# person.pets.concat(Pet.new(name: 'Spook'), Pet.new(name: 'Choo-Choo'))
|
381
|
-
# person.pets.size # => 3
|
382
|
-
#
|
383
|
-
# person.id # => 1
|
384
|
-
# person.pets
|
385
|
-
# # => [
|
386
|
-
# # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
|
387
|
-
# # #<Pet id: 2, name: "Spook", person_id: 1>,
|
388
|
-
# # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
|
389
|
-
# # ]
|
390
|
-
#
|
391
|
-
# person.pets.concat([Pet.new(name: 'Brain'), Pet.new(name: 'Benny')])
|
392
|
-
# person.pets.size # => 5
|
393
|
-
def concat(*records)
|
394
|
-
@association.concat(*records)
|
395
|
-
end
|
396
|
-
|
397
366
|
# Replaces this collection with +other_array+. This will perform a diff
|
398
367
|
# and delete/add only records that have changed.
|
399
368
|
#
|
@@ -1033,8 +1002,9 @@ module ActiveRecord
|
|
1033
1002
|
end
|
1034
1003
|
|
1035
1004
|
# Adds one or more +records+ to the collection by setting their foreign keys
|
1036
|
-
# to the association's primary key.
|
1037
|
-
#
|
1005
|
+
# to the association's primary key. Since +<<+ flattens its argument list and
|
1006
|
+
# inserts each record, +push+ and +concat+ behave identically. Returns +self+
|
1007
|
+
# so several appends may be chained together.
|
1038
1008
|
#
|
1039
1009
|
# class Person < ActiveRecord::Base
|
1040
1010
|
# has_many :pets
|
@@ -1057,6 +1027,7 @@ module ActiveRecord
|
|
1057
1027
|
end
|
1058
1028
|
alias_method :push, :<<
|
1059
1029
|
alias_method :append, :<<
|
1030
|
+
alias_method :concat, :<<
|
1060
1031
|
|
1061
1032
|
def prepend(*args)
|
1062
1033
|
raise NoMethodError, "prepend on association is not defined. Please use <<, push or append"
|
@@ -36,14 +36,6 @@ module ActiveRecord
|
|
36
36
|
super
|
37
37
|
end
|
38
38
|
|
39
|
-
def empty?
|
40
|
-
if reflection.has_cached_counter?
|
41
|
-
size.zero?
|
42
|
-
else
|
43
|
-
super
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
39
|
private
|
48
40
|
|
49
41
|
# Returns the number of records in this collection.
|
@@ -69,7 +61,7 @@ module ActiveRecord
|
|
69
61
|
# If there's nothing in the database and @target has no new records
|
70
62
|
# we are certain the current target is an empty array. This is a
|
71
63
|
# documented side-effect of the method that may avoid an extra SELECT.
|
72
|
-
|
64
|
+
loaded! if count == 0
|
73
65
|
|
74
66
|
[association_scope.limit_value, count].compact.min
|
75
67
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "active_record/associations/join_dependency/join_part"
|
4
|
+
require "active_support/core_ext/array/extract"
|
4
5
|
|
5
6
|
module ActiveRecord
|
6
7
|
module Associations
|
@@ -30,17 +31,21 @@ module ActiveRecord
|
|
30
31
|
table = tables[-i]
|
31
32
|
klass = reflection.klass
|
32
33
|
|
33
|
-
|
34
|
+
join_scope = reflection.join_scope(table, foreign_table, foreign_klass)
|
34
35
|
|
35
|
-
joins << table.create_join(table, table.create_on(constraint), join_type)
|
36
|
-
|
37
|
-
join_scope = reflection.join_scope(table, foreign_klass)
|
38
36
|
arel = join_scope.arel(alias_tracker.aliases)
|
37
|
+
nodes = arel.constraints.first
|
38
|
+
|
39
|
+
others = nodes.children.extract! do |node|
|
40
|
+
Arel.fetch_attribute(node) { |attr| attr.relation.name != table.name }
|
41
|
+
end
|
42
|
+
|
43
|
+
joins << table.create_join(table, table.create_on(nodes), join_type)
|
39
44
|
|
40
|
-
|
45
|
+
unless others.empty?
|
41
46
|
joins.concat arel.join_sources
|
42
47
|
right = joins.last.right
|
43
|
-
right.expr
|
48
|
+
right.expr.children.concat(others)
|
44
49
|
end
|
45
50
|
|
46
51
|
# The current table in this iteration becomes the foreign table in the next
|
@@ -42,11 +42,10 @@ module ActiveRecord
|
|
42
42
|
|
43
43
|
def associate_records_to_owner(owner, records)
|
44
44
|
association = owner.association(reflection.name)
|
45
|
-
association.loaded!
|
46
45
|
if reflection.collection?
|
47
|
-
association.target
|
46
|
+
association.target = records
|
48
47
|
else
|
49
|
-
association.target = records.first
|
48
|
+
association.target = records.first
|
50
49
|
end
|
51
50
|
end
|
52
51
|
|
@@ -116,7 +115,7 @@ module ActiveRecord
|
|
116
115
|
def build_scope
|
117
116
|
scope = klass.scope_for_association
|
118
117
|
|
119
|
-
if reflection.type
|
118
|
+
if reflection.type && !reflection.through_reflection?
|
120
119
|
scope.where!(reflection.type => model.polymorphic_name)
|
121
120
|
end
|
122
121
|
|
@@ -7,10 +7,9 @@ module ActiveRecord
|
|
7
7
|
def run(preloader)
|
8
8
|
already_loaded = owners.first.association(through_reflection.name).loaded?
|
9
9
|
through_scope = through_scope()
|
10
|
-
reflection_scope = target_reflection_scope
|
11
10
|
through_preloaders = preloader.preload(owners, through_reflection.name, through_scope)
|
12
11
|
middle_records = through_preloaders.flat_map(&:preloaded_records)
|
13
|
-
preloaders = preloader.preload(middle_records, source_reflection.name,
|
12
|
+
preloaders = preloader.preload(middle_records, source_reflection.name, scope)
|
14
13
|
@preloaded_records = preloaders.flat_map(&:preloaded_records)
|
15
14
|
|
16
15
|
owners.each do |owner|
|
@@ -25,18 +24,18 @@ module ActiveRecord
|
|
25
24
|
owner.association(through_reflection.name).reset if through_scope
|
26
25
|
end
|
27
26
|
result = through_records.flat_map do |record|
|
28
|
-
|
29
|
-
target = association.target
|
30
|
-
association.reset if preload_scope
|
31
|
-
target
|
27
|
+
record.association(source_reflection.name).target
|
32
28
|
end
|
33
29
|
result.compact!
|
34
|
-
if
|
35
|
-
|
36
|
-
result.uniq! if reflection_scope.distinct_value
|
37
|
-
end
|
30
|
+
result.sort_by! { |rhs| preload_index[rhs] } if scope.order_values.any?
|
31
|
+
result.uniq! if scope.distinct_value
|
38
32
|
associate_records_to_owner(owner, result)
|
39
33
|
end
|
34
|
+
unless scope.empty_scope?
|
35
|
+
middle_records.each do |owner|
|
36
|
+
owner.association(source_reflection.name).reset
|
37
|
+
end
|
38
|
+
end
|
40
39
|
end
|
41
40
|
|
42
41
|
private
|
@@ -91,16 +90,6 @@ module ActiveRecord
|
|
91
90
|
|
92
91
|
scope unless scope.empty_scope?
|
93
92
|
end
|
94
|
-
|
95
|
-
def target_reflection_scope
|
96
|
-
if preload_scope
|
97
|
-
reflection_scope.merge(preload_scope)
|
98
|
-
elsif reflection.scope
|
99
|
-
reflection_scope
|
100
|
-
else
|
101
|
-
nil
|
102
|
-
end
|
103
|
-
end
|
104
93
|
end
|
105
94
|
end
|
106
95
|
end
|