activerecord 5.0.0.beta3 → 5.0.0.beta4

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 (80) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +225 -8
  3. data/examples/performance.rb +0 -1
  4. data/examples/simple.rb +0 -1
  5. data/lib/active_record.rb +0 -1
  6. data/lib/active_record/associations.rb +10 -6
  7. data/lib/active_record/associations/association.rb +1 -1
  8. data/lib/active_record/associations/builder/collection_association.rb +5 -1
  9. data/lib/active_record/associations/join_dependency.rb +1 -1
  10. data/lib/active_record/associations/preloader.rb +1 -0
  11. data/lib/active_record/associations/preloader/through_association.rb +15 -8
  12. data/lib/active_record/attribute/user_provided_default.rb +10 -5
  13. data/lib/active_record/attribute_methods/time_zone_conversion.rb +1 -1
  14. data/lib/active_record/attributes.rb +3 -3
  15. data/lib/active_record/autosave_association.rb +1 -1
  16. data/lib/active_record/base.rb +2 -1
  17. data/lib/active_record/collection_cache_key.rb +1 -1
  18. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +0 -19
  19. data/lib/active_record/connection_adapters/abstract/database_statements.rb +7 -8
  20. data/lib/active_record/connection_adapters/abstract/query_cache.rb +1 -1
  21. data/lib/active_record/connection_adapters/abstract/quoting.rb +7 -1
  22. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  23. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +16 -2
  24. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +9 -4
  25. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +20 -10
  26. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +85 -20
  27. data/lib/active_record/connection_adapters/abstract/transaction.rb +13 -1
  28. data/lib/active_record/connection_adapters/abstract_adapter.rb +37 -16
  29. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +119 -108
  30. data/lib/active_record/connection_adapters/column.rb +5 -6
  31. data/lib/active_record/connection_adapters/mysql/database_statements.rb +125 -0
  32. data/lib/active_record/connection_adapters/mysql/quoting.rb +51 -0
  33. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +27 -6
  34. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +8 -13
  35. data/lib/active_record/connection_adapters/mysql2_adapter.rb +18 -55
  36. data/lib/active_record/connection_adapters/postgresql/column.rb +0 -1
  37. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +2 -0
  38. data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
  39. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +7 -10
  40. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +65 -25
  41. data/lib/active_record/connection_adapters/postgresql_adapter.rb +59 -30
  42. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +48 -0
  43. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +7 -0
  44. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +19 -56
  45. data/lib/active_record/connection_adapters/statement_pool.rb +6 -4
  46. data/lib/active_record/core.rb +13 -4
  47. data/lib/active_record/enum.rb +1 -1
  48. data/lib/active_record/errors.rb +9 -0
  49. data/lib/active_record/fixture_set/file.rb +7 -1
  50. data/lib/active_record/gem_version.rb +1 -1
  51. data/lib/active_record/locking/optimistic.rb +4 -0
  52. data/lib/active_record/log_subscriber.rb +1 -1
  53. data/lib/active_record/migration.rb +4 -4
  54. data/lib/active_record/migration/compatibility.rb +1 -1
  55. data/lib/active_record/model_schema.rb +12 -0
  56. data/lib/active_record/nested_attributes.rb +1 -1
  57. data/lib/active_record/persistence.rb +1 -1
  58. data/lib/active_record/query_cache.rb +13 -16
  59. data/lib/active_record/querying.rb +1 -1
  60. data/lib/active_record/railtie.rb +8 -11
  61. data/lib/active_record/railties/databases.rake +5 -5
  62. data/lib/active_record/reflection.rb +21 -4
  63. data/lib/active_record/relation.rb +10 -10
  64. data/lib/active_record/relation/batches.rb +29 -9
  65. data/lib/active_record/relation/delegation.rb +0 -1
  66. data/lib/active_record/relation/finder_methods.rb +27 -8
  67. data/lib/active_record/relation/predicate_builder.rb +4 -2
  68. data/lib/active_record/relation/where_clause.rb +2 -1
  69. data/lib/active_record/schema_dumper.rb +39 -24
  70. data/lib/active_record/scoping/default.rb +2 -1
  71. data/lib/active_record/suppressor.rb +5 -1
  72. data/lib/active_record/tasks/database_tasks.rb +6 -4
  73. data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
  74. data/lib/active_record/type.rb +1 -1
  75. data/lib/active_record/type/internal/abstract_json.rb +1 -5
  76. data/lib/active_record/type/time.rb +12 -0
  77. data/lib/active_record/validations/uniqueness.rb +1 -4
  78. data/lib/rails/generators/active_record/model/model_generator.rb +15 -11
  79. data/lib/rails/generators/active_record/model/templates/application_record.rb +2 -0
  80. metadata +11 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8926929a6df7248ea130b2445de91ba4e4933fb2
4
- data.tar.gz: e25e460b0ff4541594badc944391f6a90b2d4c9f
3
+ metadata.gz: b7f29a643f71feaf240f7200a6e5c8dba8415d6e
4
+ data.tar.gz: 3b934f19c6464814f9a3c63db0684e4fcd25922c
5
5
  SHA512:
6
- metadata.gz: baf2428151cb30e7a384a1a7a63fbb9da784c9a4fe23b8900ee9dc0ba7735baed85ca24b5e1dd2a75d1625e6b6e0b6378764e1694623cf292d66cc189f0fe373
7
- data.tar.gz: 1069aa6eb655e0ee291af703e6d49785603662274d42cc632d95d9b39e37f2facc5d79aa4a25dd24103bd7268ba40a8c5f2af8cc1ece4e7c9d437ff584313439
6
+ metadata.gz: d024e027426b52314572c887bfaca668b290c1a21b6217d9221a7c5bd3d5d1857ed9e435dc007b3ab39767889d29741ba1f48891177def1d865f41d63c95ae72
7
+ data.tar.gz: 9fbbe193fa6100f07a9a16e61b912291bc8e42d802fb53f7d63461ac34a697166cff13b01904dffe9dcbc448e8600fac934d7a1cc307db2144680f00b5085607
@@ -1,5 +1,213 @@
1
+ ## Rails 5.0.0.beta4 (April 27, 2016) ##
2
+
3
+ * PostgreSQL: Support Expression Indexes and Operator Classes.
4
+
5
+ Example:
6
+
7
+ create_table :users do |t|
8
+ t.string :name
9
+ t.index 'lower(name) varchar_pattern_ops'
10
+ end
11
+
12
+ Fixes #19090, #21765, #21819, #24359.
13
+
14
+ *Ryuta Kamizono*
15
+
16
+ * MySQL: Prepared statements support.
17
+
18
+ To enable, set `prepared_statements: true` in config/database.yml.
19
+ Requires mysql2 0.4.4+.
20
+
21
+ *Ryuta Kamizono*
22
+
23
+ * Schema dumper: Indexes are now included in the `create_table` block
24
+ instead of listed afterward as separate `add_index` lines.
25
+
26
+ This tidies up schema.rb and makes it easy to read as a list of tables.
27
+
28
+ Bonus: Allows databases that support it (MySQL) to perform as single
29
+ `CREATE TABLE` query, no additional query per index.
30
+
31
+ *Ryuta Kamizono*
32
+
33
+ * SQLite: Fix uniqueness validation when values exceed the column limit.
34
+
35
+ SQLite doesn't impose length restrictions on strings, BLOBs, or numeric
36
+ values. It treats them as helpful metadata. When we truncate strings
37
+ before checking uniqueness, we'd miss values that exceed the column limit.
38
+
39
+ Other databases enforce length limits. A large value will pass uniqueness
40
+ validation since the column limit guarantees no value that long exists.
41
+ When we insert the row, it'll raise `ActiveRecord::ValueTooLong` as we
42
+ expect.
43
+
44
+ This fixes edge-case incorrect validation failures for values that exceed
45
+ the column limit but are identical to an existing value *when truncated*.
46
+ Now these will pass validation and raise an exception.
47
+
48
+ *Ryuta Kamizono*
49
+
50
+ * Raise `ActiveRecord::ValueTooLong` when column limits are exceeded.
51
+ Supported by MySQL and PostgreSQL adapters.
52
+
53
+ *Ryuta Kamizono*
54
+
55
+ * Migrations: `#foreign_key` respects `table_name_prefix` and `_suffix`.
56
+
57
+ *Ryuta Kamizono*
58
+
59
+ * SQLite: Force NOT NULL primary keys.
60
+
61
+ From SQLite docs: https://www.sqlite.org/lang_createtable.html
62
+ According to the SQL standard, PRIMARY KEY should always imply NOT
63
+ NULL. Unfortunately, due to a bug in some early versions, this is not
64
+ the case in SQLite. Unless the column is an INTEGER PRIMARY KEY or the
65
+ table is a WITHOUT ROWID table or the column is declared NOT NULL,
66
+ SQLite allows NULL values in a PRIMARY KEY column. SQLite could be
67
+ fixed to conform to the standard, but doing so might break legacy
68
+ applications. Hence, it has been decided to merely document the fact
69
+ that SQLite allowing NULLs in most PRIMARY KEY columns.
70
+
71
+ Now we override column options to explicitly set NOT NULL rather than rely
72
+ on implicit NOT NULL like MySQL and PostgreSQL adapters.
73
+
74
+ *Ryuta Kamizono*
75
+
76
+ * Added notice when a database is successfully created or dropped.
77
+
78
+ Example:
79
+
80
+ $ bin/rails db:create
81
+ Created database 'blog_development'
82
+ Created database 'blog_test'
83
+
84
+ $ bin/rails db:drop
85
+ Dropped database 'blog_development'
86
+ Dropped database 'blog_test'
87
+
88
+ Changed older notices
89
+ `blog_development already exists` to `Database 'blog_development' already exists`.
90
+ and
91
+ `Couldn't drop blog_development` to `Couldn't drop database 'blog_development'`.
92
+
93
+ *bogdanvlviv*
94
+
95
+ * Database comments. Annotate database objects (tables, columns, indexes)
96
+ with comments stored in database metadata. PostgreSQL & MySQL support.
97
+
98
+ create_table :pages, force: :cascade, comment: 'CMS content pages' do |t|
99
+ t.string :path, comment: 'Path fragment of page URL used for routing'
100
+ t.string :locale, comment: 'RFC 3066 locale code of website language section'
101
+ t.index [:path, :locale], comment: 'Look up pages by URI'
102
+ end
103
+
104
+ *Andrey Novikov*
105
+
106
+ * Add `quoted_time` for truncating the date part of a TIME column value.
107
+ This fixes queries on TIME column on MariaDB, as it doesn't ignore the
108
+ date part of the string when it coerces to time.
109
+
110
+ *Ryuta Kamizono*
111
+
112
+ * Properly accept all valid JSON primitives in the JSON data type.
113
+
114
+ Fixes #24234
115
+
116
+ *Sean Griffin*
117
+
118
+ * MariaDB 5.3+ supports microsecond datetime precision.
119
+
120
+ *Jeremy Daer*
121
+
122
+ * Delegate `empty?`, `none?` and `one?`. Now they can be invoked as model class methods.
123
+
124
+ Example:
125
+
126
+ # When no record is found on the table
127
+ Topic.empty? # => true
128
+ Topic.none? # => true
129
+
130
+ # When only one record is found on the table
131
+ Topic.one? # => true
132
+
133
+ *Kenta Shirai*
134
+
135
+ * The form builder now properly displays values when passing a proc form
136
+ default to the attributes API.
137
+
138
+ Fixes #24249.
139
+
140
+ *Sean Griffin*
141
+
142
+ * The schema cache is now cleared after the `db:migrate` task is run.
143
+
144
+ Closes #24273.
145
+
146
+ *Chris Arcand*
147
+
148
+ * MySQL: strict mode respects other SQL modes rather than overwriting them.
149
+ Setting `strict: true` adds `STRICT_ALL_TABLES` to `sql_mode`. Setting
150
+ `strict: false` removes `STRICT_TRANS_TABLES`, `STRICT_ALL_TABLES`, and
151
+ `TRADITIONAL` from `sql_mode`.
152
+
153
+ *Ryuta Kamizono*
154
+
155
+ * Execute default_scope defined by abstract class in the context of subclass.
156
+
157
+ Fixes #23413.
158
+ Fixes #10658.
159
+
160
+ *Mehmet Emin İNAÇ*
161
+
162
+ * Fix an issue when preloading associations with extensions.
163
+ Previously every association with extension methods was transformed into an
164
+ instance dependent scope. This is no longer the case.
165
+
166
+ Fixes #23934.
167
+
168
+ *Yves Senn*
169
+
170
+ * Deprecate `{insert|update|delete}_sql` in `DatabaseStatements`.
171
+ Use the `{insert|update|delete}` public methods instead.
172
+
173
+ *Ryuta Kamizono*
174
+
175
+ * Added a configuration option to have active record raise an ArgumentError
176
+ if the order or limit is ignored in a batch query, rather than logging a
177
+ warning message.
178
+
179
+ *Scott Ringwelski*
180
+
181
+ * Honour the order of the joining model in a `has_many :through` association when eager loading.
182
+
183
+ Example:
184
+
185
+ The below will now follow the order of `by_lines` when eager loading `authors`.
186
+
187
+ class Article < ActiveRecord::Base
188
+ has_many :by_lines, -> { order(:position) }
189
+ has_many :authors, through: :by_lines
190
+ end
191
+
192
+ Fixes #17864.
193
+
194
+ *Yasyf Mohamedali*, *Joel Turkel*
195
+
196
+ * Ensure that the Suppressor runs before validations.
197
+
198
+ This moves the suppressor up to be run before validations rather than after
199
+ validations. There's no reason to validate a record you aren't planning on saving.
200
+
201
+ *Eileen M. Uchitelle*
202
+
1
203
  ## Rails 5.0.0.beta3 (February 24, 2016) ##
2
204
 
205
+ * Save many-to-many objects based on association primary key.
206
+
207
+ Fixes #20995.
208
+
209
+ *himesh-r*
210
+
3
211
  * Ensure that mutations of the array returned from `ActiveRecord::Relation#to_a`
4
212
  do not affect the original relation, by returning a duplicate array each time.
5
213
 
@@ -53,7 +261,6 @@
53
261
 
54
262
  *Bogdan Gusiev*
55
263
 
56
-
57
264
  * Allow `joins` to be unscoped.
58
265
 
59
266
  Fixes #13775.
@@ -182,6 +389,21 @@
182
389
 
183
390
  ## Rails 5.0.0.beta1 (December 18, 2015) ##
184
391
 
392
+ * Limit record touching to once per transaction.
393
+
394
+ If you have a parent/grand-parent relation like:
395
+
396
+ Comment belongs_to :message, touch: true
397
+ Message belongs_to :project, touch: true
398
+ Project belongs_to :account, touch: true
399
+
400
+ When the lowest entry(`Comment`) is saved, now, it won't repeat the touch
401
+ call multiple times for the parent records.
402
+
403
+ Related #18606.
404
+
405
+ *arthurnn*
406
+
185
407
  * Order the result of `find(ids)` to match the passed array, if the relation
186
408
  has no explicit order defined.
187
409
 
@@ -456,13 +678,13 @@
456
678
  * Add option to index errors in nested attributes
457
679
 
458
680
  For models which have nested attributes, errors within those models will
459
- now be indexed if :index_errors is specified when defining a
681
+ now be indexed if `:index_errors` is specified when defining a
460
682
  has_many relationship, or if its set in the global config.
461
683
 
462
684
  Example:
463
685
 
464
686
  class Guitar < ActiveRecord::Base
465
- has_many :tuning_pegs
687
+ has_many :tuning_pegs, index_errors: true
466
688
  accepts_nested_attributes_for :tuning_pegs
467
689
  end
468
690
 
@@ -1340,11 +1562,6 @@
1340
1562
 
1341
1563
  *Hyonjee Joo*
1342
1564
 
1343
- * Deprecate passing of `start` value to `find_in_batches` and `find_each`
1344
- in favour of `begin_at` value.
1345
-
1346
- *Vipul A M*
1347
-
1348
1565
  * Add `foreign_key_exists?` method.
1349
1566
 
1350
1567
  *Tõnis Simo*
@@ -1,4 +1,3 @@
1
- require File.expand_path('../../../load_paths', __FILE__)
2
1
  require "active_record"
3
2
  require 'benchmark/ips'
4
3
 
@@ -1,4 +1,3 @@
1
- require File.expand_path('../../../load_paths', __FILE__)
2
1
  require 'active_record'
3
2
 
4
3
  class Person < ActiveRecord::Base
@@ -137,7 +137,6 @@ module ActiveRecord
137
137
 
138
138
  eager_autoload do
139
139
  autoload :AbstractAdapter
140
- autoload :ConnectionManagement, "active_record/connection_adapters/abstract/connection_pool"
141
140
  end
142
141
  end
143
142
 
@@ -318,7 +318,7 @@ module ActiveRecord
318
318
  # create_other(attributes={}) | X | | X
319
319
  # create_other!(attributes={}) | X | | X
320
320
  #
321
- # ===Collection associations (one-to-many / many-to-many)
321
+ # === Collection associations (one-to-many / many-to-many)
322
322
  # | | | has_many
323
323
  # generated methods | habtm | has_many | :through
324
324
  # ----------------------------------+-------+----------+----------
@@ -504,7 +504,7 @@ module ActiveRecord
504
504
  #
505
505
  # == Customizing the query
506
506
  #
507
- # \Associations are built from <tt>Relation</tt>s, and you can use the Relation syntax
507
+ # \Associations are built from <tt>Relation</tt> objects, and you can use the Relation syntax
508
508
  # to customize them. For example, to add a condition:
509
509
  #
510
510
  # class Blog < ActiveRecord::Base
@@ -1326,7 +1326,8 @@ module ActiveRecord
1326
1326
  # Specifies type of the source association used by #has_many <tt>:through</tt> queries where the source
1327
1327
  # association is a polymorphic #belongs_to.
1328
1328
  # [:validate]
1329
- # If +false+, don't validate the associated objects when saving the parent object. true by default.
1329
+ # When set to +true+, validates new objects added to association when saving the parent object. +true+ by default.
1330
+ # If you want to ensure associated objects are revalidated on every update, use +validates_associated+.
1330
1331
  # [:autosave]
1331
1332
  # If true, always save the associated objects or destroy them if marked for destruction,
1332
1333
  # when saving the parent object. If false, never save or destroy the associated objects.
@@ -1456,7 +1457,8 @@ module ActiveRecord
1456
1457
  # Specifies type of the source association used by #has_one <tt>:through</tt> queries where the source
1457
1458
  # association is a polymorphic #belongs_to.
1458
1459
  # [:validate]
1459
- # If +false+, don't validate the associated object when saving the parent object. +false+ by default.
1460
+ # When set to +true+, validates new objects added to association when saving the parent object. +false+ by default.
1461
+ # If you want to ensure associated objects are revalidated on every update, use +validates_associated+.
1460
1462
  # [:autosave]
1461
1463
  # If true, always save the associated object or destroy it if marked for destruction,
1462
1464
  # when saving the parent object. If false, never save or destroy the associated object.
@@ -1580,7 +1582,8 @@ module ActiveRecord
1580
1582
  # Note: If you've enabled the counter cache, then you may want to add the counter cache attribute
1581
1583
  # to the +attr_readonly+ list in the associated classes (e.g. <tt>class Post; attr_readonly :comments_count; end</tt>).
1582
1584
  # [:validate]
1583
- # If +false+, don't validate the associated objects when saving the parent object. +false+ by default.
1585
+ # When set to +true+, validates new objects added to association when saving the parent object. +false+ by default.
1586
+ # If you want to ensure associated objects are revalidated on every update, use +validates_associated+.
1584
1587
  # [:autosave]
1585
1588
  # If true, always save the associated object or destroy it if marked for destruction, when
1586
1589
  # saving the parent object.
@@ -1766,7 +1769,8 @@ module ActiveRecord
1766
1769
  # So if a Person class makes a #has_and_belongs_to_many association to Project,
1767
1770
  # the association will use "project_id" as the default <tt>:association_foreign_key</tt>.
1768
1771
  # [:validate]
1769
- # If +false+, don't validate the associated objects when saving the parent object. +true+ by default.
1772
+ # When set to +true+, validates new objects added to association when saving the parent object. +true+ by default.
1773
+ # If you want to ensure associated objects are revalidated on every update, use +validates_associated+.
1770
1774
  # [:autosave]
1771
1775
  # If true, always save the associated objects or destroy them if marked for destruction, when
1772
1776
  # saving the parent object.
@@ -257,7 +257,7 @@ module ActiveRecord
257
257
 
258
258
  # Returns true if statement cache should be skipped on the association reader.
259
259
  def skip_statement_cache?
260
- reflection.scope_chain.any?(&:any?) ||
260
+ reflection.has_scope? ||
261
261
  scope.eager_loading? ||
262
262
  klass.scope_attributes? ||
263
263
  reflection.source_reflection.active_record.default_scopes.any?
@@ -70,7 +70,11 @@ module ActiveRecord::Associations::Builder # :nodoc:
70
70
 
71
71
  def self.wrap_scope(scope, mod)
72
72
  if scope
73
- proc { |owner| instance_exec(owner, &scope).extending(mod) }
73
+ if scope.arity > 0
74
+ proc { |owner| instance_exec(owner, &scope).extending(mod) }
75
+ else
76
+ proc { instance_exec(&scope).extending(mod) }
77
+ end
74
78
  else
75
79
  proc { extending(mod) }
76
80
  end
@@ -228,7 +228,7 @@ module ActiveRecord
228
228
 
229
229
  def find_reflection(klass, name)
230
230
  klass._reflect_on_association(name) or
231
- raise ConfigurationError, "Association named '#{ name }' was not found on #{ klass.name }; perhaps you misspelled it?"
231
+ raise ConfigurationError, "Can't join '#{ klass.name }' to association named '#{ name }'; perhaps you misspelled it?"
232
232
  end
233
233
 
234
234
  def build(associations, base_klass)
@@ -184,6 +184,7 @@ module ActiveRecord
184
184
  def self.new(klass, owners, reflection, preload_scope); self; end
185
185
  def self.run(preloader); end
186
186
  def self.preloaded_records; []; end
187
+ def self.owners; []; end
187
188
  end
188
189
 
189
190
  # Returns a class containing the logic needed to load preload the data
@@ -38,12 +38,7 @@ module ActiveRecord
38
38
  }
39
39
  end
40
40
 
41
- record_offset = {}
42
- @preloaded_records.each_with_index do |record,i|
43
- record_offset[record] = i
44
- end
45
-
46
- through_records.each_with_object({}) { |(lhs,center),records_by_owner|
41
+ through_records.each_with_object({}) do |(lhs,center), records_by_owner|
47
42
  pl_to_middle = center.group_by { |record| middle_to_pl[record] }
48
43
 
49
44
  records_by_owner[lhs] = pl_to_middle.flat_map do |pl, middles|
@@ -53,13 +48,25 @@ module ActiveRecord
53
48
  target_records_from_association(association)
54
49
  }.compact
55
50
 
56
- rhs_records.sort_by { |rhs| record_offset[rhs] }
51
+ # Respect the order on `reflection_scope` if it exists, else use the natural order.
52
+ if reflection_scope.values[:order].present?
53
+ @id_map ||= id_to_index_map @preloaded_records
54
+ rhs_records.sort_by { |rhs| @id_map[rhs] }
55
+ else
56
+ rhs_records
57
+ end
57
58
  end
58
- }
59
+ end
59
60
  end
60
61
 
61
62
  private
62
63
 
64
+ def id_to_index_map(ids)
65
+ id_map = {}
66
+ ids.each_with_index { |id, index| id_map[id] = index }
67
+ id_map
68
+ end
69
+
63
70
  def reset_association(owners, association_name)
64
71
  should_reset = (through_scope != through_reflection.klass.unscoped) ||
65
72
  (reflection.options[:source_type] && through_reflection.collection?)
@@ -4,20 +4,25 @@ module ActiveRecord
4
4
  class Attribute # :nodoc:
5
5
  class UserProvidedDefault < FromUser # :nodoc:
6
6
  def initialize(name, value, type, database_default)
7
+ @user_provided_value = value
7
8
  super(name, value, type, database_default)
8
9
  end
9
10
 
10
- def type_cast(value)
11
- if value.is_a?(Proc)
12
- super(value.call)
11
+ def value_before_type_cast
12
+ if user_provided_value.is_a?(Proc)
13
+ @memoized_value_before_type_cast ||= user_provided_value.call
13
14
  else
14
- super
15
+ @user_provided_value
15
16
  end
16
17
  end
17
18
 
18
19
  def with_type(type)
19
- self.class.new(name, value_before_type_cast, type, original_attribute)
20
+ self.class.new(name, user_provided_value, type, original_attribute)
20
21
  end
22
+
23
+ protected
24
+
25
+ attr_reader :user_provided_value
21
26
  end
22
27
  end
23
28
  end