activerecord 5.0.0.beta1.1 → 5.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.

Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +123 -15
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +1 -1
  5. data/lib/active_record.rb +2 -1
  6. data/lib/active_record/aggregations.rb +1 -1
  7. data/lib/active_record/associations.rb +3 -0
  8. data/lib/active_record/associations/builder/belongs_to.rb +1 -1
  9. data/lib/active_record/associations/builder/has_one.rb +1 -1
  10. data/lib/active_record/associations/builder/singular_association.rb +1 -1
  11. data/lib/active_record/associations/has_many_through_association.rb +5 -0
  12. data/lib/active_record/associations/join_dependency/join_association.rb +1 -2
  13. data/lib/active_record/associations/preloader/through_association.rb +7 -2
  14. data/lib/active_record/attribute_methods/time_zone_conversion.rb +11 -7
  15. data/lib/active_record/autosave_association.rb +18 -3
  16. data/lib/active_record/base.rb +0 -3
  17. data/lib/active_record/collection_cache_key.rb +12 -3
  18. data/lib/active_record/connection_adapters/abstract/database_statements.rb +21 -34
  19. data/lib/active_record/connection_adapters/abstract/quoting.rb +8 -4
  20. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +1 -1
  21. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +7 -1
  22. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +36 -20
  23. data/lib/active_record/connection_adapters/abstract/transaction.rb +8 -2
  24. data/lib/active_record/connection_adapters/abstract_adapter.rb +8 -15
  25. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +57 -198
  26. data/lib/active_record/connection_adapters/column.rb +1 -1
  27. data/lib/active_record/connection_adapters/mysql/column.rb +50 -0
  28. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +70 -0
  29. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +24 -0
  30. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +32 -0
  31. data/lib/active_record/connection_adapters/mysql2_adapter.rb +15 -34
  32. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +7 -69
  33. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +42 -0
  34. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +4 -0
  35. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +0 -2
  36. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +8 -1
  37. data/lib/active_record/connection_adapters/postgresql/quoting.rb +5 -4
  38. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +3 -7
  39. data/lib/active_record/connection_adapters/postgresql_adapter.rb +15 -23
  40. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +19 -0
  41. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +2 -31
  42. data/lib/active_record/connection_handling.rb +1 -1
  43. data/lib/active_record/core.rb +1 -1
  44. data/lib/active_record/counter_cache.rb +4 -4
  45. data/lib/active_record/enum.rb +8 -5
  46. data/lib/active_record/errors.rb +6 -1
  47. data/lib/active_record/gem_version.rb +1 -1
  48. data/lib/active_record/inheritance.rb +6 -1
  49. data/lib/active_record/internal_metadata.rb +56 -0
  50. data/lib/active_record/migration.rb +85 -20
  51. data/lib/active_record/migration/compatibility.rb +28 -2
  52. data/lib/active_record/model_schema.rb +25 -1
  53. data/lib/active_record/persistence.rb +11 -10
  54. data/lib/active_record/railtie.rb +6 -3
  55. data/lib/active_record/railties/databases.rake +20 -6
  56. data/lib/active_record/reflection.rb +39 -31
  57. data/lib/active_record/relation.rb +4 -4
  58. data/lib/active_record/relation/batches.rb +26 -41
  59. data/lib/active_record/relation/batches/batch_enumerator.rb +6 -6
  60. data/lib/active_record/relation/finder_methods.rb +35 -13
  61. data/lib/active_record/relation/from_clause.rb +1 -1
  62. data/lib/active_record/relation/merger.rb +3 -0
  63. data/lib/active_record/relation/predicate_builder.rb +19 -1
  64. data/lib/active_record/relation/predicate_builder/range_handler.rb +17 -1
  65. data/lib/active_record/relation/query_methods.rb +37 -19
  66. data/lib/active_record/relation/record_fetch_warning.rb +4 -6
  67. data/lib/active_record/relation/where_clause.rb +1 -1
  68. data/lib/active_record/relation/where_clause_factory.rb +1 -0
  69. data/lib/active_record/sanitization.rb +1 -1
  70. data/lib/active_record/schema.rb +3 -0
  71. data/lib/active_record/schema_dumper.rb +1 -1
  72. data/lib/active_record/schema_migration.rb +5 -14
  73. data/lib/active_record/scoping.rb +17 -11
  74. data/lib/active_record/scoping/default.rb +2 -2
  75. data/lib/active_record/tasks/database_tasks.rb +18 -0
  76. data/lib/active_record/timestamp.rb +5 -1
  77. data/lib/active_record/transactions.rb +3 -3
  78. data/lib/active_record/validations/uniqueness.rb +6 -3
  79. data/lib/rails/generators/active_record/migration/templates/migration.rb +4 -0
  80. data/lib/rails/generators/active_record/model/model_generator.rb +7 -1
  81. metadata +14 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ccbf826c049cab6dd670fb772aac6970dfa7b61d
4
- data.tar.gz: a80f795385b7acaaf8350dd3e2268da4a6c32d1f
3
+ metadata.gz: 1253c6d369c65fef25582c1db08ce74b101c9ca2
4
+ data.tar.gz: 15c25783b7d09e51ce7a1cffd4195b146d3c4135
5
5
  SHA512:
6
- metadata.gz: 4a01fab31f456f7d17652a97e6b2b101dfe450a0cedf76e6f4086f8faef3ada11267cffdc68c71c83d9edaffae792010b2a7b4a831e8508c76f46e6751fbb875
7
- data.tar.gz: 4099fc5636e010f802b4294987bc73b66f6975485e435f30566a810541b9778ef677914d7969b9c7dbefd861262d008f6ed6390d98c5c7b08480788f52ea17b0
6
+ metadata.gz: 9ea8bb7f465a0a0f88233fb05a70d5a7ab3ae100e928e831ea7813385537718d9907981fb7dfa51beb2eaa1b4a1726d9927c72b47562504c0cb083e4f7942ef2
7
+ data.tar.gz: 86360455da6ca811777f4288ac4d18051ad86c308ae7a2d53d1f527b0db19a0bf5f6e5d5c589f8b825e94886e03e51b0a854fc2137ab02929cd2309e685b67d2
@@ -1,7 +1,104 @@
1
- ## Rails 5.0.0.beta1 (December 18, 2015) ##
1
+ ## Rails 5.0.0.beta2 (February 01, 2016) ##
2
+
3
+ * `ActiveRecord::Relation#reverse_order` throws `ActiveRecord::IrreversibleOrderError`
4
+ when the order can not be reversed using current trivial algorithm.
5
+ Also raises the same error when `#reverse_order` is called on
6
+ relation without any order and table has no primary key:
7
+
8
+ Topic.order("concat(author_name, title)").reverse_order
9
+ # Before: SELECT `topics`.* FROM `topics` ORDER BY concat(author_name DESC, title) DESC
10
+ # After: raises ActiveRecord::IrreversibleOrderError
11
+ Edge.all.reverse_order
12
+ # Before: SELECT `edges`.* FROM `edges` ORDER BY `edges`.`` DESC
13
+ # After: raises ActiveRecord::IrreversibleOrderError
14
+
15
+ *Bogdan Gusiev*
16
+
17
+ * Improve schema_migrations insertion performance by inserting all versions
18
+ in one INSERT SQL.
19
+
20
+ *Akira Matsuda*, *Naoto Koshikawa*
21
+
22
+ * Using `references` or `belongs_to` in migrations will always add index
23
+ for the referenced column by default, without adding `index: true` option
24
+ to generated migration file. Users can opt out of this by passing
25
+ `index: false`.
26
+
27
+ Fixes #18146.
28
+
29
+ *Matthew Draper*, *Prathamesh Sonpatki*
30
+
31
+ * Run `type` attributes through attributes API type-casting before
32
+ instantiating the corresponding subclass. This makes it possible to define
33
+ custom STI mappings.
34
+
35
+ Fixes #21986.
36
+
37
+ *Yves Senn*
38
+
39
+ * Don't try to quote functions or expressions passed to `:default` option if
40
+ they are passed as procs.
41
+
42
+ This will generate proper query with the passed function or expression for
43
+ the default option, instead of trying to quote it in incorrect fashion.
44
+
45
+ Example:
46
+
47
+ create_table :posts do |t|
48
+ t.datetime :published_at, default: -> { 'NOW()' }
49
+ end
50
+
51
+ *Ryuta Kamizono*
52
+
53
+ * Fix regression when loading fixture files with symbol keys.
54
+
55
+ Fixes #22584.
56
+
57
+ *Yves Senn*
58
+
59
+ * Use `version` column as primary key for schema_migrations table because
60
+ `schema_migrations` versions are guaranteed to be unique.
61
+
62
+ This makes it possible to use `update_attributes` on models that do
63
+ not have a primary key.
2
64
 
3
- * No changes.
65
+ *Richard Schneeman*
4
66
 
67
+ * Add short-hand methods for text and blob types in MySQL.
68
+
69
+ In Pg and Sqlite3, `:text` and `:binary` have variable unlimited length.
70
+ But in MySQL, these have limited length for each types (ref #21591, #21619).
71
+ This change adds short-hand methods for each text and blob types.
72
+
73
+ Example:
74
+
75
+ create_table :foos do |t|
76
+ t.tinyblob :tiny_blob
77
+ t.mediumblob :medium_blob
78
+ t.longblob :long_blob
79
+ t.tinytext :tiny_text
80
+ t.mediumtext :medium_text
81
+ t.longtext :long_text
82
+ end
83
+
84
+ *Ryuta Kamizono*
85
+
86
+ * Take into account UTC offset when assigning string representation of
87
+ timestamp with offset specified to attribute of time type.
88
+
89
+ *Andrey Novikov*
90
+
91
+ * When calling `first` with a `limit` argument, return directly from the
92
+ `loaded?` records if available.
93
+
94
+ *Ben Woosley*
95
+
96
+ * Deprecate sending the `offset` argument to `find_nth`. Please use the
97
+ `offset` method on relation instead.
98
+
99
+ *Ben Woosley*
100
+
101
+ ## Rails 5.0.0.beta1 (December 18, 2015) ##
5
102
 
6
103
  * Order the result of `find(ids)` to match the passed array, if the relation
7
104
  has no explicit order defined.
@@ -46,6 +143,14 @@
46
143
  defaults without breaking existing migrations, or forcing them to be
47
144
  rewritten through a deprecation cycle.
48
145
 
146
+ New migrations specify the Rails version they were written for:
147
+
148
+ class AddStatusToOrders < ActiveRecord::Migration[5.0]
149
+ def change
150
+ # ...
151
+ end
152
+ end
153
+
49
154
  *Matthew Draper*, *Ravil Bayramgalin*
50
155
 
51
156
  * Use bind params for `limit` and `offset`. This will generate significantly
@@ -53,7 +158,7 @@
53
158
  change, passing a string containing a comma to `limit` has been deprecated,
54
159
  and passing an Arel node to `limit` is no longer supported.
55
160
 
56
- Fixes #22250
161
+ Fixes #22250.
57
162
 
58
163
  *Sean Griffin*
59
164
 
@@ -315,7 +420,7 @@
315
420
 
316
421
  * Don't cache arguments in `#find_by` if they are an `ActiveRecord::Relation`.
317
422
 
318
- Fixes #20817
423
+ Fixes #20817.
319
424
 
320
425
  *Hiroaki Izu*
321
426
 
@@ -348,7 +453,7 @@
348
453
 
349
454
  *Sean Griffin*
350
455
 
351
- * Give `AcriveRecord::Relation#update` its own deprecation warning when
456
+ * Give `ActiveRecord::Relation#update` its own deprecation warning when
352
457
  passed an `ActiveRecord::Base` instance.
353
458
 
354
459
  Fixes #21945.
@@ -444,9 +549,9 @@
444
549
 
445
550
  * Ensure `select` quotes aliased attributes, even when using `from`.
446
551
 
447
- Fixes #21488
552
+ Fixes #21488.
448
553
 
449
- *Sean Griffin & @johanlunds*
554
+ *Sean Griffin*, *@johanlunds*
450
555
 
451
556
  * MySQL: support `unsigned` numeric data types.
452
557
 
@@ -571,7 +676,7 @@
571
676
  * Add `ActiveRecord::Relation#in_batches` to work with records and relations
572
677
  in batches.
573
678
 
574
- Available options are `of` (batch size), `load`, `begin_at`, and `end_at`.
679
+ Available options are `of` (batch size), `load`, `start`, and `finish`.
575
680
 
576
681
  Examples:
577
682
 
@@ -772,7 +877,7 @@
772
877
 
773
878
  * Include the `Enumerable` module in `ActiveRecord::Relation`
774
879
 
775
- *Sean Griffin & bogdan*
880
+ *Sean Griffin*, *bogdan*
776
881
 
777
882
  * Use `Enumerable#sum` in `ActiveRecord::Relation` if a block is given.
778
883
 
@@ -808,7 +913,7 @@
808
913
 
809
914
  Fixes #20515.
810
915
 
811
- *Sean Griffin & jmondo*
916
+ *Sean Griffin*, *jmondo*
812
917
 
813
918
  * Deprecate the PostgreSQL `:point` type in favor of a new one which will return
814
919
  `Point` objects instead of an `Array`
@@ -1198,13 +1303,16 @@
1198
1303
  *Sean Griffin*
1199
1304
 
1200
1305
  * `scoping` no longer pollutes the current scope of sibling classes when using
1201
- STI. e.x.
1306
+ STI.
1307
+
1308
+ Fixes #18806.
1309
+
1310
+ Example:
1202
1311
 
1203
1312
  StiOne.none.scoping do
1204
1313
  StiTwo.all
1205
1314
  end
1206
1315
 
1207
- Fixes #18806.
1208
1316
 
1209
1317
  *Sean Griffin*
1210
1318
 
@@ -1216,7 +1324,7 @@
1216
1324
 
1217
1325
  *Yves Senn*
1218
1326
 
1219
- * `find_in_batches` now accepts an `:end_at` parameter that complements the `:start`
1327
+ * `find_in_batches` now accepts an `:finish` parameter that complements the `:start`
1220
1328
  parameter to specify where to stop batch processing.
1221
1329
 
1222
1330
  *Vipul A M*
@@ -1245,7 +1353,7 @@
1245
1353
 
1246
1354
  * Use `SCHEMA` instead of `DB_STRUCTURE` for specifying a structure file.
1247
1355
 
1248
- This makes the db:structure tasks consistent with test:load_structure.
1356
+ This makes the `db:structure` tasks consistent with `test:load_structure`.
1249
1357
 
1250
1358
  *Dieter Komendera*
1251
1359
 
@@ -1281,7 +1389,7 @@
1281
1389
 
1282
1390
  Fixes #17621.
1283
1391
 
1284
- *Eileen M. Uchitelle, Aaron Patterson*
1392
+ *Eileen M. Uchitelle*, *Aaron Patterson*
1285
1393
 
1286
1394
  * Fix n+1 query problem when eager loading nil associations (fixes #18312)
1287
1395
 
@@ -1,4 +1,4 @@
1
- Copyright (c) 2004-2015 David Heinemeier Hansson
1
+ Copyright (c) 2004-2016 David Heinemeier Hansson
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
@@ -17,4 +17,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
17
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
18
  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
19
  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -125,7 +125,7 @@ This would also define the following accessors: <tt>Product#name</tt> and
125
125
  )
126
126
 
127
127
  {Learn more}[link:classes/ActiveRecord/Base.html] and read about the built-in support for
128
- MySQL[link:classes/ActiveRecord/ConnectionAdapters/MysqlAdapter.html],
128
+ MySQL[link:classes/ActiveRecord/ConnectionAdapters/Mysql2Adapter.html],
129
129
  PostgreSQL[link:classes/ActiveRecord/ConnectionAdapters/PostgreSQLAdapter.html], and
130
130
  SQLite3[link:classes/ActiveRecord/ConnectionAdapters/SQLite3Adapter.html].
131
131
 
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2004-2015 David Heinemeier Hansson
2
+ # Copyright (c) 2004-2016 David Heinemeier Hansson
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining
5
5
  # a copy of this software and associated documentation files (the
@@ -40,6 +40,7 @@ module ActiveRecord
40
40
  autoload :CounterCache
41
41
  autoload :DynamicMatchers
42
42
  autoload :Enum
43
+ autoload :InternalMetadata
43
44
  autoload :Explain
44
45
  autoload :Inheritance
45
46
  autoload :Integration
@@ -33,7 +33,7 @@ module ActiveRecord
33
33
  # the database).
34
34
  #
35
35
  # class Customer < ActiveRecord::Base
36
- # composed_of :balance, class_name: "Money", mapping: %w(balance amount)
36
+ # composed_of :balance, class_name: "Money", mapping: %w(amount currency)
37
37
  # composed_of :address, mapping: [ %w(address_street street), %w(address_city city) ]
38
38
  # end
39
39
  #
@@ -1164,6 +1164,7 @@ module ActiveRecord
1164
1164
  # Adds one or more objects to the collection by setting their foreign keys to the collection's primary key.
1165
1165
  # Note that this operation instantly fires update SQL without waiting for the save or update call on the
1166
1166
  # parent object, unless the parent object is a new record.
1167
+ # This will also run validations and callbacks of associated object(s).
1167
1168
  # [collection.delete(object, ...)]
1168
1169
  # Removes one or more objects from the collection by setting their foreign keys to +NULL+.
1169
1170
  # Objects will be in addition destroyed if they're associated with <tt>dependent: :destroy</tt>,
@@ -1592,6 +1593,8 @@ module ActiveRecord
1592
1593
  # If true, the associated object will be touched (the updated_at/on attributes set to current time)
1593
1594
  # when this record is either saved or destroyed. If you specify a symbol, that attribute
1594
1595
  # will be updated with the current time in addition to the updated_at/on attribute.
1596
+ # Please note that with touching no validation is performed and only the +after_touch+,
1597
+ # +after_commit+ and +after_rollback+ callbacks are executed.
1595
1598
  # [:inverse_of]
1596
1599
  # Specifies the name of the #has_one or #has_many association on the associated
1597
1600
  # object that is the inverse of this #belongs_to association. Does not work in
@@ -5,7 +5,7 @@ module ActiveRecord::Associations::Builder # :nodoc:
5
5
  end
6
6
 
7
7
  def self.valid_options(options)
8
- super + [:foreign_type, :polymorphic, :touch, :counter_cache, :optional]
8
+ super + [:polymorphic, :touch, :counter_cache, :optional]
9
9
  end
10
10
 
11
11
  def self.valid_dependent_options
@@ -5,7 +5,7 @@ module ActiveRecord::Associations::Builder # :nodoc:
5
5
  end
6
6
 
7
7
  def self.valid_options(options)
8
- valid = super + [:as, :foreign_type]
8
+ valid = super + [:as]
9
9
  valid += [:through, :source, :source_type] if options[:through]
10
10
  valid
11
11
  end
@@ -3,7 +3,7 @@
3
3
  module ActiveRecord::Associations::Builder # :nodoc:
4
4
  class SingularAssociation < Association #:nodoc:
5
5
  def self.valid_options(options)
6
- super + [:dependent, :primary_key, :inverse_of, :required]
6
+ super + [:foreign_type, :dependent, :primary_key, :inverse_of, :required]
7
7
  end
8
8
 
9
9
  def self.define_accessors(model, reflection)
@@ -66,6 +66,11 @@ module ActiveRecord
66
66
 
67
67
  through_record = through_association.build(*options_for_through_record)
68
68
  through_record.send("#{source_reflection.name}=", record)
69
+
70
+ if options[:source_type]
71
+ through_record.send("#{source_reflection.foreign_type}=", options[:source_type])
72
+ end
73
+
69
74
  through_record
70
75
  end
71
76
  end
@@ -74,9 +74,8 @@ module ActiveRecord
74
74
  value = foreign_klass.base_class.name
75
75
  column = klass.columns_hash[reflection.type.to_s]
76
76
 
77
- substitute = klass.connection.substitute_at(column)
78
77
  binds << Relation::QueryAttribute.new(column.name, value, klass.type_for_attribute(column.name))
79
- constraint = constraint.and table[reflection.type].eq substitute
78
+ constraint = constraint.and table[reflection.type].eq(Arel::Nodes::BindParam.new)
80
79
  end
81
80
 
82
81
  joins << table.create_join(table, table.create_on(constraint), join_type)
@@ -18,7 +18,8 @@ module ActiveRecord
18
18
  through_records = owners.map do |owner|
19
19
  association = owner.association through_reflection.name
20
20
 
21
- [owner, Array(association.reader)]
21
+ center = target_records_from_association(association)
22
+ [owner, Array(center)]
22
23
  end
23
24
 
24
25
  reset_association owners, through_reflection.name
@@ -49,7 +50,7 @@ module ActiveRecord
49
50
  rhs_records = middles.flat_map { |r|
50
51
  association = r.association source_reflection.name
51
52
 
52
- association.reader
53
+ target_records_from_association(association)
53
54
  }.compact
54
55
 
55
56
  rhs_records.sort_by { |rhs| record_offset[rhs] }
@@ -91,6 +92,10 @@ module ActiveRecord
91
92
 
92
93
  scope
93
94
  end
95
+
96
+ def target_records_from_association(association)
97
+ association.loaded? ? association.target : association.reader
98
+ end
94
99
  end
95
100
  end
96
101
  end
@@ -9,9 +9,9 @@ module ActiveRecord
9
9
  end
10
10
 
11
11
  def cast(value)
12
- if value.is_a?(Array)
13
- value.map { |v| cast(v) }
14
- elsif value.is_a?(Hash)
12
+ return if value.nil?
13
+
14
+ if value.is_a?(Hash)
15
15
  set_time_zone_without_conversion(super)
16
16
  elsif value.respond_to?(:in_time_zone)
17
17
  begin
@@ -19,18 +19,22 @@ module ActiveRecord
19
19
  rescue ArgumentError
20
20
  nil
21
21
  end
22
+ else
23
+ map(super) { |t| cast(t) }
22
24
  end
23
25
  end
24
26
 
25
27
  private
26
28
 
27
29
  def convert_time_to_time_zone(value)
28
- if value.is_a?(Array)
29
- value.map { |v| convert_time_to_time_zone(v) }
30
- elsif value.acts_like?(:time)
30
+ return if value.nil?
31
+
32
+ if value.acts_like?(:time)
31
33
  value.in_time_zone
32
- else
34
+ elsif value.is_a?(::Float)
33
35
  value
36
+ else
37
+ map(value) { |v| convert_time_to_time_zone(v) }
34
38
  end
35
39
  end
36
40
 
@@ -331,15 +331,30 @@ module ActiveRecord
331
331
  validation_context = self.validation_context unless [:create, :update].include?(self.validation_context)
332
332
  unless valid = record.valid?(validation_context)
333
333
  if reflection.options[:autosave]
334
+ indexed_attribute = !index.nil? && (reflection.options[:index_errors] || ActiveRecord::Base.index_nested_attribute_errors)
335
+
334
336
  record.errors.each do |attribute, message|
335
- if index.nil? || (!reflection.options[:index_errors] && !ActiveRecord::Base.index_nested_attribute_errors)
336
- attribute = "#{reflection.name}.#{attribute}"
337
- else
337
+ if indexed_attribute
338
338
  attribute = "#{reflection.name}[#{index}].#{attribute}"
339
+ else
340
+ attribute = "#{reflection.name}.#{attribute}"
339
341
  end
340
342
  errors[attribute] << message
341
343
  errors[attribute].uniq!
342
344
  end
345
+
346
+ record.errors.details.each_key do |attribute|
347
+ if indexed_attribute
348
+ reflection_attribute = "#{reflection.name}[#{index}].#{attribute}"
349
+ else
350
+ reflection_attribute = "#{reflection.name}.#{attribute}"
351
+ end
352
+
353
+ record.errors.details[attribute].each do |error|
354
+ errors.details[reflection_attribute] << error
355
+ errors.details[reflection_attribute].uniq!
356
+ end
357
+ end
343
358
  else
344
359
  errors.add(reflection.name)
345
360
  end