activerecord 5.0.0 → 5.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +218 -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/builder/has_and_belongs_to_many.rb +4 -2
  7. data/lib/active_record/associations/builder/singular_association.rb +10 -1
  8. data/lib/active_record/associations/collection_association.rb +22 -17
  9. data/lib/active_record/associations/collection_proxy.rb +20 -7
  10. data/lib/active_record/associations/has_many_through_association.rb +4 -0
  11. data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
  12. data/lib/active_record/associations/join_dependency.rb +10 -4
  13. data/lib/active_record/associations/preloader/association.rb +18 -4
  14. data/lib/active_record/associations/preloader/collection_association.rb +0 -1
  15. data/lib/active_record/associations/preloader/singular_association.rb +0 -1
  16. data/lib/active_record/associations/singular_association.rb +8 -2
  17. data/lib/active_record/associations.rb +5 -0
  18. data/lib/active_record/attribute.rb +3 -3
  19. data/lib/active_record/attribute_methods/primary_key.rb +14 -1
  20. data/lib/active_record/attribute_methods/time_zone_conversion.rb +1 -1
  21. data/lib/active_record/attribute_methods.rb +3 -7
  22. data/lib/active_record/attribute_set/builder.rb +29 -7
  23. data/lib/active_record/attribute_set.rb +2 -0
  24. data/lib/active_record/attributes.rb +3 -3
  25. data/lib/active_record/autosave_association.rb +15 -11
  26. data/lib/active_record/base.rb +1 -1
  27. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +40 -32
  28. data/lib/active_record/connection_adapters/abstract/database_statements.rb +1 -1
  29. data/lib/active_record/connection_adapters/abstract/query_cache.rb +29 -0
  30. data/lib/active_record/connection_adapters/abstract/quoting.rb +4 -4
  31. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +8 -7
  32. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +38 -33
  33. data/lib/active_record/connection_adapters/abstract_adapter.rb +28 -5
  34. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +43 -45
  35. data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
  36. data/lib/active_record/connection_adapters/mysql/database_statements.rb +6 -23
  37. data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
  38. data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -5
  39. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +8 -0
  40. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +12 -1
  41. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
  42. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -0
  43. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +7 -1
  44. data/lib/active_record/connection_adapters/postgresql_adapter.rb +6 -2
  45. data/lib/active_record/core.rb +3 -1
  46. data/lib/active_record/enum.rb +6 -5
  47. data/lib/active_record/gem_version.rb +1 -1
  48. data/lib/active_record/integration.rb +13 -10
  49. data/lib/active_record/migration.rb +6 -5
  50. data/lib/active_record/model_schema.rb +134 -47
  51. data/lib/active_record/no_touching.rb +4 -0
  52. data/lib/active_record/persistence.rb +10 -4
  53. data/lib/active_record/query_cache.rb +13 -15
  54. data/lib/active_record/querying.rb +3 -3
  55. data/lib/active_record/railties/controller_runtime.rb +1 -1
  56. data/lib/active_record/reflection.rb +12 -0
  57. data/lib/active_record/relation/calculations.rb +11 -11
  58. data/lib/active_record/relation/delegation.rb +1 -1
  59. data/lib/active_record/relation/finder_methods.rb +11 -9
  60. data/lib/active_record/relation/query_methods.rb +3 -3
  61. data/lib/active_record/relation.rb +7 -4
  62. data/lib/active_record/result.rb +7 -1
  63. data/lib/active_record/sanitization.rb +11 -1
  64. data/lib/active_record/schema_dumper.rb +10 -17
  65. data/lib/active_record/scoping/named.rb +1 -1
  66. data/lib/active_record/statement_cache.rb +2 -2
  67. data/lib/active_record/table_metadata.rb +4 -3
  68. data/lib/active_record/touch_later.rb +6 -1
  69. data/lib/active_record/type/internal/abstract_json.rb +5 -1
  70. data/lib/active_record/validations/uniqueness.rb +3 -4
  71. data/lib/active_record.rb +1 -1
  72. metadata +8 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 175e4ed30958c211689abda4a5664d2314821c19
4
- data.tar.gz: b22c909734c877decd541b4585e6107f4a853824
3
+ metadata.gz: 234898d7d61339658ef46af85f6fdb265b658680
4
+ data.tar.gz: 642894eb2481573526cb1354bd138c000f422713
5
5
  SHA512:
6
- metadata.gz: eb75298c265d53bb950437f9eeabe32ce75a5226aa1eb180d014cb3420ee7895a97ac74f2a2d7643b54f6fce7106a2c33d169fe288c6e9950f3d726dd7488b17
7
- data.tar.gz: 7999af5a3505e7e95ea5b1226d0ff2bf5af784e59b3355376dbb0d4fe79a1a79346ebcfbb9d2a524797e376843a2213b2fc60a69d61aa519d60ba86f9cde37c9
6
+ metadata.gz: 803f30b6ebb0c25c3f1f478a9c412591d8b1c3daef6e888fbbe17257289392b9950f5ef19825d1ee133c826536a3d63fd23d04dd6f49091eec2af7017c029d86
7
+ data.tar.gz: 2caf2093ce411ac3cc8fa467b2d0fa2fca8ca46fa63e0aab0f903c10a9a0099e55cfe98abbdd07a08d4270a7ee9618a5cb2f1450abcbe760a18999ff874e2152
data/CHANGELOG.md CHANGED
@@ -1,6 +1,222 @@
1
+ ## Rails 5.0.1 (December 21, 2016) ##
2
+
3
+ * No changes.
4
+
5
+
6
+ ## Rails 5.0.1.rc2 (December 10, 2016) ##
7
+
8
+ * Correct resolution of associated class in `has_many :through`
9
+ associations' `*_ids` setters.
10
+
11
+ Fixes #27297.
12
+
13
+ *Matthew Draper*
14
+
15
+ * Support index length and order options using both string and symbol
16
+ column names.
17
+
18
+ Fixes #27243.
19
+
20
+ *Ryuta Kamizono*
21
+
22
+
23
+ ## Rails 5.0.1.rc1 (December 01, 2016) ##
24
+
25
+ * Fix that unsigned with zerofill is treated as signed.
26
+
27
+ Fixes #27125.
28
+
29
+ *Ryuta Kamizono*
30
+
31
+ * Fix the uniqueness validation scope with a polymorphic association.
32
+
33
+ *Sergey Alekseev*
34
+
35
+ * Raise ActiveRecord::RecordNotFound from collection `*_ids` setters
36
+ for unknown IDs with a better error message.
37
+
38
+ Changes the collection `*_ids` setters to cast provided IDs the data
39
+ type of the primary key set in the association, not the model
40
+ primary key.
41
+
42
+ *Dominic Cleal*
43
+
44
+ * Introduce `Model#reload_<association>` to bring back the behavior
45
+ of `Article.category(true)` where `category` is a singular
46
+ association.
47
+
48
+ The force reloading of the association reader was deprecated
49
+ in #20888. Unfortunately the suggested alternative of
50
+ `article.reload.category` does not expose the same behavior.
51
+
52
+ This patch adds a reader method with the prefix `reload_` for
53
+ singular associations. This method has the same semantics as
54
+ passing true to the association reader used to have.
55
+
56
+ *Yves Senn*
57
+
58
+ * Make sure eager loading `ActiveRecord::Associations` also loads
59
+ constants defined in `ActiveRecord::Associations::Preloader`.
60
+
61
+ *Yves Senn*
62
+
63
+ * Allow `ActionController::Parameters`-like objects to be passed as
64
+ values for Postgres HStore columns.
65
+
66
+ Fixes #26904.
67
+
68
+ *Jon Moss*
69
+
70
+ * Configure query caching (per thread) on the connection pool.
71
+
72
+ Moving the configuration to the pool means we don't allocate a connection
73
+ until it's actually needed.
74
+
75
+ Applications that manually interact with the connection pool and/or query
76
+ cache may notice that the connection's cache is now cleared and disabled
77
+ when it gets returned to the pool, even if the request is not yet completed.
78
+
79
+ *Samuel Cochran*, *Matthew Draper*
80
+
81
+ * Fixed support for case insensitive comparisons of `text` columns in
82
+ PostgreSQL.
83
+
84
+ *Edho Arief*
85
+
86
+ * Return `true` from `update_attribute` when the value of the attribute
87
+ to be updated is unchanged.
88
+
89
+ Fixes #26593.
90
+
91
+ *Prathamesh Sonpatki*
92
+
93
+ * Serialize JSON attribute value `nil` as SQL `NULL`, not JSON `null`
94
+
95
+ *Trung Duc Tran*
96
+
97
+ * Always store errors details information with symbols.
98
+
99
+ When the association is autosaved we were storing the details with
100
+ string keys. This was creating inconsistency with other details that are
101
+ added using the `Errors#add` method. It was also inconsistent with the
102
+ `Errors#messages` storage.
103
+
104
+ To fix this inconsistency we are always storing with symbols. This will
105
+ cause a small breaking change because in those cases the details could
106
+ be accessed as strings keys but now it can not.
107
+
108
+ Fix #26499.
109
+
110
+ *Rafael Mendonça França*, *Marcus Vieira*
111
+
112
+ * Using a mysql2 connection after it fails to reconnect will now have an error message
113
+ saying the connection is closed rather than an undefined method error message.
114
+
115
+ *Dylan Thacker-Smith*
116
+
117
+ * Remove unnecessarily association load when a `belongs_to` association has already been
118
+ loaded then the foreign key is changed directly and the record saved.
119
+
120
+ *James Coleman*
121
+
122
+ * PostgreSQL array columns will now respect the encoding of strings contained
123
+ in the array.
124
+
125
+ Fixes #26326.
126
+
127
+ *Sean Griffin*
128
+
129
+ * Inverse association instances will now be set before `after_find` or
130
+ `after_initialize` callbacks are run.
131
+
132
+ Fixes #26320.
133
+
134
+ *Sean Griffin*
135
+
136
+ * Avoid loading records from database when they are already loaded using
137
+ the `pluck` method on a collection.
138
+
139
+ Fixes #25921.
140
+
141
+ *Ryuta Kamizono*
142
+
143
+ * Sqlite3 migrations to add a column to an existing table can now be
144
+ successfully rolled back when the column was given and invalid column
145
+ type.
146
+
147
+ Fixes #26087
148
+
149
+ *Travis O'Neill*
150
+
151
+ * Hashes can once again be passed to setters of `composed_of`, if all of the
152
+ mapping methods are methods implemented on `Hash`.
153
+
154
+ Fixes #25978.
155
+
156
+ *Sean Griffin*
157
+
158
+ * Doing count on relations that contain LEFT OUTER JOIN Arel node no longer
159
+ force a DISTINCT. This solves issues when using count after a left_joins.
160
+
161
+ *Maxime Handfield Lapointe*
162
+
163
+ * RecordNotFound raised by association.find exposes `id`, `primary_key` and
164
+ `model` methods to be consistent with RecordNotFound raised by Record.find.
165
+
166
+ *Michel Pigassou*
167
+
168
+ * Fix the SELECT statement in `#table_comment` for MySQL.
169
+
170
+ *Takeshi Akima*
171
+
172
+ * Virtual attributes will no longer raise when read on models loaded from the
173
+ database
174
+
175
+ *Sean Griffin*
176
+
177
+ * Fixes multi-parameter attributes conversion with invalid params.
178
+
179
+ *Hiroyuki Ishii*
180
+
181
+ * Add newline between each migration in `structure.sql`.
182
+
183
+ Keeps schema migration inserts as a single commit, but allows for easier
184
+ git diff-ing. Fixes #25504.
185
+
186
+ *Grey Baker*, *Norberto Lopes*
187
+
188
+ * Using `group` with an attribute that has a custom type will properly cast
189
+ the hash keys after calling a calculation method like `count`.
190
+
191
+ Fixes #25595.
192
+
193
+ *Sean Griffin*
194
+
195
+ * Ensure concurrent invocations of the connection reaper cannot allocate the
196
+ same connection to two threads.
197
+
198
+ Fixes #25585.
199
+
200
+ *Matthew Draper*
201
+
202
+ * Fixed dumping of foreign key's referential actions when MySQL connection
203
+ uses `sql_mode = ANSI_QUOTES`.
204
+
205
+ Fixes #25300.
206
+
207
+ *Ryuta Kamizono*
208
+
209
+
1
210
  ## Rails 5.0.0 (June 30, 2016) ##
2
211
 
212
+ * Inspecting an object with an associated array of over 10 elements no longer
213
+ truncates the array, preventing `inspect` from looping infinitely in some
214
+ cases.
215
+
216
+ *Kevin McPhillips*
217
+
3
218
  * Ensure hashes can be assigned to attributes created using `composed_of`.
219
+
4
220
  Fixes #25210.
5
221
 
6
222
  *Sean Griffin*
@@ -279,7 +495,7 @@
279
495
 
280
496
  *Takashi Kokubun*
281
497
 
282
- * Add ActiveRecord `#second_to_last` and `#third_to_last` methods.
498
+ * Add `#second_to_last` and `#third_to_last` finder methods.
283
499
 
284
500
  *Brian Christian*
285
501
 
@@ -1020,7 +1236,7 @@
1020
1236
 
1021
1237
  *Mehmet Emin İNAÇ*
1022
1238
 
1023
- * Add `cache_key` to ActiveRecord::Relation.
1239
+ * Add `cache_key` to `ActiveRecord::Relation`.
1024
1240
 
1025
1241
  Example:
1026
1242
 
data/README.rdoc CHANGED
@@ -192,7 +192,7 @@ The latest version of Active Record can be installed with RubyGems:
192
192
 
193
193
  Source code can be downloaded as part of the Rails project on GitHub:
194
194
 
195
- * https://github.com/rails/rails/tree/master/activerecord
195
+ * https://github.com/rails/rails/tree/5-0-stable/activerecord
196
196
 
197
197
 
198
198
  == License
@@ -261,8 +261,10 @@ module ActiveRecord
261
261
  part = converter.respond_to?(:call) ? converter.call(part) : klass.send(converter, part)
262
262
  end
263
263
 
264
- if part.is_a?(Hash)
265
- raise ArgumentError unless part.size == part.keys.max
264
+ hash_from_multiparameter_assignment = part.is_a?(Hash) &&
265
+ part.each_key.all? { |k| k.is_a?(Integer) }
266
+ if hash_from_multiparameter_assignment
267
+ raise ArgumentError unless part.size == part.each_key.max
266
268
  part = klass.new(*part.sort.map(&:last))
267
269
  end
268
270
 
@@ -29,7 +29,10 @@ module ActiveRecord
29
29
  private
30
30
 
31
31
  def exec_queries
32
- super.each { |r| @association.set_inverse_instance r }
32
+ super do |r|
33
+ @association.set_inverse_instance r
34
+ yield r if block_given?
35
+ end
33
36
  end
34
37
  end
35
38
  end
@@ -76,8 +76,10 @@ module ActiveRecord::Associations::Builder # :nodoc:
76
76
  left_model.retrieve_connection
77
77
  end
78
78
 
79
- def self.primary_key
80
- false
79
+ private
80
+
81
+ def self.suppress_composite_primary_key(pk)
82
+ pk unless pk.is_a?(Array)
81
83
  end
82
84
  }
83
85
 
@@ -8,7 +8,16 @@ module ActiveRecord::Associations::Builder # :nodoc:
8
8
 
9
9
  def self.define_accessors(model, reflection)
10
10
  super
11
- define_constructors(model.generated_association_methods, reflection.name) if reflection.constructable?
11
+ mixin = model.generated_association_methods
12
+ name = reflection.name
13
+
14
+ define_constructors(mixin, name) if reflection.constructable?
15
+
16
+ mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
17
+ def reload_#{name}
18
+ association(:#{name}).force_reload_reader
19
+ end
20
+ CODE
12
21
  end
13
22
 
14
23
  # Defines the (build|create)_association methods for belongs_to or has_one association
@@ -69,13 +69,17 @@ module ActiveRecord
69
69
 
70
70
  # Implements the ids writer method, e.g. foo.item_ids= for Foo.has_many :items
71
71
  def ids_writer(ids)
72
- pk_type = reflection.primary_key_type
72
+ pk_type = reflection.association_primary_key_type
73
73
  ids = Array(ids).reject(&:blank?)
74
74
  ids.map! { |i| pk_type.cast(i) }
75
75
  records = klass.where(reflection.association_primary_key => ids).index_by do |r|
76
76
  r.send(reflection.association_primary_key)
77
- end.values_at(*ids)
78
- replace(records)
77
+ end.values_at(*ids).compact
78
+ if records.size != ids.size
79
+ klass.all.raise_record_not_found_exception!(ids, records.size, ids.size, reflection.association_primary_key)
80
+ else
81
+ replace(records)
82
+ end
79
83
  end
80
84
 
81
85
  def reset
@@ -312,9 +316,9 @@ module ActiveRecord
312
316
  else
313
317
  target.size
314
318
  end
315
- elsif !loaded? && !association_scope.group_values.empty?
319
+ elsif !association_scope.group_values.empty?
316
320
  load_target.size
317
- elsif !loaded? && !association_scope.distinct_value && target.is_a?(Array)
321
+ elsif !association_scope.distinct_value && target.is_a?(Array)
318
322
  unsaved_records = target.select(&:new_record?)
319
323
  unsaved_records.size + count_records
320
324
  else
@@ -426,15 +430,12 @@ module ActiveRecord
426
430
  def replace_on_target(record, index, skip_callbacks)
427
431
  callback(:before_add, record) unless skip_callbacks
428
432
 
429
- was_loaded = loaded?
430
433
  yield(record) if block_given?
431
434
 
432
- unless !was_loaded && loaded?
433
- if index
434
- @target[index] = record
435
- else
436
- @target << record
437
- end
435
+ if index
436
+ @target[index] = record
437
+ else
438
+ append_record(record)
438
439
  end
439
440
 
440
441
  callback(:after_add, record) unless skip_callbacks
@@ -454,7 +455,7 @@ module ActiveRecord
454
455
  end
455
456
 
456
457
  private
457
- def get_records
458
+ def get_records(&block)
458
459
  return scope.to_a if skip_statement_cache?
459
460
 
460
461
  conn = klass.connection
@@ -466,13 +467,13 @@ module ActiveRecord
466
467
  end
467
468
 
468
469
  binds = AssociationScope.get_bind_values(owner, reflection.chain)
469
- sc.execute binds, klass, klass.connection
470
+ sc.execute(binds, klass, klass.connection, &block)
470
471
  end
471
472
 
472
473
  def find_target
473
- records = get_records
474
- records.each { |record| set_inverse_instance(record) }
475
- records
474
+ get_records do |record|
475
+ set_inverse_instance(record)
476
+ end
476
477
  end
477
478
 
478
479
  # We have some records loaded from the database (persisted) and some that are
@@ -657,6 +658,10 @@ module ActiveRecord
657
658
  set_inverse_instance record if record.is_a? ActiveRecord::Base
658
659
  end
659
660
  end
661
+
662
+ def append_record(record)
663
+ @target << record unless @target.include?(record)
664
+ end
660
665
  end
661
666
  end
662
667
  end
@@ -28,8 +28,7 @@ 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
31
+ delegate :exists?, :update_all, :arel, to: :scope
33
32
 
34
33
  def initialize(klass, association) #:nodoc:
35
34
  @association = association
@@ -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,10 +898,6 @@ 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
@@ -1068,6 +1071,16 @@ module ActiveRecord
1068
1071
  proxy_association.reset_scope
1069
1072
  self
1070
1073
  end
1074
+
1075
+ private
1076
+
1077
+ def null_scope?
1078
+ @association.null_scope?
1079
+ end
1080
+
1081
+ def exec_queries
1082
+ load_target
1083
+ end
1071
1084
  end
1072
1085
  end
1073
1086
  end
@@ -203,6 +203,10 @@ module ActiveRecord
203
203
  def invertible_for?(record)
204
204
  false
205
205
  end
206
+
207
+ def append_record(record)
208
+ @target << record
209
+ end
206
210
  end
207
211
  end
208
212
  end
@@ -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,7 +127,7 @@ 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
@@ -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
 
@@ -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
@@ -224,6 +224,11 @@ module ActiveRecord
224
224
  autoload :AliasTracker
225
225
  end
226
226
 
227
+ def self.eager_load!
228
+ super
229
+ Preloader.eager_load!
230
+ end
231
+
227
232
  # Returns the association instance for the given name, instantiating it if it doesn't already exist
228
233
  def association(name) #:nodoc:
229
234
  association = association_instance_get(name)
@@ -65,7 +65,7 @@ module ActiveRecord
65
65
 
66
66
  def with_value_from_user(value)
67
67
  type.assert_valid_value(value)
68
- self.class.from_user(name, value, type, self)
68
+ self.class.from_user(name, value, type, original_attribute || self)
69
69
  end
70
70
 
71
71
  def with_value_from_database(value)
@@ -132,7 +132,7 @@ module ActiveRecord
132
132
  end
133
133
 
134
134
  def _original_value_for_database
135
- value_for_database
135
+ type.serialize(original_value)
136
136
  end
137
137
 
138
138
  class FromDatabase < Attribute # :nodoc:
@@ -160,7 +160,7 @@ module ActiveRecord
160
160
  value
161
161
  end
162
162
 
163
- def changed_in_place_from?(old_value)
163
+ def changed_in_place?
164
164
  false
165
165
  end
166
166
  end