activerecord 6.0.0 → 7.2.3
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 +4 -4
- data/CHANGELOG.md +996 -594
- data/MIT-LICENSE +1 -1
- data/README.rdoc +34 -34
- data/examples/performance.rb +2 -2
- data/lib/active_record/aggregations.rb +22 -20
- data/lib/active_record/association_relation.rb +22 -12
- data/lib/active_record/associations/alias_tracker.rb +41 -30
- data/lib/active_record/associations/association.rb +106 -41
- data/lib/active_record/associations/association_scope.rb +30 -21
- data/lib/active_record/associations/belongs_to_association.rb +69 -14
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +20 -6
- data/lib/active_record/associations/builder/association.rb +39 -6
- data/lib/active_record/associations/builder/belongs_to.rb +47 -17
- data/lib/active_record/associations/builder/collection_association.rb +14 -6
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -10
- data/lib/active_record/associations/builder/has_many.rb +7 -3
- data/lib/active_record/associations/builder/has_one.rb +13 -16
- data/lib/active_record/associations/builder/singular_association.rb +7 -3
- data/lib/active_record/associations/collection_association.rb +90 -53
- data/lib/active_record/associations/collection_proxy.rb +54 -19
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/errors.rb +265 -0
- data/lib/active_record/associations/foreign_association.rb +21 -1
- data/lib/active_record/associations/has_many_association.rb +41 -10
- data/lib/active_record/associations/has_many_through_association.rb +29 -12
- data/lib/active_record/associations/has_one_association.rb +33 -9
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +41 -17
- data/lib/active_record/associations/join_dependency/join_part.rb +3 -3
- data/lib/active_record/associations/join_dependency.rb +97 -54
- data/lib/active_record/associations/nested_error.rb +47 -0
- data/lib/active_record/associations/preloader/association.rb +237 -54
- data/lib/active_record/associations/preloader/batch.rb +48 -0
- data/lib/active_record/associations/preloader/branch.rb +153 -0
- data/lib/active_record/associations/preloader/through_association.rb +51 -17
- data/lib/active_record/associations/preloader.rb +55 -121
- data/lib/active_record/associations/singular_association.rb +16 -4
- data/lib/active_record/associations/through_association.rb +26 -15
- data/lib/active_record/associations.rb +454 -440
- data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
- data/lib/active_record/attribute_assignment.rb +11 -14
- data/lib/active_record/attribute_methods/before_type_cast.rb +36 -11
- data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
- data/lib/active_record/attribute_methods/dirty.rb +75 -34
- data/lib/active_record/attribute_methods/primary_key.rb +53 -31
- data/lib/active_record/attribute_methods/query.rb +31 -22
- data/lib/active_record/attribute_methods/read.rb +16 -17
- data/lib/active_record/attribute_methods/serialization.rb +177 -35
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +18 -15
- data/lib/active_record/attribute_methods/write.rb +16 -28
- data/lib/active_record/attribute_methods.rb +227 -100
- data/lib/active_record/attributes.rb +94 -56
- data/lib/active_record/autosave_association.rb +119 -73
- data/lib/active_record/base.rb +31 -21
- data/lib/active_record/callbacks.rb +168 -55
- data/lib/active_record/coders/column_serializer.rb +61 -0
- data/lib/active_record/coders/json.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +70 -25
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +284 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +211 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +79 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +367 -565
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -57
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +277 -89
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +241 -69
- data/lib/active_record/connection_adapters/abstract/quoting.rb +122 -134
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -116
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +324 -72
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +17 -4
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +611 -211
- data/lib/active_record/connection_adapters/abstract/transaction.rb +425 -82
- data/lib/active_record/connection_adapters/abstract_adapter.rb +698 -211
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +464 -239
- data/lib/active_record/connection_adapters/column.rb +28 -1
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +2 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +32 -137
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
- data/lib/active_record/connection_adapters/mysql/quoting.rb +90 -43
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +41 -7
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +18 -1
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +13 -4
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +53 -15
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +152 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +127 -63
- data/lib/active_record/connection_adapters/pool_config.rb +83 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +57 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +54 -2
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +127 -100
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +9 -5
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +10 -2
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +15 -2
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -15
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -3
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +5 -4
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -3
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +35 -8
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +23 -4
- data/lib/active_record/connection_adapters/postgresql/oid.rb +4 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +139 -106
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -2
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +98 -4
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +176 -4
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +462 -118
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -11
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +585 -295
- data/lib/active_record/connection_adapters/schema_cache.rb +399 -60
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +8 -0
- data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +99 -48
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +80 -54
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +27 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +20 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +102 -24
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +425 -174
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -1
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +229 -0
- data/lib/active_record/connection_adapters.rb +176 -0
- data/lib/active_record/connection_handling.rb +243 -115
- data/lib/active_record/core.rb +481 -199
- data/lib/active_record/counter_cache.rb +69 -32
- data/lib/active_record/database_configurations/connection_url_resolver.rb +107 -0
- data/lib/active_record/database_configurations/database_config.rb +77 -10
- data/lib/active_record/database_configurations/hash_config.rb +148 -26
- data/lib/active_record/database_configurations/url_config.rb +44 -45
- data/lib/active_record/database_configurations.rb +190 -114
- data/lib/active_record/delegated_type.rb +279 -0
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +38 -0
- data/lib/active_record/disable_joins_association_relation.rb +39 -0
- data/lib/active_record/dynamic_matchers.rb +5 -6
- data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
- data/lib/active_record/encryption/cipher.rb +53 -0
- data/lib/active_record/encryption/config.rb +68 -0
- data/lib/active_record/encryption/configurable.rb +60 -0
- data/lib/active_record/encryption/context.rb +42 -0
- data/lib/active_record/encryption/contexts.rb +76 -0
- data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
- data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
- data/lib/active_record/encryption/encryptable_record.rb +230 -0
- data/lib/active_record/encryption/encrypted_attribute_type.rb +175 -0
- data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
- data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
- data/lib/active_record/encryption/encryptor.rb +171 -0
- data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
- data/lib/active_record/encryption/errors.rb +15 -0
- data/lib/active_record/encryption/extended_deterministic_queries.rb +157 -0
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
- data/lib/active_record/encryption/key.rb +28 -0
- data/lib/active_record/encryption/key_generator.rb +53 -0
- data/lib/active_record/encryption/key_provider.rb +46 -0
- data/lib/active_record/encryption/message.rb +33 -0
- data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
- data/lib/active_record/encryption/message_serializer.rb +96 -0
- data/lib/active_record/encryption/null_encryptor.rb +25 -0
- data/lib/active_record/encryption/properties.rb +76 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +28 -0
- data/lib/active_record/encryption/scheme.rb +100 -0
- data/lib/active_record/encryption.rb +58 -0
- data/lib/active_record/enum.rb +224 -73
- data/lib/active_record/errors.rb +254 -36
- data/lib/active_record/explain.rb +30 -17
- data/lib/active_record/explain_registry.rb +11 -6
- data/lib/active_record/explain_subscriber.rb +2 -2
- data/lib/active_record/fixture_set/file.rb +22 -15
- data/lib/active_record/fixture_set/model_metadata.rb +15 -6
- data/lib/active_record/fixture_set/render_context.rb +3 -1
- data/lib/active_record/fixture_set/table_row.rb +88 -16
- data/lib/active_record/fixture_set/table_rows.rb +4 -5
- data/lib/active_record/fixtures.rb +229 -116
- data/lib/active_record/future_result.rb +178 -0
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +121 -48
- data/lib/active_record/insert_all.rb +178 -29
- data/lib/active_record/integration.rb +16 -14
- data/lib/active_record/internal_metadata.rb +132 -21
- data/lib/active_record/legacy_yaml_adapter.rb +3 -36
- data/lib/active_record/locking/optimistic.rb +64 -33
- data/lib/active_record/locking/pessimistic.rb +21 -8
- data/lib/active_record/log_subscriber.rb +61 -30
- data/lib/active_record/marshalling.rb +59 -0
- data/lib/active_record/message_pack.rb +124 -0
- data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +19 -19
- data/lib/active_record/middleware/database_selector.rb +25 -13
- data/lib/active_record/middleware/shard_selector.rb +62 -0
- data/lib/active_record/migration/command_recorder.rb +160 -55
- data/lib/active_record/migration/compatibility.rb +286 -43
- data/lib/active_record/migration/default_strategy.rb +22 -0
- data/lib/active_record/migration/execution_strategy.rb +19 -0
- data/lib/active_record/migration/join_table.rb +1 -2
- data/lib/active_record/migration/pending_migration_connection.rb +21 -0
- data/lib/active_record/migration.rb +421 -193
- data/lib/active_record/model_schema.rb +217 -125
- data/lib/active_record/nested_attributes.rb +62 -27
- data/lib/active_record/no_touching.rb +4 -4
- data/lib/active_record/normalization.rb +163 -0
- data/lib/active_record/persistence.rb +322 -319
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +18 -15
- data/lib/active_record/query_logs.rb +193 -0
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +54 -14
- data/lib/active_record/railtie.rb +250 -72
- data/lib/active_record/railties/console_sandbox.rb +2 -4
- data/lib/active_record/railties/controller_runtime.rb +25 -11
- data/lib/active_record/railties/databases.rake +312 -197
- data/lib/active_record/railties/job_runtime.rb +23 -0
- data/lib/active_record/readonly_attributes.rb +45 -3
- data/lib/active_record/reflection.rb +389 -146
- data/lib/active_record/relation/batches/batch_enumerator.rb +61 -16
- data/lib/active_record/relation/batches.rb +214 -73
- data/lib/active_record/relation/calculations.rb +379 -124
- data/lib/active_record/relation/delegation.rb +36 -23
- data/lib/active_record/relation/finder_methods.rb +159 -49
- data/lib/active_record/relation/from_clause.rb +5 -1
- data/lib/active_record/relation/merger.rb +41 -33
- data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -11
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -7
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +20 -13
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
- data/lib/active_record/relation/predicate_builder.rb +79 -53
- data/lib/active_record/relation/query_attribute.rb +30 -12
- data/lib/active_record/relation/query_methods.rb +1156 -279
- data/lib/active_record/relation/record_fetch_warning.rb +12 -11
- data/lib/active_record/relation/spawn_methods.rb +10 -9
- data/lib/active_record/relation/where_clause.rb +100 -66
- data/lib/active_record/relation.rb +829 -194
- data/lib/active_record/result.rb +76 -56
- data/lib/active_record/runtime_registry.rb +71 -13
- data/lib/active_record/sanitization.rb +86 -47
- data/lib/active_record/schema.rb +39 -23
- data/lib/active_record/schema_dumper.rb +140 -33
- data/lib/active_record/schema_migration.rb +74 -29
- data/lib/active_record/scoping/default.rb +73 -19
- data/lib/active_record/scoping/named.rb +10 -28
- data/lib/active_record/scoping.rb +65 -35
- data/lib/active_record/secure_password.rb +60 -0
- data/lib/active_record/secure_token.rb +34 -8
- data/lib/active_record/serialization.rb +11 -4
- data/lib/active_record/signed_id.rb +138 -0
- data/lib/active_record/statement_cache.rb +26 -10
- data/lib/active_record/store.rb +19 -14
- data/lib/active_record/suppressor.rb +15 -17
- data/lib/active_record/table_metadata.rb +46 -36
- data/lib/active_record/tasks/database_tasks.rb +371 -205
- data/lib/active_record/tasks/mysql_database_tasks.rb +43 -36
- data/lib/active_record/tasks/postgresql_database_tasks.rb +54 -41
- data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -13
- data/lib/active_record/test_databases.rb +5 -4
- data/lib/active_record/test_fixtures.rb +189 -104
- data/lib/active_record/testing/query_assertions.rb +121 -0
- data/lib/active_record/timestamp.rb +35 -25
- data/lib/active_record/token_for.rb +123 -0
- data/lib/active_record/touch_later.rb +31 -27
- data/lib/active_record/transaction.rb +132 -0
- data/lib/active_record/transactions.rb +131 -99
- data/lib/active_record/translation.rb +3 -5
- data/lib/active_record/type/adapter_specific_registry.rb +33 -18
- data/lib/active_record/type/hash_lookup_type_map.rb +34 -2
- data/lib/active_record/type/internal/timezone.rb +7 -2
- data/lib/active_record/type/serialized.rb +11 -6
- data/lib/active_record/type/time.rb +14 -0
- data/lib/active_record/type/type_map.rb +17 -21
- data/lib/active_record/type/unsigned_integer.rb +0 -1
- data/lib/active_record/type.rb +7 -2
- data/lib/active_record/type_caster/connection.rb +4 -5
- data/lib/active_record/type_caster/map.rb +8 -5
- data/lib/active_record/validations/absence.rb +1 -1
- data/lib/active_record/validations/associated.rb +13 -8
- data/lib/active_record/validations/numericality.rb +36 -0
- data/lib/active_record/validations/presence.rb +5 -28
- data/lib/active_record/validations/uniqueness.rb +88 -18
- data/lib/active_record/validations.rb +15 -8
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +446 -40
- data/lib/arel/alias_predication.rb +1 -1
- data/lib/arel/attributes/attribute.rb +4 -8
- data/lib/arel/collectors/bind.rb +8 -1
- data/lib/arel/collectors/composite.rb +15 -0
- data/lib/arel/collectors/sql_string.rb +7 -0
- data/lib/arel/collectors/substitute_binds.rb +7 -0
- data/lib/arel/crud.rb +30 -22
- data/lib/arel/delete_manager.rb +23 -4
- data/lib/arel/errors.rb +10 -0
- data/lib/arel/factory_methods.rb +4 -0
- data/lib/arel/filter_predications.rb +9 -0
- data/lib/arel/insert_manager.rb +2 -3
- data/lib/arel/nodes/binary.rb +82 -9
- data/lib/arel/nodes/bind_param.rb +8 -0
- data/lib/arel/nodes/bound_sql_literal.rb +65 -0
- data/lib/arel/nodes/casted.rb +22 -10
- data/lib/arel/nodes/cte.rb +36 -0
- data/lib/arel/nodes/delete_statement.rb +14 -13
- data/lib/arel/nodes/equality.rb +6 -9
- data/lib/arel/nodes/filter.rb +10 -0
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/function.rb +1 -0
- data/lib/arel/nodes/grouping.rb +3 -0
- data/lib/arel/nodes/homogeneous_in.rb +68 -0
- data/lib/arel/nodes/in.rb +8 -1
- data/lib/arel/nodes/infix_operation.rb +13 -1
- data/lib/arel/nodes/insert_statement.rb +2 -2
- data/lib/arel/nodes/join_source.rb +1 -1
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/{and.rb → nary.rb} +9 -2
- data/lib/arel/nodes/node.rb +122 -11
- data/lib/arel/nodes/ordering.rb +27 -0
- data/lib/arel/nodes/select_core.rb +2 -2
- data/lib/arel/nodes/select_statement.rb +2 -2
- data/lib/arel/nodes/sql_literal.rb +16 -0
- data/lib/arel/nodes/table_alias.rb +11 -3
- data/lib/arel/nodes/unary.rb +0 -1
- data/lib/arel/nodes/update_statement.rb +11 -4
- data/lib/arel/nodes.rb +10 -3
- data/lib/arel/predications.rb +31 -28
- data/lib/arel/select_manager.rb +18 -9
- data/lib/arel/table.rb +21 -10
- data/lib/arel/tree_manager.rb +8 -15
- data/lib/arel/update_manager.rb +25 -5
- data/lib/arel/visitors/dot.rb +94 -90
- data/lib/arel/visitors/mysql.rb +34 -6
- data/lib/arel/visitors/postgresql.rb +5 -16
- data/lib/arel/visitors/sqlite.rb +25 -1
- data/lib/arel/visitors/to_sql.rb +227 -81
- data/lib/arel/visitors/visitor.rb +2 -3
- data/lib/arel/visitors.rb +0 -7
- data/lib/arel.rb +37 -15
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +6 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -4
- data/lib/rails/generators/active_record/migration.rb +9 -3
- data/lib/rails/generators/active_record/model/USAGE +113 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +49 -4
- 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 +1 -1
- data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
- data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
- data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
- metadata +117 -30
- data/lib/active_record/attribute_decorators.rb +0 -90
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -297
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
- data/lib/active_record/define_callbacks.rb +0 -22
- data/lib/active_record/null_relation.rb +0 -68
- data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
- data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
- data/lib/active_record/relation/where_clause_factory.rb +0 -33
- data/lib/arel/attributes.rb +0 -22
- data/lib/arel/visitors/depth_first.rb +0 -204
- data/lib/arel/visitors/ibm_db.rb +0 -34
- data/lib/arel/visitors/informix.rb +0 -62
- data/lib/arel/visitors/mssql.rb +0 -157
- data/lib/arel/visitors/oracle.rb +0 -159
- data/lib/arel/visitors/oracle12.rb +0 -66
- data/lib/arel/visitors/where_sql.rb +0 -23
data/MIT-LICENSE
CHANGED
data/README.rdoc
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
= Active Record -- Object-relational mapping in Rails
|
|
1
|
+
= Active Record -- Object-relational mapping in \Rails
|
|
2
2
|
|
|
3
3
|
Active Record connects classes to relational database tables to establish an
|
|
4
4
|
almost zero-configuration persistence layer for applications. The library
|
|
@@ -13,29 +13,28 @@ columns. Although these mappings can be defined explicitly, it's recommended
|
|
|
13
13
|
to follow naming conventions, especially when getting started with the
|
|
14
14
|
library.
|
|
15
15
|
|
|
16
|
-
You can read more about Active Record in the {Active Record Basics}[https://
|
|
16
|
+
You can read more about Active Record in the {Active Record Basics}[https://guides.rubyonrails.org/active_record_basics.html] guide.
|
|
17
17
|
|
|
18
18
|
A short rundown of some of the major features:
|
|
19
19
|
|
|
20
20
|
* Automated mapping between classes and tables, attributes and columns.
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
{Learn more}[link:classes/ActiveRecord/Base.html]
|
|
22
|
+
class Product < ActiveRecord::Base
|
|
23
|
+
end
|
|
26
24
|
|
|
27
|
-
The Product class is automatically mapped to the table named "products",
|
|
28
|
-
which might look like this:
|
|
25
|
+
The Product class is automatically mapped to the table named "products",
|
|
26
|
+
which might look like this:
|
|
29
27
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
28
|
+
CREATE TABLE products (
|
|
29
|
+
id bigint NOT NULL auto_increment,
|
|
30
|
+
name varchar(255),
|
|
31
|
+
PRIMARY KEY (id)
|
|
32
|
+
);
|
|
35
33
|
|
|
36
|
-
This would also define the following accessors: <tt>Product#name</tt> and
|
|
37
|
-
<tt>Product#name=(new_name)</tt>.
|
|
34
|
+
This would also define the following accessors: <tt>Product#name</tt> and
|
|
35
|
+
<tt>Product#name=(new_name)</tt>.
|
|
38
36
|
|
|
37
|
+
{Learn more}[https://api.rubyonrails.org/classes/ActiveRecord/Base.html]
|
|
39
38
|
|
|
40
39
|
* Associations between objects defined by simple class methods.
|
|
41
40
|
|
|
@@ -45,7 +44,7 @@ This would also define the following accessors: <tt>Product#name</tt> and
|
|
|
45
44
|
belongs_to :conglomerate
|
|
46
45
|
end
|
|
47
46
|
|
|
48
|
-
{Learn more}[
|
|
47
|
+
{Learn more}[https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html]
|
|
49
48
|
|
|
50
49
|
|
|
51
50
|
* Aggregations of value objects.
|
|
@@ -57,7 +56,7 @@ This would also define the following accessors: <tt>Product#name</tt> and
|
|
|
57
56
|
mapping: [%w(address_street street), %w(address_city city)]
|
|
58
57
|
end
|
|
59
58
|
|
|
60
|
-
{Learn more}[
|
|
59
|
+
{Learn more}[https://api.rubyonrails.org/classes/ActiveRecord/Aggregations/ClassMethods.html]
|
|
61
60
|
|
|
62
61
|
|
|
63
62
|
* Validation rules that can differ for new or existing objects.
|
|
@@ -69,7 +68,7 @@ This would also define the following accessors: <tt>Product#name</tt> and
|
|
|
69
68
|
validates :password, :email_address, confirmation: true, on: :create
|
|
70
69
|
end
|
|
71
70
|
|
|
72
|
-
{Learn more}[
|
|
71
|
+
{Learn more}[https://api.rubyonrails.org/classes/ActiveRecord/Validations.html]
|
|
73
72
|
|
|
74
73
|
|
|
75
74
|
* Callbacks available for the entire life cycle (instantiation, saving, destroying, validating, etc.).
|
|
@@ -79,7 +78,7 @@ This would also define the following accessors: <tt>Product#name</tt> and
|
|
|
79
78
|
# the `invalidate_payment_plan` method gets called just before Person#destroy
|
|
80
79
|
end
|
|
81
80
|
|
|
82
|
-
{Learn more}[
|
|
81
|
+
{Learn more}[https://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html]
|
|
83
82
|
|
|
84
83
|
|
|
85
84
|
* Inheritance hierarchies.
|
|
@@ -89,7 +88,7 @@ This would also define the following accessors: <tt>Product#name</tt> and
|
|
|
89
88
|
class Client < Company; end
|
|
90
89
|
class PriorityClient < Client; end
|
|
91
90
|
|
|
92
|
-
{Learn more}[
|
|
91
|
+
{Learn more}[https://api.rubyonrails.org/classes/ActiveRecord/Base.html]
|
|
93
92
|
|
|
94
93
|
|
|
95
94
|
* Transactions.
|
|
@@ -100,7 +99,7 @@ This would also define the following accessors: <tt>Product#name</tt> and
|
|
|
100
99
|
mary.deposit(100)
|
|
101
100
|
end
|
|
102
101
|
|
|
103
|
-
{Learn more}[
|
|
102
|
+
{Learn more}[https://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html]
|
|
104
103
|
|
|
105
104
|
|
|
106
105
|
* Reflections on columns, associations, and aggregations.
|
|
@@ -109,7 +108,7 @@ This would also define the following accessors: <tt>Product#name</tt> and
|
|
|
109
108
|
reflection.klass # => Client (class)
|
|
110
109
|
Firm.columns # Returns an array of column descriptors for the firms table
|
|
111
110
|
|
|
112
|
-
{Learn more}[
|
|
111
|
+
{Learn more}[https://api.rubyonrails.org/classes/ActiveRecord/Reflection/ClassMethods.html]
|
|
113
112
|
|
|
114
113
|
|
|
115
114
|
* Database abstraction through simple adapters.
|
|
@@ -126,13 +125,13 @@ This would also define the following accessors: <tt>Product#name</tt> and
|
|
|
126
125
|
database: 'activerecord'
|
|
127
126
|
)
|
|
128
127
|
|
|
129
|
-
{Learn more}[
|
|
130
|
-
MySQL[
|
|
131
|
-
PostgreSQL[
|
|
132
|
-
SQLite3[
|
|
128
|
+
{Learn more}[https://api.rubyonrails.org/classes/ActiveRecord/Base.html] and read about the built-in support for
|
|
129
|
+
MySQL[https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/Mysql2Adapter.html],
|
|
130
|
+
PostgreSQL[https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/PostgreSQLAdapter.html], and
|
|
131
|
+
SQLite3[https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/SQLite3Adapter.html].
|
|
133
132
|
|
|
134
133
|
|
|
135
|
-
* Logging support for Log4r[https://github.com/colbygk/log4r] and Logger[
|
|
134
|
+
* Logging support for Log4r[https://github.com/colbygk/log4r] and Logger[https://docs.ruby-lang.org/en/master/Logger.html].
|
|
136
135
|
|
|
137
136
|
ActiveRecord::Base.logger = ActiveSupport::Logger.new(STDOUT)
|
|
138
137
|
ActiveRecord::Base.logger = Log4r::Logger.new('Application Log')
|
|
@@ -140,7 +139,7 @@ This would also define the following accessors: <tt>Product#name</tt> and
|
|
|
140
139
|
|
|
141
140
|
* Database agnostic schema management with Migrations.
|
|
142
141
|
|
|
143
|
-
class AddSystemSettings < ActiveRecord::Migration[
|
|
142
|
+
class AddSystemSettings < ActiveRecord::Migration[7.2]
|
|
144
143
|
def up
|
|
145
144
|
create_table :system_settings do |t|
|
|
146
145
|
t.string :name
|
|
@@ -158,7 +157,7 @@ This would also define the following accessors: <tt>Product#name</tt> and
|
|
|
158
157
|
end
|
|
159
158
|
end
|
|
160
159
|
|
|
161
|
-
{Learn more}[
|
|
160
|
+
{Learn more}[https://api.rubyonrails.org/classes/ActiveRecord/Migration.html]
|
|
162
161
|
|
|
163
162
|
|
|
164
163
|
== Philosophy
|
|
@@ -167,6 +166,7 @@ Active Record is an implementation of the object-relational mapping (ORM)
|
|
|
167
166
|
pattern[https://www.martinfowler.com/eaaCatalog/activeRecord.html] by the same
|
|
168
167
|
name described by Martin Fowler:
|
|
169
168
|
|
|
169
|
+
>>>
|
|
170
170
|
"An object that wraps a row in a database table or view,
|
|
171
171
|
encapsulates the database access, and adds domain logic on that data."
|
|
172
172
|
|
|
@@ -192,9 +192,9 @@ The latest version of Active Record can be installed with RubyGems:
|
|
|
192
192
|
|
|
193
193
|
$ gem install activerecord
|
|
194
194
|
|
|
195
|
-
Source code can be downloaded as part of the Rails project on GitHub:
|
|
195
|
+
Source code can be downloaded as part of the \Rails project on GitHub:
|
|
196
196
|
|
|
197
|
-
* https://github.com/rails/rails/tree/
|
|
197
|
+
* https://github.com/rails/rails/tree/main/activerecord
|
|
198
198
|
|
|
199
199
|
|
|
200
200
|
== License
|
|
@@ -210,10 +210,10 @@ API documentation is at:
|
|
|
210
210
|
|
|
211
211
|
* https://api.rubyonrails.org
|
|
212
212
|
|
|
213
|
-
Bug reports for the Ruby on Rails project can be filed here:
|
|
213
|
+
Bug reports for the Ruby on \Rails project can be filed here:
|
|
214
214
|
|
|
215
215
|
* https://github.com/rails/rails/issues
|
|
216
216
|
|
|
217
|
-
Feature requests should be discussed on the
|
|
217
|
+
Feature requests should be discussed on the rubyonrails-core forum here:
|
|
218
218
|
|
|
219
|
-
* https://
|
|
219
|
+
* https://discuss.rubyonrails.org/c/rubyonrails-core
|
data/examples/performance.rb
CHANGED
|
@@ -176,10 +176,10 @@ Benchmark.ips(TIME) do |x|
|
|
|
176
176
|
end
|
|
177
177
|
|
|
178
178
|
x.report "Model.log" do
|
|
179
|
-
Exhibit.
|
|
179
|
+
Exhibit.lease_connection.send(:log, "hello", "world") { }
|
|
180
180
|
end
|
|
181
181
|
|
|
182
182
|
x.report "AR.execute(query)" do
|
|
183
|
-
ActiveRecord::Base.
|
|
183
|
+
ActiveRecord::Base.lease_connection.execute("SELECT * FROM exhibits WHERE id = #{(rand * 1000 + 1).to_i}")
|
|
184
184
|
end
|
|
185
185
|
end
|
|
@@ -4,7 +4,7 @@ module ActiveRecord
|
|
|
4
4
|
# See ActiveRecord::Aggregations::ClassMethods for documentation
|
|
5
5
|
module Aggregations
|
|
6
6
|
def initialize_dup(*) # :nodoc:
|
|
7
|
-
@aggregation_cache =
|
|
7
|
+
@aggregation_cache = @aggregation_cache.dup
|
|
8
8
|
super
|
|
9
9
|
end
|
|
10
10
|
|
|
@@ -14,16 +14,17 @@ module ActiveRecord
|
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
private
|
|
17
|
-
|
|
18
17
|
def clear_aggregation_cache
|
|
19
18
|
@aggregation_cache.clear if persisted?
|
|
20
19
|
end
|
|
21
20
|
|
|
22
21
|
def init_internals
|
|
23
|
-
@aggregation_cache = {}
|
|
24
22
|
super
|
|
23
|
+
@aggregation_cache = {}
|
|
25
24
|
end
|
|
26
25
|
|
|
26
|
+
# = Active Record \Aggregations
|
|
27
|
+
#
|
|
27
28
|
# Active Record implements aggregation through a macro-like class method called #composed_of
|
|
28
29
|
# for representing attributes as value objects. It expresses relationships like "Account [is]
|
|
29
30
|
# composed of Money [among other things]" or "Person [is] composed of [an] address". Each call
|
|
@@ -33,8 +34,8 @@ module ActiveRecord
|
|
|
33
34
|
# the database).
|
|
34
35
|
#
|
|
35
36
|
# class Customer < ActiveRecord::Base
|
|
36
|
-
# composed_of :balance, class_name: "Money", mapping:
|
|
37
|
-
# composed_of :address, mapping:
|
|
37
|
+
# composed_of :balance, class_name: "Money", mapping: { balance: :amount }
|
|
38
|
+
# composed_of :address, mapping: { address_street: :street, address_city: :city }
|
|
38
39
|
# end
|
|
39
40
|
#
|
|
40
41
|
# The customer class now has the following methods to manipulate the value objects:
|
|
@@ -142,7 +143,7 @@ module ActiveRecord
|
|
|
142
143
|
# converted to an instance of value class if necessary.
|
|
143
144
|
#
|
|
144
145
|
# For example, the +NetworkResource+ model has +network_address+ and +cidr_range+ attributes that should be
|
|
145
|
-
# aggregated using the +NetAddr::CIDR+ value class (
|
|
146
|
+
# aggregated using the +NetAddr::CIDR+ value class (https://www.rubydoc.info/gems/netaddr/1.5.0/NetAddr/CIDR).
|
|
146
147
|
# The constructor for the value class is called +create+ and it expects a CIDR address string as a parameter.
|
|
147
148
|
# New values can be assigned to the value object using either another +NetAddr::CIDR+ object, a string
|
|
148
149
|
# or an array. The <tt>:constructor</tt> and <tt>:converter</tt> options can be used to meet
|
|
@@ -151,7 +152,7 @@ module ActiveRecord
|
|
|
151
152
|
# class NetworkResource < ActiveRecord::Base
|
|
152
153
|
# composed_of :cidr,
|
|
153
154
|
# class_name: 'NetAddr::CIDR',
|
|
154
|
-
# mapping:
|
|
155
|
+
# mapping: { network_address: :network, cidr_range: :bits },
|
|
155
156
|
# allow_nil: true,
|
|
156
157
|
# constructor: Proc.new { |network_address, cidr_range| NetAddr::CIDR.create("#{network_address}/#{cidr_range}") },
|
|
157
158
|
# converter: Proc.new { |value| NetAddr::CIDR.create(value.is_a?(Array) ? value.join('/') : value) }
|
|
@@ -189,10 +190,10 @@ module ActiveRecord
|
|
|
189
190
|
# to the Address class, but if the real class name is +CompanyAddress+, you'll have to specify it
|
|
190
191
|
# with this option.
|
|
191
192
|
# * <tt>:mapping</tt> - Specifies the mapping of entity attributes to attributes of the value
|
|
192
|
-
# object. Each mapping is represented as
|
|
193
|
-
# entity attribute and the
|
|
193
|
+
# object. Each mapping is represented as a key-value pair where the key is the name of the
|
|
194
|
+
# entity attribute and the value is the name of the attribute in the value object. The
|
|
194
195
|
# order in which mappings are defined determines the order in which attributes are sent to the
|
|
195
|
-
# value class constructor.
|
|
196
|
+
# value class constructor. The mapping can be written as a hash or as an array of pairs.
|
|
196
197
|
# * <tt>:allow_nil</tt> - Specifies that the value object will not be instantiated when all mapped
|
|
197
198
|
# attributes are +nil+. Setting the value object to +nil+ has the effect of writing +nil+ to all
|
|
198
199
|
# mapped attributes.
|
|
@@ -209,14 +210,15 @@ module ActiveRecord
|
|
|
209
210
|
# can return +nil+ to skip the assignment.
|
|
210
211
|
#
|
|
211
212
|
# Option examples:
|
|
212
|
-
# composed_of :temperature, mapping:
|
|
213
|
-
# composed_of :balance, class_name: "Money", mapping:
|
|
213
|
+
# composed_of :temperature, mapping: { reading: :celsius }
|
|
214
|
+
# composed_of :balance, class_name: "Money", mapping: { balance: :amount }
|
|
215
|
+
# composed_of :address, mapping: { address_street: :street, address_city: :city }
|
|
214
216
|
# composed_of :address, mapping: [ %w(address_street street), %w(address_city city) ]
|
|
215
217
|
# composed_of :gps_location
|
|
216
218
|
# composed_of :gps_location, allow_nil: true
|
|
217
219
|
# composed_of :ip_address,
|
|
218
220
|
# class_name: 'IPAddr',
|
|
219
|
-
# mapping:
|
|
221
|
+
# mapping: { ip: :to_i },
|
|
220
222
|
# constructor: Proc.new { |ip| IPAddr.new(ip, Socket::AF_INET) },
|
|
221
223
|
# converter: Proc.new { |ip| ip.is_a?(Integer) ? IPAddr.new(ip, Socket::AF_INET) : IPAddr.new(ip.to_s) }
|
|
222
224
|
#
|
|
@@ -245,12 +247,12 @@ module ActiveRecord
|
|
|
245
247
|
private
|
|
246
248
|
def reader_method(name, class_name, mapping, allow_nil, constructor)
|
|
247
249
|
define_method(name) do
|
|
248
|
-
if @aggregation_cache[name].nil? && (!allow_nil || mapping.any? { |key, _| !
|
|
249
|
-
attrs = mapping.collect { |key, _|
|
|
250
|
+
if @aggregation_cache[name].nil? && (!allow_nil || mapping.any? { |key, _| !read_attribute(key).nil? })
|
|
251
|
+
attrs = mapping.collect { |key, _| read_attribute(key) }
|
|
250
252
|
object = constructor.respond_to?(:call) ?
|
|
251
253
|
constructor.call(*attrs) :
|
|
252
254
|
class_name.constantize.send(constructor, *attrs)
|
|
253
|
-
@aggregation_cache[name] = object
|
|
255
|
+
@aggregation_cache[name] = object.freeze
|
|
254
256
|
end
|
|
255
257
|
@aggregation_cache[name]
|
|
256
258
|
end
|
|
@@ -265,18 +267,18 @@ module ActiveRecord
|
|
|
265
267
|
end
|
|
266
268
|
|
|
267
269
|
hash_from_multiparameter_assignment = part.is_a?(Hash) &&
|
|
268
|
-
part.
|
|
270
|
+
part.keys.all?(Integer)
|
|
269
271
|
if hash_from_multiparameter_assignment
|
|
270
272
|
raise ArgumentError unless part.size == part.each_key.max
|
|
271
273
|
part = klass.new(*part.sort.map(&:last))
|
|
272
274
|
end
|
|
273
275
|
|
|
274
276
|
if part.nil? && allow_nil
|
|
275
|
-
mapping.each { |key, _|
|
|
277
|
+
mapping.each { |key, _| write_attribute(key, nil) }
|
|
276
278
|
@aggregation_cache[name] = nil
|
|
277
279
|
else
|
|
278
|
-
mapping.each { |key, value|
|
|
279
|
-
@aggregation_cache[name] = part.freeze
|
|
280
|
+
mapping.each { |key, value| write_attribute(key, part.send(value)) }
|
|
281
|
+
@aggregation_cache[name] = part.dup.freeze
|
|
280
282
|
end
|
|
281
283
|
end
|
|
282
284
|
end
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module ActiveRecord
|
|
4
|
-
class AssociationRelation < Relation
|
|
5
|
-
def initialize(klass, association)
|
|
4
|
+
class AssociationRelation < Relation # :nodoc:
|
|
5
|
+
def initialize(klass, association, **)
|
|
6
6
|
super(klass)
|
|
7
7
|
@association = association
|
|
8
8
|
end
|
|
@@ -15,20 +15,30 @@ module ActiveRecord
|
|
|
15
15
|
other == records
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
scoping { @association.create(*args, &block) }
|
|
25
|
-
end
|
|
18
|
+
%w(insert insert_all insert! insert_all! upsert upsert_all).each do |method|
|
|
19
|
+
class_eval <<~RUBY, __FILE__, __LINE__ + 1
|
|
20
|
+
def #{method}(attributes, **kwargs)
|
|
21
|
+
if @association.reflection.through_reflection?
|
|
22
|
+
raise ArgumentError, "Bulk insert or upsert is currently not supported for has_many through association"
|
|
23
|
+
end
|
|
26
24
|
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
super
|
|
26
|
+
end
|
|
27
|
+
RUBY
|
|
29
28
|
end
|
|
30
29
|
|
|
31
30
|
private
|
|
31
|
+
def _new(attributes, &block)
|
|
32
|
+
@association.build(attributes, &block)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def _create(attributes, &block)
|
|
36
|
+
@association.create(attributes, &block)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def _create!(attributes, &block)
|
|
40
|
+
@association.create!(attributes, &block)
|
|
41
|
+
end
|
|
32
42
|
|
|
33
43
|
def exec_queries
|
|
34
44
|
super do |record|
|
|
@@ -6,34 +6,41 @@ module ActiveRecord
|
|
|
6
6
|
module Associations
|
|
7
7
|
# Keeps track of table aliases for ActiveRecord::Associations::JoinDependency
|
|
8
8
|
class AliasTracker # :nodoc:
|
|
9
|
-
def self.create(
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
aliases
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
def self.create(pool, initial_table, joins, aliases = nil)
|
|
10
|
+
pool.with_connection do |connection|
|
|
11
|
+
if joins.empty?
|
|
12
|
+
aliases ||= Hash.new(0)
|
|
13
|
+
elsif aliases
|
|
14
|
+
default_proc = aliases.default_proc || proc { 0 }
|
|
15
|
+
aliases.default_proc = proc { |h, k|
|
|
16
|
+
h[k] = initial_count_for(connection, k, joins) + default_proc.call(h, k)
|
|
17
|
+
}
|
|
18
|
+
else
|
|
19
|
+
aliases = Hash.new { |h, k|
|
|
20
|
+
h[k] = initial_count_for(connection, k, joins)
|
|
21
|
+
}
|
|
22
|
+
end
|
|
23
|
+
aliases[initial_table] = 1
|
|
24
|
+
new(connection.table_alias_length, aliases)
|
|
16
25
|
end
|
|
17
|
-
aliases[initial_table] = 1
|
|
18
|
-
new(connection, aliases)
|
|
19
26
|
end
|
|
20
27
|
|
|
21
28
|
def self.initial_count_for(connection, name, table_joins)
|
|
22
|
-
|
|
29
|
+
quoted_name_escaped = nil
|
|
30
|
+
name_escaped = nil
|
|
23
31
|
|
|
24
32
|
counts = table_joins.map do |join|
|
|
25
33
|
if join.is_a?(Arel::Nodes::StringJoin)
|
|
26
|
-
#
|
|
27
|
-
|
|
34
|
+
# quoted_name_escaped should be case ignored as some database adapters (Oracle) return quoted name in uppercase
|
|
35
|
+
quoted_name_escaped ||= Regexp.escape(connection.quote_table_name(name))
|
|
36
|
+
name_escaped ||= Regexp.escape(name)
|
|
28
37
|
|
|
29
38
|
# Table names + table aliases
|
|
30
39
|
join.left.scan(
|
|
31
|
-
/JOIN(?:\s+\w+)?\s+(?:\S+\s+)?(?:#{
|
|
40
|
+
/JOIN(?:\s+\w+)?\s+(?:\S+\s+)?(?:#{quoted_name_escaped}|#{name_escaped})\sON/i
|
|
32
41
|
).size
|
|
33
42
|
elsif join.is_a?(Arel::Nodes::Join)
|
|
34
43
|
join.left.name == name ? 1 : 0
|
|
35
|
-
elsif join.is_a?(Hash)
|
|
36
|
-
join[name]
|
|
37
44
|
else
|
|
38
45
|
raise ArgumentError, "joins list should be initialized by list of Arel::Nodes::Join"
|
|
39
46
|
end
|
|
@@ -43,38 +50,42 @@ module ActiveRecord
|
|
|
43
50
|
end
|
|
44
51
|
|
|
45
52
|
# table_joins is an array of arel joins which might conflict with the aliases we assign here
|
|
46
|
-
def initialize(
|
|
47
|
-
@aliases
|
|
48
|
-
@
|
|
53
|
+
def initialize(table_alias_length, aliases)
|
|
54
|
+
@aliases = aliases
|
|
55
|
+
@table_alias_length = table_alias_length
|
|
49
56
|
end
|
|
50
57
|
|
|
51
|
-
def aliased_table_for(
|
|
52
|
-
|
|
58
|
+
def aliased_table_for(arel_table, table_name = nil)
|
|
59
|
+
table_name ||= arel_table.name
|
|
60
|
+
|
|
61
|
+
if aliases[table_name] == 0
|
|
53
62
|
# If it's zero, we can have our table_name
|
|
54
63
|
aliases[table_name] = 1
|
|
55
|
-
|
|
64
|
+
arel_table = arel_table.alias(table_name) if arel_table.name != table_name
|
|
56
65
|
else
|
|
57
66
|
# Otherwise, we need to use an alias
|
|
58
|
-
aliased_name =
|
|
67
|
+
aliased_name = table_alias_for(yield)
|
|
59
68
|
|
|
60
69
|
# Update the count
|
|
61
|
-
aliases[aliased_name] += 1
|
|
70
|
+
count = aliases[aliased_name] += 1
|
|
62
71
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
aliased_name
|
|
67
|
-
end
|
|
68
|
-
Arel::Table.new(table_name, type_caster: type_caster).alias(table_alias)
|
|
72
|
+
aliased_name = "#{truncate(aliased_name)}_#{count}" if count > 1
|
|
73
|
+
|
|
74
|
+
arel_table = arel_table.alias(aliased_name)
|
|
69
75
|
end
|
|
76
|
+
|
|
77
|
+
arel_table
|
|
70
78
|
end
|
|
71
79
|
|
|
72
80
|
attr_reader :aliases
|
|
73
81
|
|
|
74
82
|
private
|
|
83
|
+
def table_alias_for(table_name)
|
|
84
|
+
table_name[0...@table_alias_length].tr(".", "_")
|
|
85
|
+
end
|
|
75
86
|
|
|
76
87
|
def truncate(name)
|
|
77
|
-
name.slice(0, @
|
|
88
|
+
name.slice(0, @table_alias_length - 2)
|
|
78
89
|
end
|
|
79
90
|
end
|
|
80
91
|
end
|