activerecord 4.2.0 → 6.1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/CHANGELOG.md +1221 -796
- 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 +267 -249
- data/lib/active_record/association_relation.rb +45 -7
- data/lib/active_record/associations/alias_tracker.rb +40 -43
- data/lib/active_record/associations/association.rb +172 -67
- data/lib/active_record/associations/association_scope.rb +105 -129
- data/lib/active_record/associations/belongs_to_association.rb +85 -59
- 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 -33
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +57 -70
- 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 +168 -279
- data/lib/active_record/associations/collection_proxy.rb +263 -155
- data/lib/active_record/associations/foreign_association.rb +33 -0
- data/lib/active_record/associations/has_many_association.rb +57 -84
- data/lib/active_record/associations/has_many_through_association.rb +70 -82
- data/lib/active_record/associations/has_one_association.rb +74 -47
- data/lib/active_record/associations/has_one_through_association.rb +20 -11
- data/lib/active_record/associations/join_dependency/join_association.rb +54 -73
- 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 +175 -164
- data/lib/active_record/associations/preloader/association.rb +107 -112
- data/lib/active_record/associations/preloader/through_association.rb +85 -65
- data/lib/active_record/associations/preloader.rb +99 -96
- data/lib/active_record/associations/singular_association.rb +18 -45
- data/lib/active_record/associations/through_association.rb +49 -24
- data/lib/active_record/associations.rb +1845 -1597
- data/lib/active_record/attribute_assignment.rb +59 -185
- data/lib/active_record/attribute_methods/before_type_cast.rb +20 -7
- data/lib/active_record/attribute_methods/dirty.rb +168 -138
- 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 +59 -36
- data/lib/active_record/attribute_methods/write.rb +25 -56
- data/lib/active_record/attribute_methods.rb +153 -162
- data/lib/active_record/attributes.rb +234 -70
- data/lib/active_record/autosave_association.rb +157 -69
- data/lib/active_record/base.rb +49 -50
- 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 +46 -13
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +887 -317
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -41
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +301 -113
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +78 -24
- data/lib/active_record/connection_adapters/abstract/quoting.rb +187 -60
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +9 -7
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +157 -93
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +485 -253
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +909 -263
- data/lib/active_record/connection_adapters/abstract/transaction.rb +254 -92
- data/lib/active_record/connection_adapters/abstract_adapter.rb +492 -221
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +580 -608
- 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 +196 -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 +271 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +40 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +81 -199
- 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 +78 -161
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +49 -57
- 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 +5 -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 +17 -13
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +6 -3
- 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 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +67 -51
- 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 +171 -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 +499 -293
- 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 +595 -382
- data/lib/active_record/connection_adapters/schema_cache.rb +191 -29
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +45 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +146 -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 -389
- 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 +488 -243
- data/lib/active_record/counter_cache.rb +71 -50
- data/lib/active_record/database_configurations/connection_url_resolver.rb +99 -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 +273 -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 +212 -94
- data/lib/active_record/errors.rb +225 -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 +11 -6
- 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 +273 -496
- 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 +64 -0
- data/lib/active_record/legacy_yaml_adapter.rb +52 -0
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +103 -95
- 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 +298 -0
- data/lib/active_record/migration/join_table.rb +8 -7
- data/lib/active_record/migration.rb +685 -309
- data/lib/active_record/model_schema.rb +420 -113
- data/lib/active_record/nested_attributes.rb +265 -216
- data/lib/active_record/no_touching.rb +15 -2
- data/lib/active_record/null_relation.rb +24 -38
- data/lib/active_record/persistence.rb +574 -135
- data/lib/active_record/query_cache.rb +29 -23
- data/lib/active_record/querying.rb +50 -31
- data/lib/active_record/railtie.rb +175 -54
- 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 +533 -216
- data/lib/active_record/readonly_attributes.rb +9 -4
- data/lib/active_record/reflection.rb +485 -310
- 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 +326 -244
- data/lib/active_record/relation/delegation.rb +76 -84
- data/lib/active_record/relation/finder_methods.rb +318 -256
- data/lib/active_record/relation/from_clause.rb +30 -0
- data/lib/active_record/relation/merger.rb +99 -84
- data/lib/active_record/relation/predicate_builder/array_handler.rb +26 -25
- 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 +139 -96
- data/lib/active_record/relation/query_attribute.rb +50 -0
- data/lib/active_record/relation/query_methods.rb +757 -409
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +23 -21
- data/lib/active_record/relation/where_clause.rb +239 -0
- data/lib/active_record/relation.rb +554 -342
- 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 -26
- data/lib/active_record/scoping/default.rb +96 -82
- 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 +133 -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 +366 -129
- data/lib/active_record/tasks/mysql_database_tasks.rb +68 -100
- data/lib/active_record/tasks/postgresql_database_tasks.rb +87 -39
- 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 +291 -0
- data/lib/active_record/timestamp.rb +86 -43
- data/lib/active_record/touch_later.rb +65 -0
- data/lib/active_record/transactions.rb +181 -152
- 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 -41
- data/lib/active_record/type/date_time.rb +4 -38
- data/lib/active_record/type/decimal_without_scale.rb +6 -2
- data/lib/active_record/type/hash_lookup_type_map.rb +12 -5
- 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 +33 -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 +65 -48
- data/lib/active_record/validations.rb +39 -35
- data/lib/active_record/version.rb +3 -1
- data/lib/active_record.rb +44 -28
- 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 -10
- 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.rb +7 -5
- metadata +175 -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 -149
- data/lib/active_record/attribute_decorators.rb +0 -66
- data/lib/active_record/attribute_set/builder.rb +0 -86
- data/lib/active_record/attribute_set.rb +0 -77
- 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 -30
- data/lib/active_record/type/decimal.rb +0 -40
- 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 -55
- 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 -36
- data/lib/active_record/type/time_value.rb +0 -38
- data/lib/active_record/type/value.rb +0 -101
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -22
- data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
- /data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
@@ -1,49 +1,44 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/string/conversions"
|
2
4
|
|
3
5
|
module ActiveRecord
|
4
6
|
module Associations
|
5
|
-
# Keeps track of table aliases for ActiveRecord::Associations::
|
6
|
-
# ActiveRecord::Associations::ThroughAssociationScope
|
7
|
+
# Keeps track of table aliases for ActiveRecord::Associations::JoinDependency
|
7
8
|
class AliasTracker # :nodoc:
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
empty connection
|
9
|
+
def self.create(connection, initial_table, joins, aliases = nil)
|
10
|
+
if joins.empty?
|
11
|
+
aliases ||= Hash.new(0)
|
12
|
+
elsif aliases
|
13
|
+
default_proc = aliases.default_proc || proc { 0 }
|
14
|
+
aliases.default_proc = proc { |h, k|
|
15
|
+
h[k] = initial_count_for(connection, k, joins) + default_proc.call(h, k)
|
16
|
+
}
|
17
17
|
else
|
18
|
-
aliases = Hash.new { |h,k|
|
19
|
-
h[k] = initial_count_for(connection, k,
|
18
|
+
aliases = Hash.new { |h, k|
|
19
|
+
h[k] = initial_count_for(connection, k, joins)
|
20
20
|
}
|
21
|
-
new connection, aliases
|
22
21
|
end
|
22
|
+
aliases[initial_table] = 1
|
23
|
+
new(connection, aliases)
|
23
24
|
end
|
24
25
|
|
25
26
|
def self.initial_count_for(connection, name, table_joins)
|
26
|
-
|
27
|
-
quoted_name = connection.quote_table_name(name).downcase
|
27
|
+
quoted_name = nil
|
28
28
|
|
29
29
|
counts = table_joins.map do |join|
|
30
30
|
if join.is_a?(Arel::Nodes::StringJoin)
|
31
|
+
# quoted_name should be case ignored as some database adapters (Oracle) return quoted name in uppercase
|
32
|
+
quoted_name ||= connection.quote_table_name(name)
|
33
|
+
|
31
34
|
# Table names + table aliases
|
32
|
-
join.left.
|
33
|
-
/
|
35
|
+
join.left.scan(
|
36
|
+
/JOIN(?:\s+\w+)?\s+(?:\S+\s+)?(?:#{quoted_name}|#{name})\sON/i
|
34
37
|
).size
|
35
|
-
elsif join.
|
36
|
-
join.left.
|
38
|
+
elsif join.is_a?(Arel::Nodes::Join)
|
39
|
+
join.left.name == name ? 1 : 0
|
37
40
|
else
|
38
|
-
|
39
|
-
#
|
40
|
-
# activerecord/test/cases/associations/cascaded_eager_loading_test.rb:37
|
41
|
-
# with :posts
|
42
|
-
#
|
43
|
-
# activerecord/test/cases/associations/eager_test.rb:1133
|
44
|
-
# with :comments
|
45
|
-
#
|
46
|
-
0
|
41
|
+
raise ArgumentError, "joins list should be initialized by list of Arel::Nodes::Join"
|
47
42
|
end
|
48
43
|
end
|
49
44
|
|
@@ -56,31 +51,33 @@ module ActiveRecord
|
|
56
51
|
@connection = connection
|
57
52
|
end
|
58
53
|
|
59
|
-
def aliased_table_for(
|
60
|
-
|
54
|
+
def aliased_table_for(arel_table, table_name = nil)
|
55
|
+
table_name ||= arel_table.name
|
56
|
+
|
57
|
+
if aliases[table_name] == 0
|
61
58
|
# If it's zero, we can have our table_name
|
62
59
|
aliases[table_name] = 1
|
63
|
-
|
60
|
+
arel_table = arel_table.alias(table_name) if arel_table.name != table_name
|
64
61
|
else
|
65
62
|
# Otherwise, we need to use an alias
|
66
|
-
aliased_name = connection.table_alias_for(
|
63
|
+
aliased_name = @connection.table_alias_for(yield)
|
67
64
|
|
68
65
|
# Update the count
|
69
|
-
aliases[aliased_name] += 1
|
66
|
+
count = aliases[aliased_name] += 1
|
70
67
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
aliased_name
|
75
|
-
end
|
76
|
-
Arel::Table.new(table_name).alias(table_alias)
|
68
|
+
aliased_name = "#{truncate(aliased_name)}_#{count}" if count > 1
|
69
|
+
|
70
|
+
arel_table = arel_table.alias(aliased_name)
|
77
71
|
end
|
72
|
+
|
73
|
+
arel_table
|
78
74
|
end
|
79
75
|
|
80
|
-
|
76
|
+
attr_reader :aliases
|
81
77
|
|
78
|
+
private
|
82
79
|
def truncate(name)
|
83
|
-
name.slice(0, connection.table_alias_length - 2)
|
80
|
+
name.slice(0, @connection.table_alias_length - 2)
|
84
81
|
end
|
85
82
|
end
|
86
83
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
module Associations
|
@@ -8,18 +8,34 @@ module ActiveRecord
|
|
8
8
|
#
|
9
9
|
# Association
|
10
10
|
# SingularAssociation
|
11
|
-
# HasOneAssociation
|
11
|
+
# HasOneAssociation + ForeignAssociation
|
12
12
|
# HasOneThroughAssociation + ThroughAssociation
|
13
13
|
# BelongsToAssociation
|
14
14
|
# BelongsToPolymorphicAssociation
|
15
15
|
# CollectionAssociation
|
16
|
-
# HasManyAssociation
|
16
|
+
# HasManyAssociation + ForeignAssociation
|
17
17
|
# HasManyThroughAssociation + ThroughAssociation
|
18
|
+
#
|
19
|
+
# Associations in Active Record are middlemen between the object that
|
20
|
+
# holds the association, known as the <tt>owner</tt>, and the associated
|
21
|
+
# result set, known as the <tt>target</tt>. Association metadata is available in
|
22
|
+
# <tt>reflection</tt>, which is an instance of <tt>ActiveRecord::Reflection::AssociationReflection</tt>.
|
23
|
+
#
|
24
|
+
# For example, given
|
25
|
+
#
|
26
|
+
# class Blog < ActiveRecord::Base
|
27
|
+
# has_many :posts
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# blog = Blog.first
|
31
|
+
#
|
32
|
+
# The association of <tt>blog.posts</tt> has the object +blog+ as its
|
33
|
+
# <tt>owner</tt>, the collection of its posts as <tt>target</tt>, and
|
34
|
+
# the <tt>reflection</tt> object represents a <tt>:has_many</tt> macro.
|
18
35
|
class Association #:nodoc:
|
19
36
|
attr_reader :owner, :target, :reflection
|
20
|
-
attr_accessor :inversed
|
21
37
|
|
22
|
-
delegate :options, :
|
38
|
+
delegate :options, to: :reflection
|
23
39
|
|
24
40
|
def initialize(owner, reflection)
|
25
41
|
reflection.check_validity!
|
@@ -30,14 +46,6 @@ module ActiveRecord
|
|
30
46
|
reset_scope
|
31
47
|
end
|
32
48
|
|
33
|
-
# Returns the name of the table of the associated class:
|
34
|
-
#
|
35
|
-
# post.comments.aliased_table_name # => "comments"
|
36
|
-
#
|
37
|
-
def aliased_table_name
|
38
|
-
klass.table_name
|
39
|
-
end
|
40
|
-
|
41
49
|
# Resets the \loaded flag to +false+ and sets the \target to +nil+.
|
42
50
|
def reset
|
43
51
|
@loaded = false
|
@@ -46,8 +54,14 @@ module ActiveRecord
|
|
46
54
|
@inversed = false
|
47
55
|
end
|
48
56
|
|
57
|
+
def reset_negative_cache # :nodoc:
|
58
|
+
reset if loaded? && target.nil?
|
59
|
+
end
|
60
|
+
|
49
61
|
# Reloads the \target and returns +self+ on success.
|
50
|
-
|
62
|
+
# The QueryCache is cleared if +force+ is true.
|
63
|
+
def reload(force = false)
|
64
|
+
klass.connection.clear_query_cache if force && klass
|
51
65
|
reset
|
52
66
|
reset_scope
|
53
67
|
load_target
|
@@ -73,7 +87,7 @@ module ActiveRecord
|
|
73
87
|
#
|
74
88
|
# Note that if the target has not been loaded, it is not considered stale.
|
75
89
|
def stale_target?
|
76
|
-
|
90
|
+
!@inversed && loaded? && @stale_state != stale_state
|
77
91
|
end
|
78
92
|
|
79
93
|
# Sets the target of this association to <tt>\target</tt>, and the \loaded flag to +true+.
|
@@ -83,18 +97,10 @@ module ActiveRecord
|
|
83
97
|
end
|
84
98
|
|
85
99
|
def scope
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
#
|
91
|
-
# Note that the association_scope is merged into the target_scope only when the
|
92
|
-
# scope method is called. This is because at that point the call may be surrounded
|
93
|
-
# by scope.scoping { ... } or with_scope { ... } etc, which affects the scope which
|
94
|
-
# actually gets built.
|
95
|
-
def association_scope
|
96
|
-
if klass
|
97
|
-
@association_scope ||= AssociationScope.scope(self, klass.connection)
|
100
|
+
if (scope = klass.current_scope) && scope.try(:proxy_association) == self
|
101
|
+
scope.spawn
|
102
|
+
else
|
103
|
+
target_scope.merge!(association_scope)
|
98
104
|
end
|
99
105
|
end
|
100
106
|
|
@@ -104,24 +110,54 @@ module ActiveRecord
|
|
104
110
|
|
105
111
|
# Set the inverse association, if possible
|
106
112
|
def set_inverse_instance(record)
|
107
|
-
if
|
108
|
-
inverse
|
109
|
-
|
110
|
-
|
113
|
+
if inverse = inverse_association_for(record)
|
114
|
+
inverse.inversed_from(owner)
|
115
|
+
end
|
116
|
+
record
|
117
|
+
end
|
118
|
+
|
119
|
+
def set_inverse_instance_from_queries(record)
|
120
|
+
if inverse = inverse_association_for(record)
|
121
|
+
inverse.inversed_from_queries(owner)
|
111
122
|
end
|
112
123
|
record
|
113
124
|
end
|
114
125
|
|
126
|
+
# Remove the inverse association, if possible
|
127
|
+
def remove_inverse_instance(record)
|
128
|
+
if inverse = inverse_association_for(record)
|
129
|
+
inverse.inversed_from(nil)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def inversed_from(record)
|
134
|
+
self.target = record
|
135
|
+
@inversed = !!record
|
136
|
+
end
|
137
|
+
|
138
|
+
def inversed_from_queries(record)
|
139
|
+
if inversable?(record)
|
140
|
+
self.target = record
|
141
|
+
@inversed = true
|
142
|
+
else
|
143
|
+
@inversed = false
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
115
147
|
# Returns the class of the target. belongs_to polymorphic overrides this to look at the
|
116
148
|
# polymorphic_type field on the owner.
|
117
149
|
def klass
|
118
150
|
reflection.klass
|
119
151
|
end
|
120
152
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
153
|
+
def extensions
|
154
|
+
extensions = klass.default_extensions | reflection.extensions
|
155
|
+
|
156
|
+
if reflection.scope
|
157
|
+
extensions |= reflection.scope_for(klass.unscoped, owner).extensions
|
158
|
+
end
|
159
|
+
|
160
|
+
extensions
|
125
161
|
end
|
126
162
|
|
127
163
|
# Loads the \target if needed and returns it.
|
@@ -143,17 +179,9 @@ module ActiveRecord
|
|
143
179
|
reset
|
144
180
|
end
|
145
181
|
|
146
|
-
|
147
|
-
if sql.respond_to?(:to_proc)
|
148
|
-
owner.instance_exec(record, &sql)
|
149
|
-
else
|
150
|
-
sql
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
# We can't dump @reflection since it contains the scope proc
|
182
|
+
# We can't dump @reflection and @through_reflection since it contains the scope proc
|
155
183
|
def marshal_dump
|
156
|
-
ivars = (instance_variables - [:@reflection]).map { |name| [name, instance_variable_get(name)] }
|
184
|
+
ivars = (instance_variables - [:@reflection, :@through_reflection]).map { |name| [name, instance_variable_get(name)] }
|
157
185
|
[@reflection.name, ivars]
|
158
186
|
end
|
159
187
|
|
@@ -163,36 +191,72 @@ module ActiveRecord
|
|
163
191
|
@reflection = @owner.class._reflect_on_association(reflection_name)
|
164
192
|
end
|
165
193
|
|
166
|
-
def initialize_attributes(record) #:nodoc:
|
194
|
+
def initialize_attributes(record, except_from_scope_attributes = nil) #:nodoc:
|
195
|
+
except_from_scope_attributes ||= {}
|
167
196
|
skip_assign = [reflection.foreign_key, reflection.type].compact
|
168
|
-
|
169
|
-
|
197
|
+
assigned_keys = record.changed_attribute_names_to_save
|
198
|
+
assigned_keys += except_from_scope_attributes.keys.map(&:to_s)
|
199
|
+
attributes = scope_for_create.except!(*(assigned_keys - skip_assign))
|
200
|
+
record.send(:_assign_attributes, attributes) if attributes.any?
|
170
201
|
set_inverse_instance(record)
|
171
202
|
end
|
172
203
|
|
204
|
+
def create(attributes = nil, &block)
|
205
|
+
_create_record(attributes, &block)
|
206
|
+
end
|
207
|
+
|
208
|
+
def create!(attributes = nil, &block)
|
209
|
+
_create_record(attributes, true, &block)
|
210
|
+
end
|
211
|
+
|
173
212
|
private
|
213
|
+
def find_target
|
214
|
+
if strict_loading? && owner.validation_context.nil?
|
215
|
+
Base.strict_loading_violation!(owner: owner.class, reflection: reflection)
|
216
|
+
end
|
174
217
|
|
175
|
-
|
176
|
-
|
218
|
+
scope = self.scope
|
219
|
+
return scope.to_a if skip_statement_cache?(scope)
|
220
|
+
|
221
|
+
sc = reflection.association_scope_cache(klass, owner) do |params|
|
222
|
+
as = AssociationScope.create { params.bind }
|
223
|
+
target_scope.merge!(as.scope(self))
|
224
|
+
end
|
225
|
+
|
226
|
+
binds = AssociationScope.get_bind_values(owner, reflection.chain)
|
227
|
+
sc.execute(binds, klass.connection) { |record| set_inverse_instance(record) }
|
177
228
|
end
|
178
229
|
|
179
|
-
def
|
180
|
-
|
230
|
+
def strict_loading?
|
231
|
+
return reflection.strict_loading? if reflection.options.key?(:strict_loading)
|
181
232
|
|
182
|
-
|
183
|
-
|
233
|
+
owner.strict_loading?
|
234
|
+
end
|
184
235
|
|
185
|
-
|
186
|
-
|
187
|
-
|
236
|
+
# The scope for this association.
|
237
|
+
#
|
238
|
+
# Note that the association_scope is merged into the target_scope only when the
|
239
|
+
# scope method is called. This is because at that point the call may be surrounded
|
240
|
+
# by scope.scoping { ... } or unscoped { ... } etc, which affects the scope which
|
241
|
+
# actually gets built.
|
242
|
+
def association_scope
|
243
|
+
if klass
|
244
|
+
@association_scope ||= AssociationScope.scope(self)
|
188
245
|
end
|
246
|
+
end
|
247
|
+
|
248
|
+
# Can be overridden (i.e. in ThroughAssociation) to merge in other scopes (i.e. the
|
249
|
+
# through association's scope)
|
250
|
+
def target_scope
|
251
|
+
AssociationRelation.create(klass, self).merge!(klass.scope_for_association)
|
252
|
+
end
|
189
253
|
|
190
|
-
|
254
|
+
def scope_for_create
|
255
|
+
scope.scope_for_create
|
191
256
|
end
|
192
257
|
|
193
|
-
|
194
|
-
|
195
|
-
creation_attributes.each { |key, value| record[key] = value }
|
258
|
+
def find_target?
|
259
|
+
!loaded? && (!owner.new_record? || foreign_key_present?) && klass
|
196
260
|
end
|
197
261
|
|
198
262
|
# Returns true if there is a foreign key present on the owner which
|
@@ -211,9 +275,19 @@ module ActiveRecord
|
|
211
275
|
# the kind of the class of the associated objects. Meant to be used as
|
212
276
|
# a sanity check when you are about to assign an associated record.
|
213
277
|
def raise_on_type_mismatch!(record)
|
214
|
-
unless record.is_a?(reflection.klass)
|
215
|
-
|
216
|
-
|
278
|
+
unless record.is_a?(reflection.klass)
|
279
|
+
fresh_class = reflection.class_name.safe_constantize
|
280
|
+
unless fresh_class && record.is_a?(fresh_class)
|
281
|
+
message = "#{reflection.class_name}(##{reflection.klass.object_id}) expected, "\
|
282
|
+
"got #{record.inspect} which is an instance of #{record.class}(##{record.class.object_id})"
|
283
|
+
raise ActiveRecord::AssociationTypeMismatch, message
|
284
|
+
end
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
def inverse_association_for(record)
|
289
|
+
if invertible_for?(record)
|
290
|
+
record.association(inverse_reflection_for(record).name)
|
217
291
|
end
|
218
292
|
end
|
219
293
|
|
@@ -232,20 +306,51 @@ module ActiveRecord
|
|
232
306
|
|
233
307
|
# Returns true if record contains the foreign_key
|
234
308
|
def foreign_key_for?(record)
|
235
|
-
record.
|
309
|
+
record._has_attribute?(reflection.foreign_key)
|
236
310
|
end
|
237
311
|
|
238
312
|
# This should be implemented to return the values of the relevant key(s) on the owner,
|
239
313
|
# so that when stale_state is different from the value stored on the last find_target,
|
240
314
|
# the target is stale.
|
241
315
|
#
|
242
|
-
# This is only relevant to certain associations, which is why it returns nil by default.
|
316
|
+
# This is only relevant to certain associations, which is why it returns +nil+ by default.
|
243
317
|
def stale_state
|
244
318
|
end
|
245
319
|
|
246
320
|
def build_record(attributes)
|
247
321
|
reflection.build_association(attributes) do |record|
|
248
|
-
initialize_attributes(record)
|
322
|
+
initialize_attributes(record, attributes)
|
323
|
+
yield(record) if block_given?
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
# Returns true if statement cache should be skipped on the association reader.
|
328
|
+
def skip_statement_cache?(scope)
|
329
|
+
reflection.has_scope? ||
|
330
|
+
scope.eager_loading? ||
|
331
|
+
klass.scope_attributes? ||
|
332
|
+
reflection.source_reflection.active_record.default_scopes.any?
|
333
|
+
end
|
334
|
+
|
335
|
+
def enqueue_destroy_association(options)
|
336
|
+
job_class = owner.class.destroy_association_async_job
|
337
|
+
|
338
|
+
if job_class
|
339
|
+
owner._after_commit_jobs.push([job_class, options])
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
def inversable?(record)
|
344
|
+
record &&
|
345
|
+
((!record.persisted? || !owner.persisted?) || matches_foreign_key?(record))
|
346
|
+
end
|
347
|
+
|
348
|
+
def matches_foreign_key?(record)
|
349
|
+
if foreign_key_for?(record)
|
350
|
+
record.read_attribute(reflection.foreign_key) == owner.id ||
|
351
|
+
(foreign_key_for?(owner) && owner.read_attribute(reflection.foreign_key) == record.id)
|
352
|
+
else
|
353
|
+
owner.read_attribute(reflection.foreign_key) == record.id
|
249
354
|
end
|
250
355
|
end
|
251
356
|
end
|