activerecord 4.2.9 → 6.1.4.1
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 +964 -1382
- data/MIT-LICENSE +4 -2
- data/README.rdoc +15 -14
- data/examples/performance.rb +33 -32
- data/examples/simple.rb +5 -4
- data/lib/active_record/aggregations.rb +266 -251
- data/lib/active_record/association_relation.rb +40 -15
- data/lib/active_record/associations/alias_tracker.rb +40 -43
- data/lib/active_record/associations/association.rb +162 -69
- data/lib/active_record/associations/association_scope.rb +105 -130
- data/lib/active_record/associations/belongs_to_association.rb +83 -65
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -12
- data/lib/active_record/associations/builder/association.rb +57 -43
- data/lib/active_record/associations/builder/belongs_to.rb +74 -57
- data/lib/active_record/associations/builder/collection_association.rb +15 -37
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +49 -66
- data/lib/active_record/associations/builder/has_many.rb +13 -5
- data/lib/active_record/associations/builder/has_one.rb +44 -6
- data/lib/active_record/associations/builder/singular_association.rb +16 -10
- data/lib/active_record/associations/collection_association.rb +148 -287
- data/lib/active_record/associations/collection_proxy.rb +252 -150
- data/lib/active_record/associations/foreign_association.rb +23 -1
- data/lib/active_record/associations/has_many_association.rb +56 -98
- data/lib/active_record/associations/has_many_through_association.rb +68 -89
- data/lib/active_record/associations/has_one_association.rb +73 -47
- data/lib/active_record/associations/has_one_through_association.rb +20 -11
- data/lib/active_record/associations/join_dependency/join_association.rb +54 -81
- data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
- data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
- data/lib/active_record/associations/join_dependency.rb +174 -169
- data/lib/active_record/associations/preloader/association.rb +108 -115
- data/lib/active_record/associations/preloader/through_association.rb +85 -65
- data/lib/active_record/associations/preloader.rb +97 -94
- data/lib/active_record/associations/singular_association.rb +18 -39
- data/lib/active_record/associations/through_association.rb +39 -19
- data/lib/active_record/associations.rb +1845 -1598
- data/lib/active_record/attribute_assignment.rb +59 -185
- data/lib/active_record/attribute_methods/before_type_cast.rb +18 -10
- data/lib/active_record/attribute_methods/dirty.rb +168 -148
- data/lib/active_record/attribute_methods/primary_key.rb +93 -83
- data/lib/active_record/attribute_methods/query.rb +8 -10
- data/lib/active_record/attribute_methods/read.rb +19 -79
- data/lib/active_record/attribute_methods/serialization.rb +49 -24
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +55 -36
- data/lib/active_record/attribute_methods/write.rb +24 -55
- data/lib/active_record/attribute_methods.rb +149 -154
- data/lib/active_record/attributes.rb +234 -78
- data/lib/active_record/autosave_association.rb +133 -60
- data/lib/active_record/base.rb +46 -46
- data/lib/active_record/callbacks.rb +234 -79
- data/lib/active_record/coders/json.rb +3 -1
- data/lib/active_record/coders/yaml_column.rb +34 -13
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +887 -323
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -41
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +292 -124
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +78 -24
- data/lib/active_record/connection_adapters/abstract/quoting.rb +177 -60
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +8 -6
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +157 -93
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +473 -255
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +869 -286
- data/lib/active_record/connection_adapters/abstract/transaction.rb +257 -91
- data/lib/active_record/connection_adapters/abstract_adapter.rb +483 -230
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +557 -640
- data/lib/active_record/connection_adapters/column.rb +67 -40
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +194 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +71 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +96 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +97 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +103 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +91 -0
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +268 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +40 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +80 -192
- data/lib/active_record/connection_adapters/pool_config.rb +73 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +44 -11
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +75 -160
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +49 -58
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +9 -8
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +4 -2
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +8 -6
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +14 -19
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -4
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -20
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
- data/lib/active_record/connection_adapters/postgresql/oid/{infinity.rb → oid.rb} +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +32 -11
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +70 -34
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -5
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +18 -4
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid.rb +25 -25
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +145 -48
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +80 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +178 -108
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +496 -298
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +11 -8
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +588 -375
- data/lib/active_record/connection_adapters/schema_cache.rb +167 -29
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +45 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +144 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +102 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +21 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +170 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +322 -373
- data/lib/active_record/connection_adapters/statement_pool.rb +33 -13
- data/lib/active_record/connection_adapters.rb +52 -0
- data/lib/active_record/connection_handling.rb +314 -41
- data/lib/active_record/core.rb +458 -241
- data/lib/active_record/counter_cache.rb +70 -49
- data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
- data/lib/active_record/database_configurations/database_config.rb +80 -0
- data/lib/active_record/database_configurations/hash_config.rb +96 -0
- data/lib/active_record/database_configurations/url_config.rb +53 -0
- data/lib/active_record/database_configurations.rb +272 -0
- data/lib/active_record/delegated_type.rb +209 -0
- data/lib/active_record/destroy_association_async_job.rb +36 -0
- data/lib/active_record/dynamic_matchers.rb +87 -106
- data/lib/active_record/enum.rb +211 -92
- data/lib/active_record/errors.rb +224 -54
- data/lib/active_record/explain.rb +27 -11
- data/lib/active_record/explain_registry.rb +4 -2
- data/lib/active_record/explain_subscriber.rb +10 -5
- data/lib/active_record/fixture_set/file.rb +33 -14
- data/lib/active_record/fixture_set/model_metadata.rb +32 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +152 -0
- data/lib/active_record/fixture_set/table_rows.rb +46 -0
- data/lib/active_record/fixtures.rb +275 -500
- data/lib/active_record/gem_version.rb +6 -4
- data/lib/active_record/inheritance.rb +175 -110
- data/lib/active_record/insert_all.rb +212 -0
- data/lib/active_record/integration.rb +121 -29
- data/lib/active_record/internal_metadata.rb +62 -0
- data/lib/active_record/legacy_yaml_adapter.rb +27 -5
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +98 -92
- data/lib/active_record/locking/pessimistic.rb +22 -6
- data/lib/active_record/log_subscriber.rb +93 -31
- data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector.rb +77 -0
- data/lib/active_record/migration/command_recorder.rb +185 -90
- data/lib/active_record/migration/compatibility.rb +295 -0
- data/lib/active_record/migration/join_table.rb +8 -7
- data/lib/active_record/migration.rb +673 -325
- data/lib/active_record/model_schema.rb +418 -113
- data/lib/active_record/nested_attributes.rb +263 -224
- data/lib/active_record/no_touching.rb +15 -2
- data/lib/active_record/null_relation.rb +24 -38
- data/lib/active_record/persistence.rb +572 -136
- data/lib/active_record/query_cache.rb +29 -23
- data/lib/active_record/querying.rb +50 -31
- data/lib/active_record/railtie.rb +170 -51
- data/lib/active_record/railties/console_sandbox.rb +3 -3
- data/lib/active_record/railties/controller_runtime.rb +34 -33
- data/lib/active_record/railties/databases.rake +523 -199
- data/lib/active_record/readonly_attributes.rb +9 -4
- data/lib/active_record/reflection.rb +454 -291
- data/lib/active_record/relation/batches/batch_enumerator.rb +85 -0
- data/lib/active_record/relation/batches.rb +217 -59
- data/lib/active_record/relation/calculations.rb +324 -249
- data/lib/active_record/relation/delegation.rb +76 -84
- data/lib/active_record/relation/finder_methods.rb +316 -242
- data/lib/active_record/relation/from_clause.rb +30 -0
- data/lib/active_record/relation/merger.rb +95 -103
- data/lib/active_record/relation/predicate_builder/array_handler.rb +26 -26
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +57 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
- data/lib/active_record/relation/predicate_builder.rb +136 -122
- data/lib/active_record/relation/query_attribute.rb +50 -0
- data/lib/active_record/relation/query_methods.rb +757 -413
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +18 -20
- data/lib/active_record/relation/where_clause.rb +239 -0
- data/lib/active_record/relation.rb +554 -343
- data/lib/active_record/result.rb +91 -47
- data/lib/active_record/runtime_registry.rb +6 -4
- data/lib/active_record/sanitization.rb +134 -122
- data/lib/active_record/schema.rb +21 -24
- data/lib/active_record/schema_dumper.rb +141 -92
- data/lib/active_record/schema_migration.rb +24 -23
- data/lib/active_record/scoping/default.rb +96 -83
- data/lib/active_record/scoping/named.rb +78 -36
- data/lib/active_record/scoping.rb +45 -27
- data/lib/active_record/secure_token.rb +48 -0
- data/lib/active_record/serialization.rb +8 -6
- data/lib/active_record/signed_id.rb +116 -0
- data/lib/active_record/statement_cache.rb +89 -36
- data/lib/active_record/store.rb +128 -43
- data/lib/active_record/suppressor.rb +61 -0
- data/lib/active_record/table_metadata.rb +81 -0
- data/lib/active_record/tasks/database_tasks.rb +364 -130
- data/lib/active_record/tasks/mysql_database_tasks.rb +67 -113
- data/lib/active_record/tasks/postgresql_database_tasks.rb +86 -49
- data/lib/active_record/tasks/sqlite_database_tasks.rb +44 -19
- data/lib/active_record/test_databases.rb +24 -0
- data/lib/active_record/test_fixtures.rb +287 -0
- data/lib/active_record/timestamp.rb +86 -43
- data/lib/active_record/touch_later.rb +65 -0
- data/lib/active_record/transactions.rb +182 -163
- data/lib/active_record/translation.rb +3 -1
- data/lib/active_record/type/adapter_specific_registry.rb +126 -0
- data/lib/active_record/type/date.rb +4 -45
- data/lib/active_record/type/date_time.rb +4 -49
- data/lib/active_record/type/decimal_without_scale.rb +6 -2
- data/lib/active_record/type/hash_lookup_type_map.rb +5 -4
- data/lib/active_record/type/internal/timezone.rb +17 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +27 -15
- data/lib/active_record/type/text.rb +2 -2
- data/lib/active_record/type/time.rb +21 -16
- data/lib/active_record/type/type_map.rb +16 -19
- data/lib/active_record/type/unsigned_integer.rb +9 -8
- data/lib/active_record/type.rb +84 -23
- data/lib/active_record/type_caster/connection.rb +33 -0
- data/lib/active_record/type_caster/map.rb +23 -0
- data/lib/active_record/type_caster.rb +9 -0
- data/lib/active_record/validations/absence.rb +25 -0
- data/lib/active_record/validations/associated.rb +12 -4
- data/lib/active_record/validations/length.rb +26 -0
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/presence.rb +14 -13
- data/lib/active_record/validations/uniqueness.rb +63 -56
- data/lib/active_record/validations.rb +39 -35
- data/lib/active_record/version.rb +3 -1
- data/lib/active_record.rb +42 -29
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +41 -0
- data/lib/arel/collectors/bind.rb +29 -0
- data/lib/arel/collectors/composite.rb +39 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +27 -0
- data/lib/arel/collectors/substitute_binds.rb +35 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/insert_manager.rb +49 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +126 -0
- data/lib/arel/nodes/bind_param.rb +44 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +62 -0
- data/lib/arel/nodes/comment.rb +29 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +45 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +15 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +11 -0
- data/lib/arel/nodes/homogeneous_in.rb +76 -0
- data/lib/arel/nodes/in.rb +15 -0
- data/lib/arel/nodes/infix_operation.rb +92 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +51 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/ordering.rb +27 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +67 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +19 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +31 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +44 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +41 -0
- data/lib/arel/nodes/values_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/nodes.rb +70 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +250 -0
- data/lib/arel/select_manager.rb +270 -0
- data/lib/arel/table.rb +118 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors/dot.rb +308 -0
- data/lib/arel/visitors/mysql.rb +93 -0
- data/lib/arel/visitors/postgresql.rb +120 -0
- data/lib/arel/visitors/sqlite.rb +38 -0
- data/lib/arel/visitors/to_sql.rb +899 -0
- data/lib/arel/visitors/visitor.rb +45 -0
- data/lib/arel/visitors.rb +13 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +54 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +43 -37
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +26 -0
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +13 -4
- data/lib/rails/generators/active_record/migration.rb +35 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +55 -22
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
- data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
- data/lib/rails/generators/active_record.rb +7 -5
- metadata +172 -65
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
- data/lib/active_record/associations/preloader/collection_association.rb +0 -24
- data/lib/active_record/associations/preloader/has_many.rb +0 -17
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
- data/lib/active_record/associations/preloader/has_one.rb +0 -23
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -21
- data/lib/active_record/attribute.rb +0 -163
- data/lib/active_record/attribute_decorators.rb +0 -66
- data/lib/active_record/attribute_set/builder.rb +0 -106
- data/lib/active_record/attribute_set.rb +0 -81
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -275
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
- data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
- data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- 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/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/time_value.rb +0 -38
- data/lib/active_record/type/value.rb +0 -110
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -19
- data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
@@ -1,10 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module Associations
|
3
|
-
#
|
4
|
-
#
|
5
|
-
# object, known as the <tt>@target</tt>. The kind of association any proxy is
|
6
|
-
# about is available in <tt>@reflection</tt>. That's an instance of the class
|
7
|
-
# ActiveRecord::Reflection::AssociationReflection.
|
5
|
+
# Collection proxies in Active Record are middlemen between an
|
6
|
+
# <tt>association</tt>, and its <tt>target</tt> result set.
|
8
7
|
#
|
9
8
|
# For example, given
|
10
9
|
#
|
@@ -14,27 +13,26 @@ module ActiveRecord
|
|
14
13
|
#
|
15
14
|
# blog = Blog.first
|
16
15
|
#
|
17
|
-
#
|
18
|
-
# <tt
|
19
|
-
#
|
16
|
+
# The collection proxy returned by <tt>blog.posts</tt> is built from a
|
17
|
+
# <tt>:has_many</tt> <tt>association</tt>, and delegates to a collection
|
18
|
+
# of posts as the <tt>target</tt>.
|
20
19
|
#
|
21
|
-
# This class delegates unknown methods to <tt
|
22
|
-
#
|
20
|
+
# This class delegates unknown methods to the <tt>association</tt>'s
|
21
|
+
# relation class via a delegate cache.
|
23
22
|
#
|
24
|
-
# The <tt
|
23
|
+
# The <tt>target</tt> result set is not loaded until needed. For example,
|
25
24
|
#
|
26
25
|
# blog.posts.count
|
27
26
|
#
|
28
27
|
# is computed directly through SQL and does not trigger by itself the
|
29
28
|
# instantiation of the actual post records.
|
30
29
|
class CollectionProxy < Relation
|
31
|
-
|
32
|
-
delegate :find_nth, to: :scope
|
33
|
-
|
34
|
-
def initialize(klass, association) #:nodoc:
|
30
|
+
def initialize(klass, association, **) #:nodoc:
|
35
31
|
@association = association
|
36
|
-
super klass
|
37
|
-
|
32
|
+
super klass
|
33
|
+
|
34
|
+
extensions = association.extensions
|
35
|
+
extend(*extensions) if extensions.any?
|
38
36
|
end
|
39
37
|
|
40
38
|
def target
|
@@ -53,7 +51,14 @@ module ActiveRecord
|
|
53
51
|
def loaded?
|
54
52
|
@association.loaded?
|
55
53
|
end
|
54
|
+
alias :loaded :loaded?
|
56
55
|
|
56
|
+
##
|
57
|
+
# :method: select
|
58
|
+
#
|
59
|
+
# :call-seq:
|
60
|
+
# select(*fields, &block)
|
61
|
+
#
|
57
62
|
# Works in two ways.
|
58
63
|
#
|
59
64
|
# *First:* Specify a subset of fields to be selected from the result set.
|
@@ -76,7 +81,7 @@ module ActiveRecord
|
|
76
81
|
# # #<Pet id: nil, name: "Choo-Choo">
|
77
82
|
# # ]
|
78
83
|
#
|
79
|
-
# person.pets.select(:id, :name
|
84
|
+
# person.pets.select(:id, :name)
|
80
85
|
# # => [
|
81
86
|
# # #<Pet id: 1, name: "Fancy-Fancy">,
|
82
87
|
# # #<Pet id: 2, name: "Spook">,
|
@@ -96,23 +101,14 @@ module ActiveRecord
|
|
96
101
|
# converting them into an array and iterating through them using
|
97
102
|
# Array#select.
|
98
103
|
#
|
99
|
-
# person.pets.select { |pet| pet.name
|
104
|
+
# person.pets.select { |pet| /oo/.match?(pet.name) }
|
100
105
|
# # => [
|
101
106
|
# # #<Pet id: 2, name: "Spook", person_id: 1>,
|
102
107
|
# # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
|
103
108
|
# # ]
|
104
|
-
#
|
105
|
-
# person.pets.select(:name) { |pet| pet.name =~ /oo/ }
|
106
|
-
# # => [
|
107
|
-
# # #<Pet id: 2, name: "Spook">,
|
108
|
-
# # #<Pet id: 3, name: "Choo-Choo">
|
109
|
-
# # ]
|
110
|
-
def select(*fields, &block)
|
111
|
-
@association.select(*fields, &block)
|
112
|
-
end
|
113
109
|
|
114
110
|
# Finds an object in the collection responding to the +id+. Uses the same
|
115
|
-
# rules as
|
111
|
+
# rules as ActiveRecord::Base.find. Returns ActiveRecord::RecordNotFound
|
116
112
|
# error if the object cannot be found.
|
117
113
|
#
|
118
114
|
# class Person < ActiveRecord::Base
|
@@ -127,7 +123,7 @@ module ActiveRecord
|
|
127
123
|
# # ]
|
128
124
|
#
|
129
125
|
# 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
|
126
|
+
# person.pets.find(4) # => ActiveRecord::RecordNotFound: Couldn't find Pet with 'id'=4
|
131
127
|
#
|
132
128
|
# person.pets.find(2) { |pet| pet.name.downcase! }
|
133
129
|
# # => #<Pet id: 2, name: "fancy-fancy", person_id: 1>
|
@@ -137,10 +133,17 @@ module ActiveRecord
|
|
137
133
|
# # #<Pet id: 2, name: "Spook", person_id: 1>,
|
138
134
|
# # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
|
139
135
|
# # ]
|
140
|
-
def find(*args
|
141
|
-
|
136
|
+
def find(*args)
|
137
|
+
return super if block_given?
|
138
|
+
@association.find(*args)
|
142
139
|
end
|
143
140
|
|
141
|
+
##
|
142
|
+
# :method: first
|
143
|
+
#
|
144
|
+
# :call-seq:
|
145
|
+
# first(limit = nil)
|
146
|
+
#
|
144
147
|
# Returns the first record, or the first +n+ records, from the collection.
|
145
148
|
# If the collection is empty, the first form returns +nil+, and the second
|
146
149
|
# form returns an empty array.
|
@@ -167,35 +170,63 @@ module ActiveRecord
|
|
167
170
|
# another_person_without.pets # => []
|
168
171
|
# another_person_without.pets.first # => nil
|
169
172
|
# another_person_without.pets.first(3) # => []
|
170
|
-
def first(*args)
|
171
|
-
@association.first(*args)
|
172
|
-
end
|
173
173
|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
174
|
+
##
|
175
|
+
# :method: second
|
176
|
+
#
|
177
|
+
# :call-seq:
|
178
|
+
# second()
|
179
|
+
#
|
180
|
+
# Same as #first except returns only the second record.
|
178
181
|
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
182
|
+
##
|
183
|
+
# :method: third
|
184
|
+
#
|
185
|
+
# :call-seq:
|
186
|
+
# third()
|
187
|
+
#
|
188
|
+
# Same as #first except returns only the third record.
|
183
189
|
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
190
|
+
##
|
191
|
+
# :method: fourth
|
192
|
+
#
|
193
|
+
# :call-seq:
|
194
|
+
# fourth()
|
195
|
+
#
|
196
|
+
# Same as #first except returns only the fourth record.
|
188
197
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
198
|
+
##
|
199
|
+
# :method: fifth
|
200
|
+
#
|
201
|
+
# :call-seq:
|
202
|
+
# fifth()
|
203
|
+
#
|
204
|
+
# Same as #first except returns only the fifth record.
|
193
205
|
|
194
|
-
|
206
|
+
##
|
207
|
+
# :method: forty_two
|
208
|
+
#
|
209
|
+
# :call-seq:
|
210
|
+
# forty_two()
|
211
|
+
#
|
212
|
+
# Same as #first except returns only the forty second record.
|
195
213
|
# Also known as accessing "the reddit".
|
196
|
-
|
197
|
-
|
198
|
-
|
214
|
+
|
215
|
+
##
|
216
|
+
# :method: third_to_last
|
217
|
+
#
|
218
|
+
# :call-seq:
|
219
|
+
# third_to_last()
|
220
|
+
#
|
221
|
+
# Same as #first except returns only the third-to-last record.
|
222
|
+
|
223
|
+
##
|
224
|
+
# :method: second_to_last
|
225
|
+
#
|
226
|
+
# :call-seq:
|
227
|
+
# second_to_last()
|
228
|
+
#
|
229
|
+
# Same as #first except returns only the second-to-last record.
|
199
230
|
|
200
231
|
# Returns the last record, or the last +n+ records, from the collection.
|
201
232
|
# If the collection is empty, the first form returns +nil+, and the second
|
@@ -223,12 +254,39 @@ module ActiveRecord
|
|
223
254
|
# another_person_without.pets # => []
|
224
255
|
# another_person_without.pets.last # => nil
|
225
256
|
# another_person_without.pets.last(3) # => []
|
226
|
-
def last(
|
227
|
-
|
257
|
+
def last(limit = nil)
|
258
|
+
load_target if find_from_target?
|
259
|
+
super
|
228
260
|
end
|
229
261
|
|
230
|
-
|
231
|
-
|
262
|
+
# Gives a record (or N records if a parameter is supplied) from the collection
|
263
|
+
# using the same rules as <tt>ActiveRecord::Base.take</tt>.
|
264
|
+
#
|
265
|
+
# class Person < ActiveRecord::Base
|
266
|
+
# has_many :pets
|
267
|
+
# end
|
268
|
+
#
|
269
|
+
# person.pets
|
270
|
+
# # => [
|
271
|
+
# # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
|
272
|
+
# # #<Pet id: 2, name: "Spook", person_id: 1>,
|
273
|
+
# # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
|
274
|
+
# # ]
|
275
|
+
#
|
276
|
+
# person.pets.take # => #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>
|
277
|
+
#
|
278
|
+
# person.pets.take(2)
|
279
|
+
# # => [
|
280
|
+
# # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
|
281
|
+
# # #<Pet id: 2, name: "Spook", person_id: 1>
|
282
|
+
# # ]
|
283
|
+
#
|
284
|
+
# another_person_without.pets # => []
|
285
|
+
# another_person_without.pets.take # => nil
|
286
|
+
# another_person_without.pets.take(2) # => []
|
287
|
+
def take(limit = nil)
|
288
|
+
load_target if find_from_target?
|
289
|
+
super
|
232
290
|
end
|
233
291
|
|
234
292
|
# Returns a new object of the collection type that has been instantiated
|
@@ -290,7 +348,7 @@ module ActiveRecord
|
|
290
348
|
@association.create(attributes, &block)
|
291
349
|
end
|
292
350
|
|
293
|
-
# Like
|
351
|
+
# Like #create, except that if the record is invalid, raises an exception.
|
294
352
|
#
|
295
353
|
# class Person
|
296
354
|
# has_many :pets
|
@@ -306,34 +364,6 @@ module ActiveRecord
|
|
306
364
|
@association.create!(attributes, &block)
|
307
365
|
end
|
308
366
|
|
309
|
-
# Add one or more records to the collection by setting their foreign keys
|
310
|
-
# to the association's primary key. Since << flattens its argument list and
|
311
|
-
# inserts each record, +push+ and +concat+ behave identically. Returns +self+
|
312
|
-
# so method calls may be chained.
|
313
|
-
#
|
314
|
-
# class Person < ActiveRecord::Base
|
315
|
-
# has_many :pets
|
316
|
-
# end
|
317
|
-
#
|
318
|
-
# person.pets.size # => 0
|
319
|
-
# person.pets.concat(Pet.new(name: 'Fancy-Fancy'))
|
320
|
-
# person.pets.concat(Pet.new(name: 'Spook'), Pet.new(name: 'Choo-Choo'))
|
321
|
-
# person.pets.size # => 3
|
322
|
-
#
|
323
|
-
# person.id # => 1
|
324
|
-
# person.pets
|
325
|
-
# # => [
|
326
|
-
# # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
|
327
|
-
# # #<Pet id: 2, name: "Spook", person_id: 1>,
|
328
|
-
# # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
|
329
|
-
# # ]
|
330
|
-
#
|
331
|
-
# person.pets.concat([Pet.new(name: 'Brain'), Pet.new(name: 'Benny')])
|
332
|
-
# person.pets.size # => 5
|
333
|
-
def concat(*records)
|
334
|
-
@association.concat(*records)
|
335
|
-
end
|
336
|
-
|
337
367
|
# Replaces this collection with +other_array+. This will perform a diff
|
338
368
|
# and delete/add only records that have changed.
|
339
369
|
#
|
@@ -344,7 +374,7 @@ module ActiveRecord
|
|
344
374
|
# person.pets
|
345
375
|
# # => [#<Pet id: 1, name: "Gorby", group: "cats", person_id: 1>]
|
346
376
|
#
|
347
|
-
# other_pets = [Pet.new(name: 'Puff', group: 'celebrities']
|
377
|
+
# other_pets = [Pet.new(name: 'Puff', group: 'celebrities')]
|
348
378
|
#
|
349
379
|
# person.pets.replace(other_pets)
|
350
380
|
#
|
@@ -364,7 +394,7 @@ module ActiveRecord
|
|
364
394
|
# specified by the +:dependent+ option. If no +:dependent+ option is given,
|
365
395
|
# then it will follow the default strategy.
|
366
396
|
#
|
367
|
-
# For
|
397
|
+
# For <tt>has_many :through</tt> associations, the default deletion strategy is
|
368
398
|
# +:delete_all+.
|
369
399
|
#
|
370
400
|
# For +has_many+ associations, the default deletion strategy is +:nullify+.
|
@@ -399,7 +429,7 @@ module ActiveRecord
|
|
399
429
|
# # #<Pet id: 3, name: "Choo-Choo", person_id: nil>
|
400
430
|
# # ]
|
401
431
|
#
|
402
|
-
# Both +has_many+ and
|
432
|
+
# Both +has_many+ and <tt>has_many :through</tt> dependencies default to the
|
403
433
|
# +:delete_all+ strategy if the +:dependent+ option is set to +:destroy+.
|
404
434
|
# Records are not instantiated and callbacks will not be fired.
|
405
435
|
#
|
@@ -418,7 +448,7 @@ module ActiveRecord
|
|
418
448
|
# person.pets.delete_all
|
419
449
|
#
|
420
450
|
# Pet.find(1, 2, 3)
|
421
|
-
# # => ActiveRecord::RecordNotFound
|
451
|
+
# # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 2, 3)
|
422
452
|
#
|
423
453
|
# If it is set to <tt>:delete_all</tt>, all the objects are deleted
|
424
454
|
# *without* calling their +destroy+ method.
|
@@ -438,9 +468,9 @@ module ActiveRecord
|
|
438
468
|
# person.pets.delete_all
|
439
469
|
#
|
440
470
|
# Pet.find(1, 2, 3)
|
441
|
-
# # => ActiveRecord::RecordNotFound
|
471
|
+
# # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 2, 3)
|
442
472
|
def delete_all(dependent = nil)
|
443
|
-
@association.delete_all(dependent)
|
473
|
+
@association.delete_all(dependent).tap { reset_scope }
|
444
474
|
end
|
445
475
|
|
446
476
|
# Deletes the records of the collection directly from the database
|
@@ -467,7 +497,7 @@ module ActiveRecord
|
|
467
497
|
#
|
468
498
|
# Pet.find(1) # => Couldn't find Pet with id=1
|
469
499
|
def destroy_all
|
470
|
-
@association.destroy_all
|
500
|
+
@association.destroy_all.tap { reset_scope }
|
471
501
|
end
|
472
502
|
|
473
503
|
# Deletes the +records+ supplied from the collection according to the strategy
|
@@ -475,7 +505,7 @@ module ActiveRecord
|
|
475
505
|
# then it will follow the default strategy. Returns an array with the
|
476
506
|
# deleted records.
|
477
507
|
#
|
478
|
-
# For
|
508
|
+
# For <tt>has_many :through</tt> associations, the default deletion strategy is
|
479
509
|
# +:delete_all+.
|
480
510
|
#
|
481
511
|
# For +has_many+ associations, the default deletion strategy is +:nullify+.
|
@@ -532,7 +562,7 @@ module ActiveRecord
|
|
532
562
|
# # => [#<Pet id: 2, name: "Spook", person_id: 1>]
|
533
563
|
#
|
534
564
|
# Pet.find(1, 3)
|
535
|
-
# # => ActiveRecord::RecordNotFound: Couldn't find all Pets with
|
565
|
+
# # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 3)
|
536
566
|
#
|
537
567
|
# If it is set to <tt>:delete_all</tt>, all the +records+ are deleted
|
538
568
|
# *without* calling their +destroy+ method.
|
@@ -560,7 +590,7 @@ module ActiveRecord
|
|
560
590
|
# # ]
|
561
591
|
#
|
562
592
|
# Pet.find(1)
|
563
|
-
# # => ActiveRecord::RecordNotFound: Couldn't find Pet with id=1
|
593
|
+
# # => ActiveRecord::RecordNotFound: Couldn't find Pet with 'id'=1
|
564
594
|
#
|
565
595
|
# You can pass +Integer+ or +String+ values, it finds the records
|
566
596
|
# responding to the +id+ and executes delete on them.
|
@@ -586,7 +616,7 @@ module ActiveRecord
|
|
586
616
|
# # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
|
587
617
|
# # ]
|
588
618
|
def delete(*records)
|
589
|
-
@association.delete(*records)
|
619
|
+
@association.delete(*records).tap { reset_scope }
|
590
620
|
end
|
591
621
|
|
592
622
|
# Destroys the +records+ supplied and removes them from the collection.
|
@@ -624,7 +654,7 @@ module ActiveRecord
|
|
624
654
|
# person.pets.size # => 0
|
625
655
|
# person.pets # => []
|
626
656
|
#
|
627
|
-
# Pet.find(1, 2, 3) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with
|
657
|
+
# Pet.find(1, 2, 3) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 2, 3)
|
628
658
|
#
|
629
659
|
# You can pass +Integer+ or +String+ values, it finds the records
|
630
660
|
# responding to the +id+ and then deletes them from the database.
|
@@ -656,11 +686,17 @@ module ActiveRecord
|
|
656
686
|
# person.pets.size # => 0
|
657
687
|
# person.pets # => []
|
658
688
|
#
|
659
|
-
# Pet.find(4, 5, 6) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with
|
689
|
+
# Pet.find(4, 5, 6) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (4, 5, 6)
|
660
690
|
def destroy(*records)
|
661
|
-
@association.destroy(*records)
|
691
|
+
@association.destroy(*records).tap { reset_scope }
|
662
692
|
end
|
663
693
|
|
694
|
+
##
|
695
|
+
# :method: distinct
|
696
|
+
#
|
697
|
+
# :call-seq:
|
698
|
+
# distinct(value = true)
|
699
|
+
#
|
664
700
|
# Specifies whether the records should be unique or not.
|
665
701
|
#
|
666
702
|
# class Person < ActiveRecord::Base
|
@@ -675,17 +711,35 @@ module ActiveRecord
|
|
675
711
|
#
|
676
712
|
# person.pets.select(:name).distinct
|
677
713
|
# # => [#<Pet name: "Fancy-Fancy">]
|
678
|
-
|
679
|
-
|
714
|
+
#
|
715
|
+
# person.pets.select(:name).distinct.distinct(false)
|
716
|
+
# # => [
|
717
|
+
# # #<Pet name: "Fancy-Fancy">,
|
718
|
+
# # #<Pet name: "Fancy-Fancy">
|
719
|
+
# # ]
|
720
|
+
|
721
|
+
#--
|
722
|
+
def calculate(operation, column_name)
|
723
|
+
null_scope? ? scope.calculate(operation, column_name) : super
|
724
|
+
end
|
725
|
+
|
726
|
+
def pluck(*column_names)
|
727
|
+
null_scope? ? scope.pluck(*column_names) : super
|
680
728
|
end
|
681
|
-
alias uniq distinct
|
682
729
|
|
683
|
-
|
730
|
+
##
|
731
|
+
# :method: count
|
732
|
+
#
|
733
|
+
# :call-seq:
|
734
|
+
# count(column_name = nil, &block)
|
735
|
+
#
|
736
|
+
# Count all records.
|
684
737
|
#
|
685
738
|
# class Person < ActiveRecord::Base
|
686
739
|
# has_many :pets
|
687
740
|
# end
|
688
741
|
#
|
742
|
+
# # This will perform the count using SQL.
|
689
743
|
# person.pets.count # => 3
|
690
744
|
# person.pets
|
691
745
|
# # => [
|
@@ -693,11 +747,11 @@ module ActiveRecord
|
|
693
747
|
# # #<Pet id: 2, name: "Spook", person_id: 1>,
|
694
748
|
# # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
|
695
749
|
# # ]
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
750
|
+
#
|
751
|
+
# Passing a block will select all of a person's pets in SQL and then
|
752
|
+
# perform the count using Ruby.
|
753
|
+
#
|
754
|
+
# person.pets.count { |pet| pet.name.include?('-') } # => 2
|
701
755
|
|
702
756
|
# Returns the size of the collection. If the collection hasn't been loaded,
|
703
757
|
# it executes a <tt>SELECT COUNT(*)</tt> query. Else it calls <tt>collection.size</tt>.
|
@@ -727,6 +781,12 @@ module ActiveRecord
|
|
727
781
|
@association.size
|
728
782
|
end
|
729
783
|
|
784
|
+
##
|
785
|
+
# :method: length
|
786
|
+
#
|
787
|
+
# :call-seq:
|
788
|
+
# length()
|
789
|
+
#
|
730
790
|
# Returns the size of the collection calling +size+ on the target.
|
731
791
|
# If the collection has been already loaded, +length+ and +size+ are
|
732
792
|
# equivalent. If not and you are going to need the records anyway this
|
@@ -747,14 +807,11 @@ module ActiveRecord
|
|
747
807
|
# # #<Pet id: 2, name: "Spook", person_id: 1>,
|
748
808
|
# # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
|
749
809
|
# # ]
|
750
|
-
def length
|
751
|
-
@association.length
|
752
|
-
end
|
753
810
|
|
754
811
|
# Returns +true+ if the collection is empty. If the collection has been
|
755
812
|
# loaded it is equivalent
|
756
813
|
# to <tt>collection.size.zero?</tt>. If the collection has not been loaded,
|
757
|
-
# it is equivalent to <tt
|
814
|
+
# it is equivalent to <tt>!collection.exists?</tt>. If the collection has
|
758
815
|
# not already been loaded and you are going to fetch the records anyway it
|
759
816
|
# is better to check <tt>collection.length.zero?</tt>.
|
760
817
|
#
|
@@ -773,6 +830,12 @@ module ActiveRecord
|
|
773
830
|
@association.empty?
|
774
831
|
end
|
775
832
|
|
833
|
+
##
|
834
|
+
# :method: any?
|
835
|
+
#
|
836
|
+
# :call-seq:
|
837
|
+
# any?()
|
838
|
+
#
|
776
839
|
# Returns +true+ if the collection is not empty.
|
777
840
|
#
|
778
841
|
# class Person < ActiveRecord::Base
|
@@ -783,7 +846,7 @@ module ActiveRecord
|
|
783
846
|
# person.pets.any? # => false
|
784
847
|
#
|
785
848
|
# person.pets << Pet.new(name: 'Snoop')
|
786
|
-
# person.pets.count # =>
|
849
|
+
# person.pets.count # => 1
|
787
850
|
# person.pets.any? # => true
|
788
851
|
#
|
789
852
|
# You can also pass a +block+ to define criteria. The behavior
|
@@ -802,10 +865,13 @@ module ActiveRecord
|
|
802
865
|
# pet.group == 'dogs'
|
803
866
|
# end
|
804
867
|
# # => true
|
805
|
-
def any?(&block)
|
806
|
-
@association.any?(&block)
|
807
|
-
end
|
808
868
|
|
869
|
+
##
|
870
|
+
# :method: many?
|
871
|
+
#
|
872
|
+
# :call-seq:
|
873
|
+
# many?()
|
874
|
+
#
|
809
875
|
# Returns true if the collection has more than one record.
|
810
876
|
# Equivalent to <tt>collection.size > 1</tt>.
|
811
877
|
#
|
@@ -840,9 +906,6 @@ module ActiveRecord
|
|
840
906
|
# pet.group == 'cats'
|
841
907
|
# end
|
842
908
|
# # => true
|
843
|
-
def many?(&block)
|
844
|
-
@association.many?(&block)
|
845
|
-
end
|
846
909
|
|
847
910
|
# Returns +true+ if the given +record+ is present in the collection.
|
848
911
|
#
|
@@ -858,27 +921,14 @@ module ActiveRecord
|
|
858
921
|
!!@association.include?(record)
|
859
922
|
end
|
860
923
|
|
861
|
-
def
|
862
|
-
scope.arel
|
863
|
-
end
|
864
|
-
|
865
|
-
def proxy_association
|
924
|
+
def proxy_association # :nodoc:
|
866
925
|
@association
|
867
926
|
end
|
868
927
|
|
869
|
-
# We don't want this object to be put on the scoping stack, because
|
870
|
-
# that could create an infinite loop where we call an @association
|
871
|
-
# method, which gets the current scope, which is this object, which
|
872
|
-
# delegates to @association, and so on.
|
873
|
-
def scoping
|
874
|
-
@association.scope.scoping { yield }
|
875
|
-
end
|
876
|
-
|
877
928
|
# Returns a <tt>Relation</tt> object for the records in this association
|
878
929
|
def scope
|
879
|
-
@association.scope
|
930
|
+
@scope ||= @association.scope
|
880
931
|
end
|
881
|
-
alias spawn scope
|
882
932
|
|
883
933
|
# Equivalent to <tt>Array#==</tt>. Returns +true+ if the two arrays
|
884
934
|
# contain the same number of elements and if each element is equal
|
@@ -908,6 +958,12 @@ module ActiveRecord
|
|
908
958
|
load_target == other
|
909
959
|
end
|
910
960
|
|
961
|
+
##
|
962
|
+
# :method: to_ary
|
963
|
+
#
|
964
|
+
# :call-seq:
|
965
|
+
# to_ary()
|
966
|
+
#
|
911
967
|
# Returns a new array of objects from the collection. If the collection
|
912
968
|
# hasn't been loaded, it fetches the records from the database.
|
913
969
|
#
|
@@ -941,14 +997,15 @@ module ActiveRecord
|
|
941
997
|
# # #<Pet id: 5, name: "Brain", person_id: 1>,
|
942
998
|
# # #<Pet id: 6, name: "Boss", person_id: 1>
|
943
999
|
# # ]
|
944
|
-
|
945
|
-
|
1000
|
+
|
1001
|
+
def records # :nodoc:
|
1002
|
+
load_target
|
946
1003
|
end
|
947
|
-
alias_method :to_a, :to_ary
|
948
1004
|
|
949
1005
|
# Adds one or more +records+ to the collection by setting their foreign keys
|
950
|
-
# to the association's primary key.
|
951
|
-
#
|
1006
|
+
# to the association's primary key. Since <tt><<</tt> flattens its argument list and
|
1007
|
+
# inserts each record, +push+ and +concat+ behave identically. Returns +self+
|
1008
|
+
# so several appends may be chained together.
|
952
1009
|
#
|
953
1010
|
# class Person < ActiveRecord::Base
|
954
1011
|
# has_many :pets
|
@@ -971,21 +1028,24 @@ module ActiveRecord
|
|
971
1028
|
end
|
972
1029
|
alias_method :push, :<<
|
973
1030
|
alias_method :append, :<<
|
1031
|
+
alias_method :concat, :<<
|
974
1032
|
|
975
|
-
def prepend(*args)
|
976
|
-
raise NoMethodError, "prepend on association is not defined. Please use
|
1033
|
+
def prepend(*args) # :nodoc:
|
1034
|
+
raise NoMethodError, "prepend on association is not defined. Please use <<, push or append"
|
977
1035
|
end
|
978
1036
|
|
979
1037
|
# Equivalent to +delete_all+. The difference is that returns +self+, instead
|
980
1038
|
# of an array with the deleted objects, so methods can be chained. See
|
981
1039
|
# +delete_all+ for more information.
|
1040
|
+
# Note that because +delete_all+ removes records by directly
|
1041
|
+
# running an SQL query into the database, the +updated_at+ column of
|
1042
|
+
# the object is not changed.
|
982
1043
|
def clear
|
983
1044
|
delete_all
|
984
1045
|
self
|
985
1046
|
end
|
986
1047
|
|
987
1048
|
# Reloads the collection from the database. Returns +self+.
|
988
|
-
# Equivalent to <tt>collection(true)</tt>.
|
989
1049
|
#
|
990
1050
|
# class Person < ActiveRecord::Base
|
991
1051
|
# has_many :pets
|
@@ -999,12 +1059,9 @@ module ActiveRecord
|
|
999
1059
|
#
|
1000
1060
|
# person.pets.reload # fetches pets from the database
|
1001
1061
|
# # => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]
|
1002
|
-
#
|
1003
|
-
# person.pets(true) # fetches pets from the database
|
1004
|
-
# # => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]
|
1005
1062
|
def reload
|
1006
|
-
proxy_association.reload
|
1007
|
-
|
1063
|
+
proxy_association.reload(true)
|
1064
|
+
reset_scope
|
1008
1065
|
end
|
1009
1066
|
|
1010
1067
|
# Unloads the association. Returns +self+.
|
@@ -1026,8 +1083,53 @@ module ActiveRecord
|
|
1026
1083
|
def reset
|
1027
1084
|
proxy_association.reset
|
1028
1085
|
proxy_association.reset_scope
|
1086
|
+
reset_scope
|
1087
|
+
end
|
1088
|
+
|
1089
|
+
def reset_scope # :nodoc:
|
1090
|
+
@offsets = @take = nil
|
1091
|
+
@scope = nil
|
1029
1092
|
self
|
1030
1093
|
end
|
1094
|
+
|
1095
|
+
def inspect # :nodoc:
|
1096
|
+
load_target if find_from_target?
|
1097
|
+
super
|
1098
|
+
end
|
1099
|
+
|
1100
|
+
delegate_methods = [
|
1101
|
+
QueryMethods,
|
1102
|
+
SpawnMethods,
|
1103
|
+
].flat_map { |klass|
|
1104
|
+
klass.public_instance_methods(false)
|
1105
|
+
} - self.public_instance_methods(false) - [:select] + [
|
1106
|
+
:scoping, :values, :insert, :insert_all, :insert!, :insert_all!, :upsert, :upsert_all
|
1107
|
+
]
|
1108
|
+
|
1109
|
+
delegate(*delegate_methods, to: :scope)
|
1110
|
+
|
1111
|
+
private
|
1112
|
+
def find_nth_with_limit(index, limit)
|
1113
|
+
load_target if find_from_target?
|
1114
|
+
super
|
1115
|
+
end
|
1116
|
+
|
1117
|
+
def find_nth_from_last(index)
|
1118
|
+
load_target if find_from_target?
|
1119
|
+
super
|
1120
|
+
end
|
1121
|
+
|
1122
|
+
def null_scope?
|
1123
|
+
@association.null_scope?
|
1124
|
+
end
|
1125
|
+
|
1126
|
+
def find_from_target?
|
1127
|
+
@association.find_from_target?
|
1128
|
+
end
|
1129
|
+
|
1130
|
+
def exec_queries
|
1131
|
+
load_target
|
1132
|
+
end
|
1031
1133
|
end
|
1032
1134
|
end
|
1033
1135
|
end
|