activerecord 4.2.11.3 → 5.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +1029 -1349
- data/MIT-LICENSE +1 -1
- data/README.rdoc +6 -7
- data/examples/performance.rb +2 -2
- data/lib/active_record.rb +7 -3
- data/lib/active_record/aggregations.rb +35 -25
- data/lib/active_record/association_relation.rb +2 -2
- data/lib/active_record/associations.rb +305 -204
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +10 -8
- data/lib/active_record/associations/association_scope.rb +73 -102
- data/lib/active_record/associations/belongs_to_association.rb +20 -32
- data/lib/active_record/associations/builder/association.rb +28 -34
- data/lib/active_record/associations/builder/belongs_to.rb +41 -18
- data/lib/active_record/associations/builder/collection_association.rb +8 -24
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +11 -11
- data/lib/active_record/associations/builder/has_many.rb +4 -4
- data/lib/active_record/associations/builder/has_one.rb +10 -5
- data/lib/active_record/associations/builder/singular_association.rb +2 -9
- data/lib/active_record/associations/collection_association.rb +40 -43
- data/lib/active_record/associations/collection_proxy.rb +55 -29
- data/lib/active_record/associations/foreign_association.rb +1 -1
- data/lib/active_record/associations/has_many_association.rb +20 -71
- data/lib/active_record/associations/has_many_through_association.rb +8 -52
- data/lib/active_record/associations/has_one_association.rb +12 -5
- data/lib/active_record/associations/join_dependency.rb +28 -18
- data/lib/active_record/associations/join_dependency/join_association.rb +13 -12
- data/lib/active_record/associations/preloader.rb +13 -4
- data/lib/active_record/associations/preloader/association.rb +45 -51
- data/lib/active_record/associations/preloader/collection_association.rb +0 -6
- data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
- data/lib/active_record/associations/preloader/has_one.rb +0 -8
- data/lib/active_record/associations/preloader/through_association.rb +5 -4
- data/lib/active_record/associations/singular_association.rb +6 -0
- data/lib/active_record/associations/through_association.rb +11 -3
- data/lib/active_record/attribute.rb +61 -17
- data/lib/active_record/attribute/user_provided_default.rb +23 -0
- data/lib/active_record/attribute_assignment.rb +27 -140
- data/lib/active_record/attribute_decorators.rb +6 -5
- data/lib/active_record/attribute_methods.rb +79 -26
- data/lib/active_record/attribute_methods/before_type_cast.rb +1 -1
- data/lib/active_record/attribute_methods/dirty.rb +46 -86
- data/lib/active_record/attribute_methods/primary_key.rb +2 -2
- data/lib/active_record/attribute_methods/query.rb +2 -2
- data/lib/active_record/attribute_methods/read.rb +26 -42
- data/lib/active_record/attribute_methods/serialization.rb +13 -16
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +42 -9
- data/lib/active_record/attribute_methods/write.rb +13 -24
- data/lib/active_record/attribute_mutation_tracker.rb +70 -0
- data/lib/active_record/attribute_set.rb +30 -3
- data/lib/active_record/attribute_set/builder.rb +6 -4
- data/lib/active_record/attributes.rb +194 -81
- data/lib/active_record/autosave_association.rb +33 -15
- data/lib/active_record/base.rb +30 -18
- data/lib/active_record/callbacks.rb +36 -40
- data/lib/active_record/coders/yaml_column.rb +20 -8
- data/lib/active_record/collection_cache_key.rb +31 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +431 -122
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +40 -22
- data/lib/active_record/connection_adapters/abstract/quoting.rb +62 -8
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +46 -38
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +229 -185
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +52 -13
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +275 -115
- data/lib/active_record/connection_adapters/abstract/transaction.rb +32 -33
- data/lib/active_record/connection_adapters/abstract_adapter.rb +83 -32
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +384 -221
- data/lib/active_record/connection_adapters/column.rb +27 -41
- data/lib/active_record/connection_adapters/connection_specification.rb +2 -21
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +57 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +69 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +59 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +22 -101
- data/lib/active_record/connection_adapters/postgresql/column.rb +6 -10
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +23 -57
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +7 -22
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -26
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +0 -2
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +23 -16
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +0 -4
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +18 -11
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +29 -10
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -79
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +54 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +174 -128
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +184 -112
- data/lib/active_record/connection_adapters/schema_cache.rb +36 -23
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +15 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +134 -110
- data/lib/active_record/connection_adapters/statement_pool.rb +28 -11
- data/lib/active_record/connection_handling.rb +5 -5
- data/lib/active_record/core.rb +72 -104
- data/lib/active_record/counter_cache.rb +9 -20
- data/lib/active_record/dynamic_matchers.rb +1 -20
- data/lib/active_record/enum.rb +110 -76
- data/lib/active_record/errors.rb +72 -47
- data/lib/active_record/explain_registry.rb +1 -1
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +19 -4
- data/lib/active_record/fixtures.rb +76 -40
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +27 -40
- data/lib/active_record/integration.rb +4 -4
- data/lib/active_record/legacy_yaml_adapter.rb +18 -2
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +10 -14
- data/lib/active_record/locking/pessimistic.rb +1 -1
- data/lib/active_record/log_subscriber.rb +40 -22
- data/lib/active_record/migration.rb +304 -133
- data/lib/active_record/migration/command_recorder.rb +59 -18
- data/lib/active_record/migration/compatibility.rb +90 -0
- data/lib/active_record/model_schema.rb +92 -40
- data/lib/active_record/nested_attributes.rb +45 -34
- data/lib/active_record/null_relation.rb +15 -7
- data/lib/active_record/persistence.rb +112 -72
- data/lib/active_record/querying.rb +6 -5
- data/lib/active_record/railtie.rb +20 -13
- data/lib/active_record/railties/controller_runtime.rb +1 -1
- data/lib/active_record/railties/databases.rake +47 -38
- data/lib/active_record/readonly_attributes.rb +1 -1
- data/lib/active_record/reflection.rb +182 -57
- data/lib/active_record/relation.rb +152 -100
- data/lib/active_record/relation/batches.rb +133 -33
- data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
- data/lib/active_record/relation/calculations.rb +80 -101
- data/lib/active_record/relation/delegation.rb +6 -19
- data/lib/active_record/relation/finder_methods.rb +58 -46
- data/lib/active_record/relation/from_clause.rb +32 -0
- data/lib/active_record/relation/merger.rb +13 -42
- data/lib/active_record/relation/predicate_builder.rb +99 -105
- data/lib/active_record/relation/predicate_builder/array_handler.rb +11 -16
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +78 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
- data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +17 -0
- data/lib/active_record/relation/query_attribute.rb +19 -0
- data/lib/active_record/relation/query_methods.rb +274 -238
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +3 -6
- data/lib/active_record/relation/where_clause.rb +173 -0
- data/lib/active_record/relation/where_clause_factory.rb +37 -0
- data/lib/active_record/result.rb +4 -3
- data/lib/active_record/runtime_registry.rb +1 -1
- data/lib/active_record/sanitization.rb +94 -65
- data/lib/active_record/schema.rb +23 -22
- data/lib/active_record/schema_dumper.rb +33 -22
- data/lib/active_record/schema_migration.rb +10 -4
- data/lib/active_record/scoping.rb +17 -6
- data/lib/active_record/scoping/default.rb +19 -6
- data/lib/active_record/scoping/named.rb +39 -28
- data/lib/active_record/secure_token.rb +38 -0
- data/lib/active_record/serialization.rb +2 -4
- data/lib/active_record/statement_cache.rb +15 -13
- data/lib/active_record/store.rb +8 -3
- data/lib/active_record/suppressor.rb +54 -0
- data/lib/active_record/table_metadata.rb +64 -0
- data/lib/active_record/tasks/database_tasks.rb +30 -40
- data/lib/active_record/tasks/mysql_database_tasks.rb +7 -15
- data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -2
- data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
- data/lib/active_record/timestamp.rb +16 -9
- data/lib/active_record/touch_later.rb +58 -0
- data/lib/active_record/transactions.rb +138 -56
- data/lib/active_record/type.rb +66 -17
- data/lib/active_record/type/adapter_specific_registry.rb +130 -0
- data/lib/active_record/type/date.rb +2 -45
- data/lib/active_record/type/date_time.rb +2 -49
- data/lib/active_record/type/internal/abstract_json.rb +33 -0
- data/lib/active_record/type/internal/timezone.rb +15 -0
- data/lib/active_record/type/serialized.rb +9 -14
- data/lib/active_record/type/time.rb +3 -21
- data/lib/active_record/type/type_map.rb +4 -4
- data/lib/active_record/type_caster.rb +7 -0
- data/lib/active_record/type_caster/connection.rb +29 -0
- data/lib/active_record/type_caster/map.rb +19 -0
- data/lib/active_record/validations.rb +33 -32
- data/lib/active_record/validations/absence.rb +24 -0
- data/lib/active_record/validations/associated.rb +10 -3
- data/lib/active_record/validations/length.rb +36 -0
- data/lib/active_record/validations/presence.rb +12 -12
- data/lib/active_record/validations/uniqueness.rb +24 -21
- data/lib/rails/generators/active_record/migration.rb +7 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +7 -4
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +8 -3
- data/lib/rails/generators/active_record/migration/templates/migration.rb +4 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +21 -15
- data/lib/rails/generators/active_record/model/templates/model.rb +3 -0
- metadata +50 -35
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +0 -11
- data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
- data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
- data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
- data/lib/active_record/serializers/xml_serializer.rb +0 -193
- data/lib/active_record/type/big_integer.rb +0 -13
- data/lib/active_record/type/binary.rb +0 -50
- data/lib/active_record/type/boolean.rb +0 -31
- data/lib/active_record/type/decimal.rb +0 -64
- data/lib/active_record/type/decimal_without_scale.rb +0 -11
- data/lib/active_record/type/decorator.rb +0 -14
- data/lib/active_record/type/float.rb +0 -19
- data/lib/active_record/type/integer.rb +0 -59
- data/lib/active_record/type/mutable.rb +0 -16
- data/lib/active_record/type/numeric.rb +0 -36
- data/lib/active_record/type/string.rb +0 -40
- data/lib/active_record/type/text.rb +0 -11
- data/lib/active_record/type/time_value.rb +0 -38
- data/lib/active_record/type/unsigned_integer.rb +0 -15
- data/lib/active_record/type/value.rb +0 -110
@@ -33,7 +33,7 @@ module ActiveRecord
|
|
33
33
|
|
34
34
|
def initialize(klass, association) #:nodoc:
|
35
35
|
@association = association
|
36
|
-
super klass, klass.arel_table
|
36
|
+
super klass, klass.arel_table, klass.predicate_builder
|
37
37
|
merge! association.scope(nullify: false)
|
38
38
|
end
|
39
39
|
|
@@ -112,7 +112,7 @@ module ActiveRecord
|
|
112
112
|
end
|
113
113
|
|
114
114
|
# Finds an object in the collection responding to the +id+. Uses the same
|
115
|
-
# rules as
|
115
|
+
# rules as ActiveRecord::Base.find. Returns ActiveRecord::RecordNotFound
|
116
116
|
# error if the object cannot be found.
|
117
117
|
#
|
118
118
|
# class Person < ActiveRecord::Base
|
@@ -127,7 +127,7 @@ module ActiveRecord
|
|
127
127
|
# # ]
|
128
128
|
#
|
129
129
|
# person.pets.find(1) # => #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>
|
130
|
-
# person.pets.find(4) # => ActiveRecord::RecordNotFound: Couldn't find Pet with id=4
|
130
|
+
# person.pets.find(4) # => ActiveRecord::RecordNotFound: Couldn't find Pet with 'id'=4
|
131
131
|
#
|
132
132
|
# person.pets.find(2) { |pet| pet.name.downcase! }
|
133
133
|
# # => #<Pet id: 2, name: "fancy-fancy", person_id: 1>
|
@@ -171,27 +171,27 @@ module ActiveRecord
|
|
171
171
|
@association.first(*args)
|
172
172
|
end
|
173
173
|
|
174
|
-
# Same as
|
174
|
+
# Same as #first except returns only the second record.
|
175
175
|
def second(*args)
|
176
176
|
@association.second(*args)
|
177
177
|
end
|
178
178
|
|
179
|
-
# Same as
|
179
|
+
# Same as #first except returns only the third record.
|
180
180
|
def third(*args)
|
181
181
|
@association.third(*args)
|
182
182
|
end
|
183
183
|
|
184
|
-
# Same as
|
184
|
+
# Same as #first except returns only the fourth record.
|
185
185
|
def fourth(*args)
|
186
186
|
@association.fourth(*args)
|
187
187
|
end
|
188
188
|
|
189
|
-
# Same as
|
189
|
+
# Same as #first except returns only the fifth record.
|
190
190
|
def fifth(*args)
|
191
191
|
@association.fifth(*args)
|
192
192
|
end
|
193
193
|
|
194
|
-
# Same as
|
194
|
+
# Same as #first except returns only the forty second record.
|
195
195
|
# Also known as accessing "the reddit".
|
196
196
|
def forty_two(*args)
|
197
197
|
@association.forty_two(*args)
|
@@ -227,6 +227,31 @@ module ActiveRecord
|
|
227
227
|
@association.last(*args)
|
228
228
|
end
|
229
229
|
|
230
|
+
# Gives a record (or N records if a parameter is supplied) from the collection
|
231
|
+
# using the same rules as <tt>ActiveRecord::Base.take</tt>.
|
232
|
+
#
|
233
|
+
# class Person < ActiveRecord::Base
|
234
|
+
# has_many :pets
|
235
|
+
# end
|
236
|
+
#
|
237
|
+
# person.pets
|
238
|
+
# # => [
|
239
|
+
# # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
|
240
|
+
# # #<Pet id: 2, name: "Spook", person_id: 1>,
|
241
|
+
# # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
|
242
|
+
# # ]
|
243
|
+
#
|
244
|
+
# person.pets.take # => #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>
|
245
|
+
#
|
246
|
+
# person.pets.take(2)
|
247
|
+
# # => [
|
248
|
+
# # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
|
249
|
+
# # #<Pet id: 2, name: "Spook", person_id: 1>
|
250
|
+
# # ]
|
251
|
+
#
|
252
|
+
# another_person_without.pets # => []
|
253
|
+
# another_person_without.pets.take # => nil
|
254
|
+
# another_person_without.pets.take(2) # => []
|
230
255
|
def take(n = nil)
|
231
256
|
@association.take(n)
|
232
257
|
end
|
@@ -290,7 +315,7 @@ module ActiveRecord
|
|
290
315
|
@association.create(attributes, &block)
|
291
316
|
end
|
292
317
|
|
293
|
-
# Like
|
318
|
+
# Like #create, except that if the record is invalid, raises an exception.
|
294
319
|
#
|
295
320
|
# class Person
|
296
321
|
# has_many :pets
|
@@ -307,8 +332,8 @@ module ActiveRecord
|
|
307
332
|
end
|
308
333
|
|
309
334
|
# Add one or more records to the collection by setting their foreign keys
|
310
|
-
# to the association's primary key. Since
|
311
|
-
# inserts each record, +push+ and
|
335
|
+
# to the association's primary key. Since #<< flattens its argument list and
|
336
|
+
# inserts each record, +push+ and #concat behave identically. Returns +self+
|
312
337
|
# so method calls may be chained.
|
313
338
|
#
|
314
339
|
# class Person < ActiveRecord::Base
|
@@ -364,7 +389,7 @@ module ActiveRecord
|
|
364
389
|
# specified by the +:dependent+ option. If no +:dependent+ option is given,
|
365
390
|
# then it will follow the default strategy.
|
366
391
|
#
|
367
|
-
# For
|
392
|
+
# For <tt>has_many :through</tt> associations, the default deletion strategy is
|
368
393
|
# +:delete_all+.
|
369
394
|
#
|
370
395
|
# For +has_many+ associations, the default deletion strategy is +:nullify+.
|
@@ -399,7 +424,7 @@ module ActiveRecord
|
|
399
424
|
# # #<Pet id: 3, name: "Choo-Choo", person_id: nil>
|
400
425
|
# # ]
|
401
426
|
#
|
402
|
-
# Both +has_many+ and
|
427
|
+
# Both +has_many+ and <tt>has_many :through</tt> dependencies default to the
|
403
428
|
# +:delete_all+ strategy if the +:dependent+ option is set to +:destroy+.
|
404
429
|
# Records are not instantiated and callbacks will not be fired.
|
405
430
|
#
|
@@ -418,7 +443,7 @@ module ActiveRecord
|
|
418
443
|
# person.pets.delete_all
|
419
444
|
#
|
420
445
|
# Pet.find(1, 2, 3)
|
421
|
-
# # => ActiveRecord::RecordNotFound
|
446
|
+
# # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 2, 3)
|
422
447
|
#
|
423
448
|
# If it is set to <tt>:delete_all</tt>, all the objects are deleted
|
424
449
|
# *without* calling their +destroy+ method.
|
@@ -438,7 +463,7 @@ module ActiveRecord
|
|
438
463
|
# person.pets.delete_all
|
439
464
|
#
|
440
465
|
# Pet.find(1, 2, 3)
|
441
|
-
# # => ActiveRecord::RecordNotFound
|
466
|
+
# # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 2, 3)
|
442
467
|
def delete_all(dependent = nil)
|
443
468
|
@association.delete_all(dependent)
|
444
469
|
end
|
@@ -475,7 +500,7 @@ module ActiveRecord
|
|
475
500
|
# then it will follow the default strategy. Returns an array with the
|
476
501
|
# deleted records.
|
477
502
|
#
|
478
|
-
# For
|
503
|
+
# For <tt>has_many :through</tt> associations, the default deletion strategy is
|
479
504
|
# +:delete_all+.
|
480
505
|
#
|
481
506
|
# For +has_many+ associations, the default deletion strategy is +:nullify+.
|
@@ -532,7 +557,7 @@ module ActiveRecord
|
|
532
557
|
# # => [#<Pet id: 2, name: "Spook", person_id: 1>]
|
533
558
|
#
|
534
559
|
# Pet.find(1, 3)
|
535
|
-
# # => ActiveRecord::RecordNotFound: Couldn't find all Pets with
|
560
|
+
# # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 3)
|
536
561
|
#
|
537
562
|
# If it is set to <tt>:delete_all</tt>, all the +records+ are deleted
|
538
563
|
# *without* calling their +destroy+ method.
|
@@ -560,9 +585,9 @@ module ActiveRecord
|
|
560
585
|
# # ]
|
561
586
|
#
|
562
587
|
# Pet.find(1)
|
563
|
-
# # => ActiveRecord::RecordNotFound: Couldn't find Pet with id=1
|
588
|
+
# # => ActiveRecord::RecordNotFound: Couldn't find Pet with 'id'=1
|
564
589
|
#
|
565
|
-
# You can pass +
|
590
|
+
# You can pass +Fixnum+ or +String+ values, it finds the records
|
566
591
|
# responding to the +id+ and executes delete on them.
|
567
592
|
#
|
568
593
|
# class Person < ActiveRecord::Base
|
@@ -624,9 +649,9 @@ module ActiveRecord
|
|
624
649
|
# person.pets.size # => 0
|
625
650
|
# person.pets # => []
|
626
651
|
#
|
627
|
-
# Pet.find(1, 2, 3) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with
|
652
|
+
# Pet.find(1, 2, 3) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 2, 3)
|
628
653
|
#
|
629
|
-
# You can pass +
|
654
|
+
# You can pass +Fixnum+ or +String+ values, it finds the records
|
630
655
|
# responding to the +id+ and then deletes them from the database.
|
631
656
|
#
|
632
657
|
# person.pets.size # => 3
|
@@ -656,7 +681,7 @@ module ActiveRecord
|
|
656
681
|
# person.pets.size # => 0
|
657
682
|
# person.pets # => []
|
658
683
|
#
|
659
|
-
# Pet.find(4, 5, 6) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with
|
684
|
+
# Pet.find(4, 5, 6) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (4, 5, 6)
|
660
685
|
def destroy(*records)
|
661
686
|
@association.destroy(*records)
|
662
687
|
end
|
@@ -693,10 +718,8 @@ module ActiveRecord
|
|
693
718
|
# # #<Pet id: 2, name: "Spook", person_id: 1>,
|
694
719
|
# # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
|
695
720
|
# # ]
|
696
|
-
def count(column_name = nil
|
697
|
-
|
698
|
-
# activerecord-deprecated_finders.
|
699
|
-
@association.count(column_name, options)
|
721
|
+
def count(column_name = nil)
|
722
|
+
@association.count(column_name)
|
700
723
|
end
|
701
724
|
|
702
725
|
# Returns the size of the collection. If the collection hasn't been loaded,
|
@@ -783,7 +806,7 @@ module ActiveRecord
|
|
783
806
|
# person.pets.any? # => false
|
784
807
|
#
|
785
808
|
# person.pets << Pet.new(name: 'Snoop')
|
786
|
-
# person.pets.count # =>
|
809
|
+
# person.pets.count # => 1
|
787
810
|
# person.pets.any? # => true
|
788
811
|
#
|
789
812
|
# You can also pass a +block+ to define criteria. The behavior
|
@@ -858,7 +881,7 @@ module ActiveRecord
|
|
858
881
|
!!@association.include?(record)
|
859
882
|
end
|
860
883
|
|
861
|
-
def arel
|
884
|
+
def arel #:nodoc:
|
862
885
|
scope.arel
|
863
886
|
end
|
864
887
|
|
@@ -973,12 +996,15 @@ module ActiveRecord
|
|
973
996
|
alias_method :append, :<<
|
974
997
|
|
975
998
|
def prepend(*args)
|
976
|
-
raise NoMethodError, "prepend on association is not defined. Please use
|
999
|
+
raise NoMethodError, "prepend on association is not defined. Please use <<, push or append"
|
977
1000
|
end
|
978
1001
|
|
979
1002
|
# Equivalent to +delete_all+. The difference is that returns +self+, instead
|
980
1003
|
# of an array with the deleted objects, so methods can be chained. See
|
981
1004
|
# +delete_all+ for more information.
|
1005
|
+
# Note that because +delete_all+ removes records by directly
|
1006
|
+
# running an SQL query into the database, the +updated_at+ column of
|
1007
|
+
# the object is not changed.
|
982
1008
|
def clear
|
983
1009
|
delete_all
|
984
1010
|
self
|
@@ -15,9 +15,16 @@ module ActiveRecord
|
|
15
15
|
|
16
16
|
when :restrict_with_error
|
17
17
|
unless empty?
|
18
|
-
record =
|
19
|
-
owner.errors.
|
20
|
-
|
18
|
+
record = owner.class.human_attribute_name(reflection.name).downcase
|
19
|
+
message = owner.errors.generate_message(:base, :'restrict_dependent_destroy.many', record: record, raise: true) rescue nil
|
20
|
+
if message
|
21
|
+
ActiveSupport::Deprecation.warn(<<-MESSAGE.squish)
|
22
|
+
The error key `:'restrict_dependent_destroy.many'` has been deprecated and will be removed in Rails 5.1.
|
23
|
+
Please use `:'restrict_dependent_destroy.has_many'` instead.
|
24
|
+
MESSAGE
|
25
|
+
end
|
26
|
+
owner.errors.add(:base, message || :'restrict_dependent_destroy.has_many', record: record)
|
27
|
+
throw(:abort)
|
21
28
|
end
|
22
29
|
|
23
30
|
else
|
@@ -43,7 +50,7 @@ module ActiveRecord
|
|
43
50
|
end
|
44
51
|
|
45
52
|
def empty?
|
46
|
-
if has_cached_counter?
|
53
|
+
if reflection.has_cached_counter?
|
47
54
|
size.zero?
|
48
55
|
else
|
49
56
|
super
|
@@ -66,8 +73,8 @@ module ActiveRecord
|
|
66
73
|
# If the collection is empty the target is set to an empty array and
|
67
74
|
# the loaded flag is set to true as well.
|
68
75
|
def count_records
|
69
|
-
count = if has_cached_counter?
|
70
|
-
owner._read_attribute
|
76
|
+
count = if reflection.has_cached_counter?
|
77
|
+
owner._read_attribute reflection.counter_cache_column
|
71
78
|
else
|
72
79
|
scope.count
|
73
80
|
end
|
@@ -80,78 +87,20 @@ module ActiveRecord
|
|
80
87
|
[association_scope.limit_value, count].compact.min
|
81
88
|
end
|
82
89
|
|
83
|
-
|
84
|
-
# Returns whether a counter cache should be used for this association.
|
85
|
-
#
|
86
|
-
# The counter_cache option must be given on either the owner or inverse
|
87
|
-
# association, and the column must be present on the owner.
|
88
|
-
def has_cached_counter?(reflection = reflection())
|
89
|
-
if reflection.options[:counter_cache] || (inverse = inverse_which_updates_counter_cache(reflection)) && inverse.options[:counter_cache]
|
90
|
-
owner.attribute_present?(cached_counter_attribute_name(reflection))
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
def cached_counter_attribute_name(reflection = reflection())
|
95
|
-
if reflection.options[:counter_cache]
|
96
|
-
reflection.options[:counter_cache].to_s
|
97
|
-
else
|
98
|
-
"#{reflection.name}_count"
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
90
|
def update_counter(difference, reflection = reflection())
|
103
|
-
|
104
|
-
|
105
|
-
end
|
106
|
-
|
107
|
-
def update_counter_in_database(difference, reflection = reflection())
|
108
|
-
if has_cached_counter?(reflection)
|
109
|
-
counter = cached_counter_attribute_name(reflection)
|
110
|
-
owner.class.update_counters(owner.id, counter => difference)
|
91
|
+
if reflection.has_cached_counter?
|
92
|
+
owner.increment!(reflection.counter_cache_column, difference)
|
111
93
|
end
|
112
94
|
end
|
113
95
|
|
114
96
|
def update_counter_in_memory(difference, reflection = reflection())
|
115
|
-
if counter_must_be_updated_by_has_many?
|
116
|
-
counter =
|
117
|
-
owner
|
118
|
-
owner.send(:
|
97
|
+
if reflection.counter_must_be_updated_by_has_many?
|
98
|
+
counter = reflection.counter_cache_column
|
99
|
+
owner.increment(counter, difference)
|
100
|
+
owner.send(:clear_attribute_change, counter) # eww
|
119
101
|
end
|
120
102
|
end
|
121
103
|
|
122
|
-
# This shit is nasty. We need to avoid the following situation:
|
123
|
-
#
|
124
|
-
# * An associated record is deleted via record.destroy
|
125
|
-
# * Hence the callbacks run, and they find a belongs_to on the record with a
|
126
|
-
# :counter_cache options which points back at our owner. So they update the
|
127
|
-
# counter cache.
|
128
|
-
# * In which case, we must make sure to *not* update the counter cache, or else
|
129
|
-
# it will be decremented twice.
|
130
|
-
#
|
131
|
-
# Hence this method.
|
132
|
-
def inverse_which_updates_counter_cache(reflection = reflection())
|
133
|
-
counter_name = cached_counter_attribute_name(reflection)
|
134
|
-
inverse_which_updates_counter_named(counter_name, reflection)
|
135
|
-
end
|
136
|
-
alias inverse_updates_counter_cache? inverse_which_updates_counter_cache
|
137
|
-
|
138
|
-
def inverse_which_updates_counter_named(counter_name, reflection)
|
139
|
-
reflection.klass._reflections.values.find { |inverse_reflection|
|
140
|
-
inverse_reflection.belongs_to? &&
|
141
|
-
inverse_reflection.counter_cache_column == counter_name
|
142
|
-
}
|
143
|
-
end
|
144
|
-
alias inverse_updates_counter_named? inverse_which_updates_counter_named
|
145
|
-
|
146
|
-
def inverse_updates_counter_in_memory?(reflection)
|
147
|
-
inverse = inverse_which_updates_counter_cache(reflection)
|
148
|
-
inverse && inverse == reflection.inverse_of
|
149
|
-
end
|
150
|
-
|
151
|
-
def counter_must_be_updated_by_has_many?(reflection)
|
152
|
-
!inverse_updates_counter_in_memory?(reflection) && has_cached_counter?(reflection)
|
153
|
-
end
|
154
|
-
|
155
104
|
def delete_count(method, scope)
|
156
105
|
if method == :delete_all
|
157
106
|
scope.delete_all
|
@@ -169,7 +118,7 @@ module ActiveRecord
|
|
169
118
|
def delete_records(records, method)
|
170
119
|
if method == :destroy
|
171
120
|
records.each(&:destroy!)
|
172
|
-
update_counter(-records.length) unless inverse_updates_counter_cache?
|
121
|
+
update_counter(-records.length) unless reflection.inverse_updates_counter_cache?
|
173
122
|
else
|
174
123
|
scope = self.scope.where(reflection.klass.primary_key => records)
|
175
124
|
update_counter(-delete_count(method, scope))
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'active_support/core_ext/string/filters'
|
2
|
-
|
3
1
|
module ActiveRecord
|
4
2
|
# = Active Record Has Many Through Association
|
5
3
|
module Associations
|
@@ -13,21 +11,6 @@ module ActiveRecord
|
|
13
11
|
@through_association = nil
|
14
12
|
end
|
15
13
|
|
16
|
-
# Returns the size of the collection by executing a SELECT COUNT(*) query
|
17
|
-
# if the collection hasn't been loaded, and by calling collection.size if
|
18
|
-
# it has. If the collection will likely have a size greater than zero,
|
19
|
-
# and if fetching the collection will be needed afterwards, one less
|
20
|
-
# SELECT query will be generated by using #length instead.
|
21
|
-
def size
|
22
|
-
if has_cached_counter?
|
23
|
-
owner._read_attribute cached_counter_attribute_name(reflection)
|
24
|
-
elsif loaded?
|
25
|
-
target.size
|
26
|
-
else
|
27
|
-
super
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
14
|
def concat(*records)
|
32
15
|
unless owner.new_record?
|
33
16
|
records.flatten.each do |record|
|
@@ -55,25 +38,14 @@ module ActiveRecord
|
|
55
38
|
def insert_record(record, validate = true, raise = false)
|
56
39
|
ensure_not_nested
|
57
40
|
|
58
|
-
if
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
return unless record.save(:validate => validate)
|
63
|
-
end
|
41
|
+
if raise
|
42
|
+
record.save!(:validate => validate)
|
43
|
+
else
|
44
|
+
return unless record.save(:validate => validate)
|
64
45
|
end
|
65
46
|
|
66
47
|
save_through_record(record)
|
67
|
-
if has_cached_counter? && !through_reflection_updates_counter_cache?
|
68
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
69
|
-
Automatic updating of counter caches on through associations has been
|
70
|
-
deprecated, and will be removed in Rails 5. Instead, please set the
|
71
|
-
appropriate `counter_cache` options on the `has_many` and `belongs_to`
|
72
|
-
for your associations to #{through_reflection.name}.
|
73
|
-
MSG
|
74
48
|
|
75
|
-
update_counter_in_database(1)
|
76
|
-
end
|
77
49
|
record
|
78
50
|
end
|
79
51
|
|
@@ -94,11 +66,6 @@ module ActiveRecord
|
|
94
66
|
|
95
67
|
through_record = through_association.build(*options_for_through_record)
|
96
68
|
through_record.send("#{source_reflection.name}=", record)
|
97
|
-
|
98
|
-
if options[:source_type]
|
99
|
-
through_record.send("#{source_reflection.foreign_type}=", options[:source_type])
|
100
|
-
end
|
101
|
-
|
102
69
|
through_record
|
103
70
|
end
|
104
71
|
end
|
@@ -143,7 +110,7 @@ module ActiveRecord
|
|
143
110
|
def update_through_counter?(method)
|
144
111
|
case method
|
145
112
|
when :destroy
|
146
|
-
!inverse_updates_counter_cache?
|
113
|
+
!through_reflection.inverse_updates_counter_cache?
|
147
114
|
when :nullify
|
148
115
|
false
|
149
116
|
else
|
@@ -166,17 +133,15 @@ module ActiveRecord
|
|
166
133
|
if scope.klass.primary_key
|
167
134
|
count = scope.destroy_all.length
|
168
135
|
else
|
169
|
-
scope.each
|
170
|
-
record._run_destroy_callbacks
|
171
|
-
end
|
136
|
+
scope.each(&:_run_destroy_callbacks)
|
172
137
|
|
173
138
|
arel = scope.arel
|
174
139
|
|
175
|
-
stmt = Arel::DeleteManager.new
|
140
|
+
stmt = Arel::DeleteManager.new
|
176
141
|
stmt.from scope.klass.arel_table
|
177
142
|
stmt.wheres = arel.constraints
|
178
143
|
|
179
|
-
count = scope.klass.connection.delete(stmt, 'SQL', scope.
|
144
|
+
count = scope.klass.connection.delete(stmt, 'SQL', scope.bound_attributes)
|
180
145
|
end
|
181
146
|
when :nullify
|
182
147
|
count = scope.update_all(source_reflection.foreign_key => nil)
|
@@ -233,15 +198,6 @@ module ActiveRecord
|
|
233
198
|
def invertible_for?(record)
|
234
199
|
false
|
235
200
|
end
|
236
|
-
|
237
|
-
def has_cached_counter?(reflection = reflection())
|
238
|
-
owner.attribute_present?(cached_counter_attribute_name(reflection))
|
239
|
-
end
|
240
|
-
|
241
|
-
def through_reflection_updates_counter_cache?
|
242
|
-
counter_name = cached_counter_attribute_name
|
243
|
-
inverse_updates_counter_named?(counter_name, through_reflection)
|
244
|
-
end
|
245
201
|
end
|
246
202
|
end
|
247
203
|
end
|