activerecord 5.1.0 → 5.2.3
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 +596 -450
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -5
- data/examples/performance.rb +2 -0
- data/examples/simple.rb +2 -0
- data/lib/active_record.rb +11 -4
- data/lib/active_record/aggregations.rb +6 -5
- data/lib/active_record/association_relation.rb +7 -5
- data/lib/active_record/associations.rb +77 -85
- data/lib/active_record/associations/alias_tracker.rb +23 -32
- data/lib/active_record/associations/association.rb +49 -35
- data/lib/active_record/associations/association_scope.rb +55 -55
- data/lib/active_record/associations/belongs_to_association.rb +30 -11
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -8
- data/lib/active_record/associations/builder/association.rb +4 -7
- data/lib/active_record/associations/builder/belongs_to.rb +21 -8
- data/lib/active_record/associations/builder/collection_association.rb +1 -1
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -1
- data/lib/active_record/associations/builder/has_many.rb +2 -0
- data/lib/active_record/associations/builder/has_one.rb +2 -0
- data/lib/active_record/associations/builder/singular_association.rb +2 -0
- data/lib/active_record/associations/collection_association.rb +66 -53
- data/lib/active_record/associations/collection_proxy.rb +30 -73
- data/lib/active_record/associations/foreign_association.rb +2 -0
- data/lib/active_record/associations/has_many_association.rb +13 -2
- data/lib/active_record/associations/has_many_through_association.rb +37 -19
- data/lib/active_record/associations/has_one_association.rb +14 -1
- data/lib/active_record/associations/has_one_through_association.rb +13 -8
- data/lib/active_record/associations/join_dependency.rb +52 -96
- data/lib/active_record/associations/join_dependency/join_association.rb +22 -75
- data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
- data/lib/active_record/associations/join_dependency/join_part.rb +9 -9
- data/lib/active_record/associations/preloader.rb +17 -37
- data/lib/active_record/associations/preloader/association.rb +53 -92
- data/lib/active_record/associations/preloader/through_association.rb +72 -73
- data/lib/active_record/associations/singular_association.rb +14 -16
- data/lib/active_record/associations/through_association.rb +27 -12
- data/lib/active_record/attribute_assignment.rb +2 -5
- data/lib/active_record/attribute_decorators.rb +3 -2
- data/lib/active_record/attribute_methods.rb +65 -24
- data/lib/active_record/attribute_methods/before_type_cast.rb +2 -0
- data/lib/active_record/attribute_methods/dirty.rb +33 -216
- data/lib/active_record/attribute_methods/primary_key.rb +10 -13
- data/lib/active_record/attribute_methods/query.rb +2 -0
- data/lib/active_record/attribute_methods/read.rb +9 -3
- data/lib/active_record/attribute_methods/serialization.rb +23 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +6 -8
- data/lib/active_record/attribute_methods/write.rb +22 -19
- data/lib/active_record/attributes.rb +7 -6
- data/lib/active_record/autosave_association.rb +15 -13
- data/lib/active_record/base.rb +2 -0
- data/lib/active_record/callbacks.rb +12 -6
- data/lib/active_record/coders/json.rb +2 -0
- data/lib/active_record/coders/yaml_column.rb +2 -0
- data/lib/active_record/collection_cache_key.rb +15 -11
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +120 -39
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +7 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +192 -37
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +13 -2
- data/lib/active_record/connection_adapters/abstract/quoting.rb +15 -25
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +15 -6
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +65 -7
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +158 -87
- data/lib/active_record/connection_adapters/abstract/transaction.rb +66 -21
- data/lib/active_record/connection_adapters/abstract_adapter.rb +86 -98
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +126 -189
- data/lib/active_record/connection_adapters/column.rb +4 -2
- data/lib/active_record/connection_adapters/connection_specification.rb +17 -3
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +13 -2
- data/lib/active_record/connection_adapters/mysql/column.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +45 -15
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +9 -10
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +5 -3
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +7 -10
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +30 -23
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +106 -1
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -2
- data/lib/active_record/connection_adapters/postgresql/column.rb +30 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +6 -32
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +13 -1
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +8 -2
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +4 -2
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +22 -1
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +24 -11
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +20 -13
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +258 -129
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +75 -87
- data/lib/active_record/connection_adapters/schema_cache.rb +4 -2
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +24 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +6 -15
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +3 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +75 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +90 -96
- data/lib/active_record/connection_adapters/statement_pool.rb +2 -0
- data/lib/active_record/connection_handling.rb +4 -2
- data/lib/active_record/core.rb +41 -61
- data/lib/active_record/counter_cache.rb +20 -15
- data/lib/active_record/define_callbacks.rb +5 -3
- data/lib/active_record/dynamic_matchers.rb +9 -9
- data/lib/active_record/enum.rb +18 -13
- data/lib/active_record/errors.rb +60 -15
- data/lib/active_record/explain.rb +3 -1
- data/lib/active_record/explain_registry.rb +2 -0
- data/lib/active_record/explain_subscriber.rb +2 -0
- data/lib/active_record/fixture_set/file.rb +2 -0
- data/lib/active_record/fixtures.rb +67 -60
- data/lib/active_record/gem_version.rb +4 -2
- data/lib/active_record/inheritance.rb +49 -19
- data/lib/active_record/integration.rb +58 -19
- data/lib/active_record/internal_metadata.rb +2 -0
- data/lib/active_record/legacy_yaml_adapter.rb +3 -1
- data/lib/active_record/locking/optimistic.rb +30 -42
- data/lib/active_record/locking/pessimistic.rb +10 -7
- data/lib/active_record/log_subscriber.rb +46 -4
- data/lib/active_record/migration.rb +189 -139
- data/lib/active_record/migration/command_recorder.rb +11 -9
- data/lib/active_record/migration/compatibility.rb +81 -29
- data/lib/active_record/migration/join_table.rb +2 -0
- data/lib/active_record/model_schema.rb +74 -58
- data/lib/active_record/nested_attributes.rb +18 -6
- data/lib/active_record/no_touching.rb +3 -1
- data/lib/active_record/null_relation.rb +2 -0
- data/lib/active_record/persistence.rb +199 -54
- data/lib/active_record/query_cache.rb +8 -10
- data/lib/active_record/querying.rb +5 -3
- data/lib/active_record/railtie.rb +62 -6
- data/lib/active_record/railties/console_sandbox.rb +2 -0
- data/lib/active_record/railties/controller_runtime.rb +2 -0
- data/lib/active_record/railties/databases.rake +48 -38
- data/lib/active_record/readonly_attributes.rb +3 -2
- data/lib/active_record/reflection.rb +137 -207
- data/lib/active_record/relation.rb +132 -207
- data/lib/active_record/relation/batches.rb +32 -17
- data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
- data/lib/active_record/relation/calculations.rb +66 -25
- data/lib/active_record/relation/delegation.rb +45 -29
- data/lib/active_record/relation/finder_methods.rb +76 -85
- data/lib/active_record/relation/from_clause.rb +2 -8
- data/lib/active_record/relation/merger.rb +53 -23
- data/lib/active_record/relation/predicate_builder.rb +60 -79
- data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -7
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +12 -1
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +56 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +26 -9
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
- data/lib/active_record/relation/query_attribute.rb +28 -2
- data/lib/active_record/relation/query_methods.rb +135 -103
- data/lib/active_record/relation/record_fetch_warning.rb +2 -0
- data/lib/active_record/relation/spawn_methods.rb +4 -2
- data/lib/active_record/relation/where_clause.rb +65 -67
- data/lib/active_record/relation/where_clause_factory.rb +5 -48
- data/lib/active_record/result.rb +2 -0
- data/lib/active_record/runtime_registry.rb +2 -0
- data/lib/active_record/sanitization.rb +129 -121
- data/lib/active_record/schema.rb +4 -2
- data/lib/active_record/schema_dumper.rb +36 -26
- data/lib/active_record/schema_migration.rb +2 -0
- data/lib/active_record/scoping.rb +12 -10
- data/lib/active_record/scoping/default.rb +10 -7
- data/lib/active_record/scoping/named.rb +40 -12
- data/lib/active_record/secure_token.rb +2 -0
- data/lib/active_record/serialization.rb +2 -0
- data/lib/active_record/statement_cache.rb +22 -12
- data/lib/active_record/store.rb +3 -1
- data/lib/active_record/suppressor.rb +2 -0
- data/lib/active_record/table_metadata.rb +12 -3
- data/lib/active_record/tasks/database_tasks.rb +38 -26
- data/lib/active_record/tasks/mysql_database_tasks.rb +11 -50
- data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -3
- data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -3
- data/lib/active_record/timestamp.rb +13 -6
- data/lib/active_record/touch_later.rb +2 -0
- data/lib/active_record/transactions.rb +32 -27
- data/lib/active_record/translation.rb +2 -0
- data/lib/active_record/type.rb +4 -1
- data/lib/active_record/type/adapter_specific_registry.rb +2 -0
- data/lib/active_record/type/date.rb +2 -0
- data/lib/active_record/type/date_time.rb +2 -0
- data/lib/active_record/type/decimal_without_scale.rb +2 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +2 -0
- data/lib/active_record/type/internal/timezone.rb +2 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +6 -0
- data/lib/active_record/type/text.rb +2 -0
- data/lib/active_record/type/time.rb +2 -0
- data/lib/active_record/type/type_map.rb +2 -0
- data/lib/active_record/type/unsigned_integer.rb +2 -0
- data/lib/active_record/type_caster.rb +2 -0
- data/lib/active_record/type_caster/connection.rb +2 -0
- data/lib/active_record/type_caster/map.rb +3 -1
- data/lib/active_record/validations.rb +2 -0
- data/lib/active_record/validations/absence.rb +2 -0
- data/lib/active_record/validations/associated.rb +2 -0
- data/lib/active_record/validations/length.rb +2 -0
- data/lib/active_record/validations/presence.rb +2 -0
- data/lib/active_record/validations/uniqueness.rb +36 -6
- data/lib/active_record/version.rb +2 -0
- data/lib/rails/generators/active_record.rb +3 -1
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
- data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
- data/lib/rails/generators/active_record/migration.rb +2 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -1
- data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +0 -0
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +0 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +2 -23
- data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +0 -0
- data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
- metadata +24 -36
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -15
- data/lib/active_record/associations/preloader/collection_association.rb +0 -17
- data/lib/active_record/associations/preloader/has_many.rb +0 -15
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
- data/lib/active_record/associations/preloader/has_one.rb +0 -15
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -18
- data/lib/active_record/attribute.rb +0 -240
- data/lib/active_record/attribute/user_provided_default.rb +0 -30
- data/lib/active_record/attribute_mutation_tracker.rb +0 -113
- data/lib/active_record/attribute_set.rb +0 -113
- data/lib/active_record/attribute_set/builder.rb +0 -124
- data/lib/active_record/attribute_set/yaml_encoder.rb +0 -41
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -10
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -59
- data/lib/active_record/type/internal/abstract_json.rb +0 -33
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module Associations
|
3
5
|
# Association proxies in Active Record are middlemen between the object that
|
@@ -30,7 +32,10 @@ module ActiveRecord
|
|
30
32
|
class CollectionProxy < Relation
|
31
33
|
def initialize(klass, association) #:nodoc:
|
32
34
|
@association = association
|
33
|
-
super klass
|
35
|
+
super klass
|
36
|
+
|
37
|
+
extensions = association.extensions
|
38
|
+
extend(*extensions) if extensions.any?
|
34
39
|
end
|
35
40
|
|
36
41
|
def target
|
@@ -130,8 +135,9 @@ module ActiveRecord
|
|
130
135
|
# # #<Pet id: 2, name: "Spook", person_id: 1>,
|
131
136
|
# # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
|
132
137
|
# # ]
|
133
|
-
def find(*args
|
134
|
-
|
138
|
+
def find(*args)
|
139
|
+
return super if block_given?
|
140
|
+
@association.find(*args)
|
135
141
|
end
|
136
142
|
|
137
143
|
##
|
@@ -360,34 +366,6 @@ module ActiveRecord
|
|
360
366
|
@association.create!(attributes, &block)
|
361
367
|
end
|
362
368
|
|
363
|
-
# Add one or more records to the collection by setting their foreign keys
|
364
|
-
# to the association's primary key. Since #<< flattens its argument list and
|
365
|
-
# inserts each record, +push+ and #concat behave identically. Returns +self+
|
366
|
-
# so method calls may be chained.
|
367
|
-
#
|
368
|
-
# class Person < ActiveRecord::Base
|
369
|
-
# has_many :pets
|
370
|
-
# end
|
371
|
-
#
|
372
|
-
# person.pets.size # => 0
|
373
|
-
# person.pets.concat(Pet.new(name: 'Fancy-Fancy'))
|
374
|
-
# person.pets.concat(Pet.new(name: 'Spook'), Pet.new(name: 'Choo-Choo'))
|
375
|
-
# person.pets.size # => 3
|
376
|
-
#
|
377
|
-
# person.id # => 1
|
378
|
-
# person.pets
|
379
|
-
# # => [
|
380
|
-
# # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
|
381
|
-
# # #<Pet id: 2, name: "Spook", person_id: 1>,
|
382
|
-
# # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
|
383
|
-
# # ]
|
384
|
-
#
|
385
|
-
# person.pets.concat([Pet.new(name: 'Brain'), Pet.new(name: 'Benny')])
|
386
|
-
# person.pets.size # => 5
|
387
|
-
def concat(*records)
|
388
|
-
@association.concat(*records)
|
389
|
-
end
|
390
|
-
|
391
369
|
# Replaces this collection with +other_array+. This will perform a diff
|
392
370
|
# and delete/add only records that have changed.
|
393
371
|
#
|
@@ -494,7 +472,7 @@ module ActiveRecord
|
|
494
472
|
# Pet.find(1, 2, 3)
|
495
473
|
# # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 2, 3)
|
496
474
|
def delete_all(dependent = nil)
|
497
|
-
@association.delete_all(dependent)
|
475
|
+
@association.delete_all(dependent).tap { reset_scope }
|
498
476
|
end
|
499
477
|
|
500
478
|
# Deletes the records of the collection directly from the database
|
@@ -521,7 +499,7 @@ module ActiveRecord
|
|
521
499
|
#
|
522
500
|
# Pet.find(1) # => Couldn't find Pet with id=1
|
523
501
|
def destroy_all
|
524
|
-
@association.destroy_all
|
502
|
+
@association.destroy_all.tap { reset_scope }
|
525
503
|
end
|
526
504
|
|
527
505
|
# Deletes the +records+ supplied from the collection according to the strategy
|
@@ -640,7 +618,7 @@ module ActiveRecord
|
|
640
618
|
# # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
|
641
619
|
# # ]
|
642
620
|
def delete(*records)
|
643
|
-
@association.delete(*records)
|
621
|
+
@association.delete(*records).tap { reset_scope }
|
644
622
|
end
|
645
623
|
|
646
624
|
# Destroys the +records+ supplied and removes them from the collection.
|
@@ -712,7 +690,7 @@ module ActiveRecord
|
|
712
690
|
#
|
713
691
|
# Pet.find(4, 5, 6) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (4, 5, 6)
|
714
692
|
def destroy(*records)
|
715
|
-
@association.destroy(*records)
|
693
|
+
@association.destroy(*records).tap { reset_scope }
|
716
694
|
end
|
717
695
|
|
718
696
|
##
|
@@ -743,10 +721,6 @@ module ActiveRecord
|
|
743
721
|
# # ]
|
744
722
|
|
745
723
|
#--
|
746
|
-
def uniq
|
747
|
-
load_target.uniq
|
748
|
-
end
|
749
|
-
|
750
724
|
def calculate(operation, column_name)
|
751
725
|
null_scope? ? scope.calculate(operation, column_name) : super
|
752
726
|
end
|
@@ -986,6 +960,12 @@ module ActiveRecord
|
|
986
960
|
load_target == other
|
987
961
|
end
|
988
962
|
|
963
|
+
##
|
964
|
+
# :method: to_ary
|
965
|
+
#
|
966
|
+
# :call-seq:
|
967
|
+
# to_ary()
|
968
|
+
#
|
989
969
|
# Returns a new array of objects from the collection. If the collection
|
990
970
|
# hasn't been loaded, it fetches the records from the database.
|
991
971
|
#
|
@@ -1019,18 +999,15 @@ module ActiveRecord
|
|
1019
999
|
# # #<Pet id: 5, name: "Brain", person_id: 1>,
|
1020
1000
|
# # #<Pet id: 6, name: "Boss", person_id: 1>
|
1021
1001
|
# # ]
|
1022
|
-
def to_ary
|
1023
|
-
load_target.dup
|
1024
|
-
end
|
1025
|
-
alias_method :to_a, :to_ary
|
1026
1002
|
|
1027
1003
|
def records # :nodoc:
|
1028
1004
|
load_target
|
1029
1005
|
end
|
1030
1006
|
|
1031
1007
|
# Adds one or more +records+ to the collection by setting their foreign keys
|
1032
|
-
# to the association's primary key.
|
1033
|
-
#
|
1008
|
+
# to the association's primary key. Since +<<+ flattens its argument list and
|
1009
|
+
# inserts each record, +push+ and +concat+ behave identically. Returns +self+
|
1010
|
+
# so several appends may be chained together.
|
1034
1011
|
#
|
1035
1012
|
# class Person < ActiveRecord::Base
|
1036
1013
|
# has_many :pets
|
@@ -1053,6 +1030,7 @@ module ActiveRecord
|
|
1053
1030
|
end
|
1054
1031
|
alias_method :push, :<<
|
1055
1032
|
alias_method :append, :<<
|
1033
|
+
alias_method :concat, :<<
|
1056
1034
|
|
1057
1035
|
def prepend(*args)
|
1058
1036
|
raise NoMethodError, "prepend on association is not defined. Please use <<, push or append"
|
@@ -1070,7 +1048,6 @@ module ActiveRecord
|
|
1070
1048
|
end
|
1071
1049
|
|
1072
1050
|
# Reloads the collection from the database. Returns +self+.
|
1073
|
-
# Equivalent to <tt>collection(true)</tt>.
|
1074
1051
|
#
|
1075
1052
|
# class Person < ActiveRecord::Base
|
1076
1053
|
# has_many :pets
|
@@ -1084,13 +1061,9 @@ module ActiveRecord
|
|
1084
1061
|
#
|
1085
1062
|
# person.pets.reload # fetches pets from the database
|
1086
1063
|
# # => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]
|
1087
|
-
#
|
1088
|
-
# person.pets(true) # fetches pets from the database
|
1089
|
-
# # => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]
|
1090
1064
|
def reload
|
1091
|
-
@scope = nil
|
1092
1065
|
proxy_association.reload
|
1093
|
-
|
1066
|
+
reset_scope
|
1094
1067
|
end
|
1095
1068
|
|
1096
1069
|
# Unloads the association. Returns +self+.
|
@@ -1110,9 +1083,14 @@ module ActiveRecord
|
|
1110
1083
|
# person.pets # fetches pets from the database
|
1111
1084
|
# # => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]
|
1112
1085
|
def reset
|
1113
|
-
@scope = nil
|
1114
1086
|
proxy_association.reset
|
1115
1087
|
proxy_association.reset_scope
|
1088
|
+
reset_scope
|
1089
|
+
end
|
1090
|
+
|
1091
|
+
def reset_scope # :nodoc:
|
1092
|
+
@offsets = {}
|
1093
|
+
@scope = nil
|
1116
1094
|
self
|
1117
1095
|
end
|
1118
1096
|
|
@@ -1125,19 +1103,6 @@ module ActiveRecord
|
|
1125
1103
|
|
1126
1104
|
delegate(*delegate_methods, to: :scope)
|
1127
1105
|
|
1128
|
-
module DelegateExtending # :nodoc:
|
1129
|
-
private
|
1130
|
-
def method_missing(method, *args, &block)
|
1131
|
-
extending_values = association_scope.extending_values
|
1132
|
-
if extending_values.any? && (extending_values - self.class.included_modules).any?
|
1133
|
-
self.class.include(*extending_values)
|
1134
|
-
public_send(method, *args, &block)
|
1135
|
-
else
|
1136
|
-
super
|
1137
|
-
end
|
1138
|
-
end
|
1139
|
-
end
|
1140
|
-
|
1141
1106
|
private
|
1142
1107
|
|
1143
1108
|
def find_nth_with_limit(index, limit)
|
@@ -1158,17 +1123,9 @@ module ActiveRecord
|
|
1158
1123
|
@association.find_from_target?
|
1159
1124
|
end
|
1160
1125
|
|
1161
|
-
def association_scope
|
1162
|
-
@association.association_scope
|
1163
|
-
end
|
1164
|
-
|
1165
1126
|
def exec_queries
|
1166
1127
|
load_target
|
1167
1128
|
end
|
1168
|
-
|
1169
|
-
def respond_to_missing?(method, _)
|
1170
|
-
association_scope.respond_to?(method) || super
|
1171
|
-
end
|
1172
1129
|
end
|
1173
1130
|
end
|
1174
1131
|
end
|
@@ -1,6 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
|
-
# = Active Record Has Many Association
|
3
4
|
module Associations
|
5
|
+
# = Active Record Has Many Association
|
4
6
|
# This is the proxy that handles a has many association.
|
5
7
|
#
|
6
8
|
# If the association has a <tt>:through</tt> option further specialization
|
@@ -61,7 +63,7 @@ module ActiveRecord
|
|
61
63
|
count = if reflection.has_cached_counter?
|
62
64
|
owner._read_attribute(reflection.counter_cache_column).to_i
|
63
65
|
else
|
64
|
-
scope.count
|
66
|
+
scope.count(:all)
|
65
67
|
end
|
66
68
|
|
67
69
|
# If there's nothing in the database and @target has no new records
|
@@ -97,6 +99,7 @@ module ActiveRecord
|
|
97
99
|
def delete_or_nullify_all_records(method)
|
98
100
|
count = delete_count(method, scope)
|
99
101
|
update_counter(-count)
|
102
|
+
count
|
100
103
|
end
|
101
104
|
|
102
105
|
# Deletes the records according to the <tt>:dependent</tt> option.
|
@@ -128,6 +131,14 @@ module ActiveRecord
|
|
128
131
|
end
|
129
132
|
saved_successfully
|
130
133
|
end
|
134
|
+
|
135
|
+
def difference(a, b)
|
136
|
+
a - b
|
137
|
+
end
|
138
|
+
|
139
|
+
def intersection(a, b)
|
140
|
+
a & b
|
141
|
+
end
|
131
142
|
end
|
132
143
|
end
|
133
144
|
end
|
@@ -1,14 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
|
-
# = Active Record Has Many Through Association
|
3
4
|
module Associations
|
5
|
+
# = Active Record Has Many Through Association
|
4
6
|
class HasManyThroughAssociation < HasManyAssociation #:nodoc:
|
5
7
|
include ThroughAssociation
|
6
8
|
|
7
9
|
def initialize(owner, reflection)
|
8
10
|
super
|
9
|
-
|
10
|
-
@through_records = {}
|
11
|
-
@through_association = nil
|
11
|
+
@through_records = {}
|
12
12
|
end
|
13
13
|
|
14
14
|
def concat(*records)
|
@@ -48,11 +48,6 @@ module ActiveRecord
|
|
48
48
|
end
|
49
49
|
|
50
50
|
private
|
51
|
-
|
52
|
-
def through_association
|
53
|
-
@through_association ||= owner.association(through_reflection.name)
|
54
|
-
end
|
55
|
-
|
56
51
|
# The through record (built with build_record) is temporarily cached
|
57
52
|
# so that it may be reused if insert_record is subsequently called.
|
58
53
|
#
|
@@ -95,7 +90,7 @@ module ActiveRecord
|
|
95
90
|
def build_record(attributes)
|
96
91
|
ensure_not_nested
|
97
92
|
|
98
|
-
record = super
|
93
|
+
record = super
|
99
94
|
|
100
95
|
inverse = source_reflection.inverse_of
|
101
96
|
if inverse
|
@@ -109,6 +104,11 @@ module ActiveRecord
|
|
109
104
|
record
|
110
105
|
end
|
111
106
|
|
107
|
+
def remove_records(existing_records, records, method)
|
108
|
+
super
|
109
|
+
delete_through_records(records)
|
110
|
+
end
|
111
|
+
|
112
112
|
def target_reflection_has_associated_record?
|
113
113
|
!(through_reflection.belongs_to? && owner[through_reflection.foreign_key].blank?)
|
114
114
|
end
|
@@ -133,21 +133,15 @@ module ActiveRecord
|
|
133
133
|
|
134
134
|
scope = through_association.scope
|
135
135
|
scope.where! construct_join_attributes(*records)
|
136
|
+
scope = scope.where(through_scope_attributes)
|
136
137
|
|
137
138
|
case method
|
138
139
|
when :destroy
|
139
140
|
if scope.klass.primary_key
|
140
|
-
count = scope.destroy_all.
|
141
|
+
count = scope.destroy_all.count(&:destroyed?)
|
141
142
|
else
|
142
143
|
scope.each(&:_run_destroy_callbacks)
|
143
|
-
|
144
|
-
arel = scope.arel
|
145
|
-
|
146
|
-
stmt = Arel::DeleteManager.new
|
147
|
-
stmt.from scope.klass.arel_table
|
148
|
-
stmt.wheres = arel.constraints
|
149
|
-
|
150
|
-
count = scope.klass.connection.delete(stmt, "SQL", scope.bound_attributes)
|
144
|
+
count = scope.delete_all
|
151
145
|
end
|
152
146
|
when :nullify
|
153
147
|
count = scope.update_all(source_reflection.foreign_key => nil)
|
@@ -167,6 +161,30 @@ module ActiveRecord
|
|
167
161
|
else
|
168
162
|
update_counter(-count)
|
169
163
|
end
|
164
|
+
|
165
|
+
count
|
166
|
+
end
|
167
|
+
|
168
|
+
def difference(a, b)
|
169
|
+
distribution = distribution(b)
|
170
|
+
|
171
|
+
a.reject { |record| mark_occurrence(distribution, record) }
|
172
|
+
end
|
173
|
+
|
174
|
+
def intersection(a, b)
|
175
|
+
distribution = distribution(b)
|
176
|
+
|
177
|
+
a.select { |record| mark_occurrence(distribution, record) }
|
178
|
+
end
|
179
|
+
|
180
|
+
def mark_occurrence(distribution, record)
|
181
|
+
distribution[record] > 0 && distribution[record] -= 1
|
182
|
+
end
|
183
|
+
|
184
|
+
def distribution(array)
|
185
|
+
array.each_with_object(Hash.new(0)) do |record, distribution|
|
186
|
+
distribution[record] += 1
|
187
|
+
end
|
170
188
|
end
|
171
189
|
|
172
190
|
def through_records_for(record)
|
@@ -1,6 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
|
-
# = Active Record Has One Association
|
3
4
|
module Associations
|
5
|
+
# = Active Record Has One Association
|
4
6
|
class HasOneAssociation < SingularAssociation #:nodoc:
|
5
7
|
include ForeignAssociation
|
6
8
|
|
@@ -56,7 +58,9 @@ module ActiveRecord
|
|
56
58
|
when :delete
|
57
59
|
target.delete
|
58
60
|
when :destroy
|
61
|
+
target.destroyed_by_association = reflection
|
59
62
|
target.destroy
|
63
|
+
throw(:abort) unless target.destroyed?
|
60
64
|
when :nullify
|
61
65
|
target.update_columns(reflection.foreign_key => nil) if target.persisted?
|
62
66
|
end
|
@@ -78,6 +82,7 @@ module ActiveRecord
|
|
78
82
|
when :delete
|
79
83
|
target.delete
|
80
84
|
when :destroy
|
85
|
+
target.destroyed_by_association = reflection
|
81
86
|
target.destroy
|
82
87
|
else
|
83
88
|
nullify_owner_attributes(target)
|
@@ -102,6 +107,14 @@ module ActiveRecord
|
|
102
107
|
yield
|
103
108
|
end
|
104
109
|
end
|
110
|
+
|
111
|
+
def _create_record(attributes, raise_error = false, &block)
|
112
|
+
unless owner.persisted?
|
113
|
+
raise ActiveRecord::RecordNotSaved, "You cannot call create unless the parent is saved"
|
114
|
+
end
|
115
|
+
|
116
|
+
super
|
117
|
+
end
|
105
118
|
end
|
106
119
|
end
|
107
120
|
end
|
@@ -1,20 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
|
-
# = Active Record Has One Through Association
|
3
4
|
module Associations
|
5
|
+
# = Active Record Has One Through Association
|
4
6
|
class HasOneThroughAssociation < HasOneAssociation #:nodoc:
|
5
7
|
include ThroughAssociation
|
6
8
|
|
7
|
-
def replace(record)
|
8
|
-
create_through_record(record)
|
9
|
+
def replace(record, save = true)
|
10
|
+
create_through_record(record, save)
|
9
11
|
self.target = record
|
10
12
|
end
|
11
13
|
|
12
14
|
private
|
13
|
-
|
14
|
-
def create_through_record(record)
|
15
|
+
def create_through_record(record, save)
|
15
16
|
ensure_not_nested
|
16
17
|
|
17
|
-
through_proxy =
|
18
|
+
through_proxy = through_association
|
18
19
|
through_record = through_proxy.load_target
|
19
20
|
|
20
21
|
if through_record && !record
|
@@ -27,8 +28,12 @@ module ActiveRecord
|
|
27
28
|
end
|
28
29
|
|
29
30
|
if through_record
|
30
|
-
through_record.
|
31
|
-
|
31
|
+
if through_record.new_record?
|
32
|
+
through_record.assign_attributes(attributes)
|
33
|
+
else
|
34
|
+
through_record.update(attributes)
|
35
|
+
end
|
36
|
+
elsif owner.new_record? || !save
|
32
37
|
through_proxy.build(attributes)
|
33
38
|
else
|
34
39
|
through_proxy.create(attributes)
|