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
|
@@ -7,14 +7,13 @@ module ActiveRecord
|
|
|
7
7
|
#
|
|
8
8
|
# This class is used to dump the database schema for some connection to some
|
|
9
9
|
# output format (i.e., ActiveRecord::Schema).
|
|
10
|
-
class SchemaDumper
|
|
10
|
+
class SchemaDumper # :nodoc:
|
|
11
11
|
private_class_method :new
|
|
12
12
|
|
|
13
13
|
##
|
|
14
14
|
# :singleton-method:
|
|
15
15
|
# A list of tables which should not be dumped to the schema.
|
|
16
|
-
# Acceptable values are strings
|
|
17
|
-
# Only strings are accepted if ActiveRecord::Base.schema_format == :sql.
|
|
16
|
+
# Acceptable values are strings and regexps.
|
|
18
17
|
cattr_accessor :ignore_tables, default: []
|
|
19
18
|
|
|
20
19
|
##
|
|
@@ -23,9 +22,29 @@ module ActiveRecord
|
|
|
23
22
|
# should not be dumped to db/schema.rb.
|
|
24
23
|
cattr_accessor :fk_ignore_pattern, default: /^fk_rails_[0-9a-f]{10}$/
|
|
25
24
|
|
|
25
|
+
##
|
|
26
|
+
# :singleton-method:
|
|
27
|
+
# Specify a custom regular expression matching check constraints which name
|
|
28
|
+
# should not be dumped to db/schema.rb.
|
|
29
|
+
cattr_accessor :chk_ignore_pattern, default: /^chk_rails_[0-9a-f]{10}$/
|
|
30
|
+
|
|
31
|
+
##
|
|
32
|
+
# :singleton-method:
|
|
33
|
+
# Specify a custom regular expression matching exclusion constraints which name
|
|
34
|
+
# should not be dumped to db/schema.rb.
|
|
35
|
+
cattr_accessor :excl_ignore_pattern, default: /^excl_rails_[0-9a-f]{10}$/
|
|
36
|
+
|
|
37
|
+
##
|
|
38
|
+
# :singleton-method:
|
|
39
|
+
# Specify a custom regular expression matching unique constraints which name
|
|
40
|
+
# should not be dumped to db/schema.rb.
|
|
41
|
+
cattr_accessor :unique_ignore_pattern, default: /^uniq_rails_[0-9a-f]{10}$/
|
|
42
|
+
|
|
26
43
|
class << self
|
|
27
|
-
def dump(
|
|
28
|
-
connection
|
|
44
|
+
def dump(pool = ActiveRecord::Base.connection_pool, stream = $stdout, config = ActiveRecord::Base)
|
|
45
|
+
pool.with_connection do |connection|
|
|
46
|
+
connection.create_schema_dumper(generate_options(config)).dump(stream)
|
|
47
|
+
end
|
|
29
48
|
stream
|
|
30
49
|
end
|
|
31
50
|
|
|
@@ -40,7 +59,9 @@ module ActiveRecord
|
|
|
40
59
|
|
|
41
60
|
def dump(stream)
|
|
42
61
|
header(stream)
|
|
62
|
+
schemas(stream)
|
|
43
63
|
extensions(stream)
|
|
64
|
+
types(stream)
|
|
44
65
|
tables(stream)
|
|
45
66
|
trailer(stream)
|
|
46
67
|
stream
|
|
@@ -51,8 +72,13 @@ module ActiveRecord
|
|
|
51
72
|
|
|
52
73
|
def initialize(connection, options = {})
|
|
53
74
|
@connection = connection
|
|
54
|
-
@version = connection.migration_context.current_version rescue nil
|
|
75
|
+
@version = connection.pool.migration_context.current_version rescue nil
|
|
55
76
|
@options = options
|
|
77
|
+
@ignore_tables = [
|
|
78
|
+
ActiveRecord::Base.schema_migrations_table_name,
|
|
79
|
+
ActiveRecord::Base.internal_metadata_table_name,
|
|
80
|
+
self.class.ignore_tables
|
|
81
|
+
].flatten
|
|
56
82
|
end
|
|
57
83
|
|
|
58
84
|
# turns 20170404131909 into "2017_04_04_131909"
|
|
@@ -67,22 +93,21 @@ module ActiveRecord
|
|
|
67
93
|
end
|
|
68
94
|
|
|
69
95
|
def header(stream)
|
|
70
|
-
stream.puts
|
|
71
|
-
# This file is auto-generated from the current state of the database. Instead
|
|
72
|
-
# of editing this file, please use the migrations feature of Active Record to
|
|
73
|
-
# incrementally modify your database, and then regenerate this schema definition.
|
|
74
|
-
#
|
|
75
|
-
# This file is the source Rails uses to define your schema when running `rails
|
|
76
|
-
# db:schema:load`. When creating a new database, `rails db:schema:load` tends to
|
|
77
|
-
# be faster and is potentially less error prone than running all of your
|
|
78
|
-
# migrations from scratch. Old migrations may fail to apply correctly if those
|
|
79
|
-
# migrations use external dependencies or application code.
|
|
80
|
-
#
|
|
81
|
-
# It's strongly recommended that you check this file into your version control system.
|
|
82
|
-
|
|
83
|
-
ActiveRecord::Schema.define(#{define_params}) do
|
|
84
|
-
|
|
85
|
-
HEADER
|
|
96
|
+
stream.puts <<~HEADER
|
|
97
|
+
# This file is auto-generated from the current state of the database. Instead
|
|
98
|
+
# of editing this file, please use the migrations feature of Active Record to
|
|
99
|
+
# incrementally modify your database, and then regenerate this schema definition.
|
|
100
|
+
#
|
|
101
|
+
# This file is the source Rails uses to define your schema when running `bin/rails
|
|
102
|
+
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
|
|
103
|
+
# be faster and is potentially less error prone than running all of your
|
|
104
|
+
# migrations from scratch. Old migrations may fail to apply correctly if those
|
|
105
|
+
# migrations use external dependencies or application code.
|
|
106
|
+
#
|
|
107
|
+
# It's strongly recommended that you check this file into your version control system.
|
|
108
|
+
|
|
109
|
+
ActiveRecord::Schema[#{ActiveRecord::Migration.current_version}].define(#{define_params}) do
|
|
110
|
+
HEADER
|
|
86
111
|
end
|
|
87
112
|
|
|
88
113
|
def trailer(stream)
|
|
@@ -93,18 +118,35 @@ HEADER
|
|
|
93
118
|
def extensions(stream)
|
|
94
119
|
end
|
|
95
120
|
|
|
121
|
+
# (enum) types are only supported by PostgreSQL
|
|
122
|
+
def types(stream)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# schemas are only supported by PostgreSQL
|
|
126
|
+
def schemas(stream)
|
|
127
|
+
end
|
|
128
|
+
|
|
96
129
|
def tables(stream)
|
|
97
130
|
sorted_tables = @connection.tables.sort
|
|
98
131
|
|
|
99
|
-
sorted_tables.
|
|
100
|
-
|
|
132
|
+
not_ignored_tables = sorted_tables.reject { |table_name| ignored?(table_name) }
|
|
133
|
+
|
|
134
|
+
not_ignored_tables.each_with_index do |table_name, index|
|
|
135
|
+
table(table_name, stream)
|
|
136
|
+
stream.puts if index < not_ignored_tables.count - 1
|
|
101
137
|
end
|
|
102
138
|
|
|
103
139
|
# dump foreign keys at the end to make sure all dependent tables exist.
|
|
104
140
|
if @connection.supports_foreign_keys?
|
|
105
|
-
|
|
106
|
-
|
|
141
|
+
foreign_keys_stream = StringIO.new
|
|
142
|
+
not_ignored_tables.each do |tbl|
|
|
143
|
+
foreign_keys(tbl, foreign_keys_stream)
|
|
107
144
|
end
|
|
145
|
+
|
|
146
|
+
foreign_keys_string = foreign_keys_stream.string
|
|
147
|
+
stream.puts if foreign_keys_string.length > 0
|
|
148
|
+
|
|
149
|
+
stream.print foreign_keys_string
|
|
108
150
|
end
|
|
109
151
|
end
|
|
110
152
|
|
|
@@ -125,7 +167,10 @@ HEADER
|
|
|
125
167
|
tbl.print ", primary_key: #{pk.inspect}" unless pk == "id"
|
|
126
168
|
pkcol = columns.detect { |c| c.name == pk }
|
|
127
169
|
pkcolspec = column_spec_for_primary_key(pkcol)
|
|
128
|
-
|
|
170
|
+
unless pkcolspec.empty?
|
|
171
|
+
if pkcolspec != pkcolspec.slice(:id, :default)
|
|
172
|
+
pkcolspec = { id: { type: pkcolspec.delete(:id), **pkcolspec }.compact }
|
|
173
|
+
end
|
|
129
174
|
tbl.print ", #{format_colspec(pkcolspec)}"
|
|
130
175
|
end
|
|
131
176
|
when Array
|
|
@@ -145,6 +190,7 @@ HEADER
|
|
|
145
190
|
columns.each do |column|
|
|
146
191
|
raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" unless @connection.valid_type?(column.type)
|
|
147
192
|
next if column.name == pk
|
|
193
|
+
|
|
148
194
|
type, colspec = column_spec(column)
|
|
149
195
|
if type.is_a?(Symbol)
|
|
150
196
|
tbl.print " t.#{type} #{column.name.inspect}"
|
|
@@ -156,12 +202,18 @@ HEADER
|
|
|
156
202
|
end
|
|
157
203
|
|
|
158
204
|
indexes_in_create(table, tbl)
|
|
205
|
+
remaining = check_constraints_in_create(table, tbl) if @connection.supports_check_constraints?
|
|
206
|
+
exclusion_constraints_in_create(table, tbl) if @connection.supports_exclusion_constraints?
|
|
207
|
+
unique_constraints_in_create(table, tbl) if @connection.supports_unique_constraints?
|
|
159
208
|
|
|
160
209
|
tbl.puts " end"
|
|
161
|
-
tbl.puts
|
|
162
210
|
|
|
163
|
-
|
|
164
|
-
|
|
211
|
+
if remaining
|
|
212
|
+
tbl.puts
|
|
213
|
+
tbl.print remaining.string
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
stream.print tbl.string
|
|
165
217
|
rescue => e
|
|
166
218
|
stream.puts "# Could not dump table #{table.inspect} because of following #{e.class}"
|
|
167
219
|
stream.puts "# #{e.message}"
|
|
@@ -186,6 +238,18 @@ HEADER
|
|
|
186
238
|
|
|
187
239
|
def indexes_in_create(table, stream)
|
|
188
240
|
if (indexes = @connection.indexes(table)).any?
|
|
241
|
+
if @connection.supports_exclusion_constraints? && (exclusion_constraints = @connection.exclusion_constraints(table)).any?
|
|
242
|
+
exclusion_constraint_names = exclusion_constraints.collect(&:name)
|
|
243
|
+
|
|
244
|
+
indexes = indexes.reject { |index| exclusion_constraint_names.include?(index.name) }
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
if @connection.supports_unique_constraints? && (unique_constraints = @connection.unique_constraints(table)).any?
|
|
248
|
+
unique_constraint_names = unique_constraints.collect(&:name)
|
|
249
|
+
|
|
250
|
+
indexes = indexes.reject { |index| unique_constraint_names.include?(index.name) }
|
|
251
|
+
end
|
|
252
|
+
|
|
189
253
|
index_statements = indexes.map do |index|
|
|
190
254
|
" t.index #{index_parts(index).join(', ')}"
|
|
191
255
|
end
|
|
@@ -204,11 +268,46 @@ HEADER
|
|
|
204
268
|
index_parts << "opclass: #{format_index_parts(index.opclasses)}" if index.opclasses.present?
|
|
205
269
|
index_parts << "where: #{index.where.inspect}" if index.where
|
|
206
270
|
index_parts << "using: #{index.using.inspect}" if !@connection.default_index_type?(index)
|
|
271
|
+
index_parts << "include: #{index.include.inspect}" if index.include
|
|
272
|
+
index_parts << "nulls_not_distinct: #{index.nulls_not_distinct.inspect}" if index.nulls_not_distinct
|
|
207
273
|
index_parts << "type: #{index.type.inspect}" if index.type
|
|
208
274
|
index_parts << "comment: #{index.comment.inspect}" if index.comment
|
|
209
275
|
index_parts
|
|
210
276
|
end
|
|
211
277
|
|
|
278
|
+
def check_constraints_in_create(table, stream)
|
|
279
|
+
if (check_constraints = @connection.check_constraints(table)).any?
|
|
280
|
+
check_valid, check_invalid = check_constraints.partition { |chk| chk.validate? }
|
|
281
|
+
|
|
282
|
+
unless check_valid.empty?
|
|
283
|
+
check_constraint_statements = check_valid.map do |check|
|
|
284
|
+
" t.check_constraint #{check_parts(check).join(', ')}"
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
stream.puts check_constraint_statements.sort.join("\n")
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
unless check_invalid.empty?
|
|
291
|
+
remaining = StringIO.new
|
|
292
|
+
table_name = remove_prefix_and_suffix(table).inspect
|
|
293
|
+
|
|
294
|
+
add_check_constraint_statements = check_invalid.map do |check|
|
|
295
|
+
" add_check_constraint #{([table_name] + check_parts(check)).join(', ')}"
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
remaining.puts add_check_constraint_statements.sort.join("\n")
|
|
299
|
+
remaining
|
|
300
|
+
end
|
|
301
|
+
end
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
def check_parts(check)
|
|
305
|
+
check_parts = [ check.expression.inspect ]
|
|
306
|
+
check_parts << "name: #{check.name.inspect}" if check.export_name_on_schema_dump?
|
|
307
|
+
check_parts << "validate: #{check.validate?.inspect}" unless check.validate?
|
|
308
|
+
check_parts
|
|
309
|
+
end
|
|
310
|
+
|
|
212
311
|
def foreign_keys(table, stream)
|
|
213
312
|
if (foreign_keys = @connection.foreign_keys(table)).any?
|
|
214
313
|
add_foreign_key_statements = foreign_keys.map do |foreign_key|
|
|
@@ -217,7 +316,7 @@ HEADER
|
|
|
217
316
|
remove_prefix_and_suffix(foreign_key.to_table).inspect,
|
|
218
317
|
]
|
|
219
318
|
|
|
220
|
-
if foreign_key.column != @connection.foreign_key_column_for(foreign_key.to_table)
|
|
319
|
+
if foreign_key.column != @connection.foreign_key_column_for(foreign_key.to_table, "id")
|
|
221
320
|
parts << "column: #{foreign_key.column.inspect}"
|
|
222
321
|
end
|
|
223
322
|
|
|
@@ -231,6 +330,8 @@ HEADER
|
|
|
231
330
|
|
|
232
331
|
parts << "on_update: #{foreign_key.on_update.inspect}" if foreign_key.on_update
|
|
233
332
|
parts << "on_delete: #{foreign_key.on_delete.inspect}" if foreign_key.on_delete
|
|
333
|
+
parts << "deferrable: #{foreign_key.deferrable.inspect}" if foreign_key.deferrable
|
|
334
|
+
parts << "validate: #{foreign_key.validate?.inspect}" unless foreign_key.validate?
|
|
234
335
|
|
|
235
336
|
" #{parts.join(', ')}"
|
|
236
337
|
end
|
|
@@ -240,7 +341,9 @@ HEADER
|
|
|
240
341
|
end
|
|
241
342
|
|
|
242
343
|
def format_colspec(colspec)
|
|
243
|
-
colspec.map
|
|
344
|
+
colspec.map do |key, value|
|
|
345
|
+
"#{key}: #{ value.is_a?(Hash) ? "{ #{format_colspec(value)} }" : value }"
|
|
346
|
+
end.join(", ")
|
|
244
347
|
end
|
|
245
348
|
|
|
246
349
|
def format_options(options)
|
|
@@ -256,13 +359,17 @@ HEADER
|
|
|
256
359
|
end
|
|
257
360
|
|
|
258
361
|
def remove_prefix_and_suffix(table)
|
|
362
|
+
# This method appears at the top when profiling active_record test cases run.
|
|
363
|
+
# Avoid costly calculation when there are no prefix and suffix.
|
|
364
|
+
return table if @options[:table_name_prefix].blank? && @options[:table_name_suffix].blank?
|
|
365
|
+
|
|
259
366
|
prefix = Regexp.escape(@options[:table_name_prefix].to_s)
|
|
260
367
|
suffix = Regexp.escape(@options[:table_name_suffix].to_s)
|
|
261
368
|
table.sub(/\A#{prefix}(.+)#{suffix}\z/, "\\1")
|
|
262
369
|
end
|
|
263
370
|
|
|
264
371
|
def ignored?(table_name)
|
|
265
|
-
|
|
372
|
+
@ignore_tables.any? do |ignored|
|
|
266
373
|
ignored === remove_prefix_and_suffix(table_name)
|
|
267
374
|
end
|
|
268
375
|
end
|
|
@@ -1,60 +1,105 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "active_record/scoping/default"
|
|
4
|
-
require "active_record/scoping/named"
|
|
5
|
-
|
|
6
3
|
module ActiveRecord
|
|
7
4
|
# This class is used to create a table that keeps track of which migrations
|
|
8
5
|
# have been applied to a given database. When a migration is run, its schema
|
|
9
|
-
# number is inserted in to the
|
|
6
|
+
# number is inserted in to the schema migrations table so it doesn't need
|
|
10
7
|
# to be executed the next time.
|
|
11
|
-
class SchemaMigration
|
|
12
|
-
class
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
8
|
+
class SchemaMigration # :nodoc:
|
|
9
|
+
class NullSchemaMigration # :nodoc:
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
attr_reader :arel_table
|
|
16
13
|
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
def initialize(pool)
|
|
15
|
+
@pool = pool
|
|
16
|
+
@arel_table = Arel::Table.new(table_name)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def create_version(version)
|
|
20
|
+
im = Arel::InsertManager.new(arel_table)
|
|
21
|
+
im.insert(arel_table[primary_key] => version)
|
|
22
|
+
@pool.with_connection do |connection|
|
|
23
|
+
connection.insert(im, "#{self.class} Create", primary_key, version)
|
|
19
24
|
end
|
|
25
|
+
end
|
|
20
26
|
|
|
21
|
-
|
|
22
|
-
|
|
27
|
+
def delete_version(version)
|
|
28
|
+
dm = Arel::DeleteManager.new(arel_table)
|
|
29
|
+
dm.wheres = [arel_table[primary_key].eq(version)]
|
|
30
|
+
|
|
31
|
+
@pool.with_connection do |connection|
|
|
32
|
+
connection.delete(dm, "#{self.class} Destroy")
|
|
23
33
|
end
|
|
34
|
+
end
|
|
24
35
|
|
|
25
|
-
|
|
26
|
-
|
|
36
|
+
def delete_all_versions
|
|
37
|
+
@pool.with_connection do |connection|
|
|
38
|
+
versions.each do |version|
|
|
39
|
+
delete_version(version)
|
|
40
|
+
end
|
|
27
41
|
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def primary_key
|
|
45
|
+
"version"
|
|
46
|
+
end
|
|
28
47
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
48
|
+
def table_name
|
|
49
|
+
"#{ActiveRecord::Base.table_name_prefix}#{ActiveRecord::Base.schema_migrations_table_name}#{ActiveRecord::Base.table_name_suffix}"
|
|
50
|
+
end
|
|
32
51
|
|
|
52
|
+
def create_table
|
|
53
|
+
@pool.with_connection do |connection|
|
|
54
|
+
unless connection.table_exists?(table_name)
|
|
33
55
|
connection.create_table(table_name, id: false) do |t|
|
|
34
|
-
t.string :version,
|
|
56
|
+
t.string :version, **connection.internal_string_options_for_primary_key
|
|
35
57
|
end
|
|
36
58
|
end
|
|
37
59
|
end
|
|
60
|
+
end
|
|
38
61
|
|
|
39
|
-
|
|
62
|
+
def drop_table
|
|
63
|
+
@pool.with_connection do |connection|
|
|
40
64
|
connection.drop_table table_name, if_exists: true
|
|
41
65
|
end
|
|
66
|
+
end
|
|
42
67
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
68
|
+
def normalize_migration_number(number)
|
|
69
|
+
"%.3d" % number.to_i
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def normalized_versions
|
|
73
|
+
versions.map { |v| normalize_migration_number v }
|
|
74
|
+
end
|
|
46
75
|
|
|
47
|
-
|
|
48
|
-
|
|
76
|
+
def versions
|
|
77
|
+
sm = Arel::SelectManager.new(arel_table)
|
|
78
|
+
sm.project(arel_table[primary_key])
|
|
79
|
+
sm.order(arel_table[primary_key].asc)
|
|
80
|
+
|
|
81
|
+
@pool.with_connection do |connection|
|
|
82
|
+
connection.select_values(sm, "#{self.class} Load")
|
|
49
83
|
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def integer_versions
|
|
87
|
+
versions.map(&:to_i)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def count
|
|
91
|
+
sm = Arel::SelectManager.new(arel_table)
|
|
92
|
+
sm.project(*Arel::Nodes::Count.new([Arel.star]))
|
|
50
93
|
|
|
51
|
-
|
|
52
|
-
|
|
94
|
+
@pool.with_connection do |connection|
|
|
95
|
+
connection.select_values(sm, "#{self.class} Count").first
|
|
53
96
|
end
|
|
54
97
|
end
|
|
55
98
|
|
|
56
|
-
def
|
|
57
|
-
|
|
99
|
+
def table_exists?
|
|
100
|
+
@pool.with_connection do |connection|
|
|
101
|
+
connection.data_source_exists?(table_name)
|
|
102
|
+
end
|
|
58
103
|
end
|
|
59
104
|
end
|
|
60
105
|
end
|
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
module ActiveRecord
|
|
4
4
|
module Scoping
|
|
5
|
+
class DefaultScope # :nodoc:
|
|
6
|
+
attr_reader :scope, :all_queries
|
|
7
|
+
|
|
8
|
+
def initialize(scope, all_queries = nil)
|
|
9
|
+
@scope = scope
|
|
10
|
+
@all_queries = all_queries
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
5
14
|
module Default
|
|
6
15
|
extend ActiveSupport::Concern
|
|
7
16
|
|
|
@@ -15,14 +24,22 @@ module ActiveRecord
|
|
|
15
24
|
# Returns a scope for the model without the previously set scopes.
|
|
16
25
|
#
|
|
17
26
|
# class Post < ActiveRecord::Base
|
|
27
|
+
# belongs_to :user
|
|
28
|
+
#
|
|
18
29
|
# def self.default_scope
|
|
19
30
|
# where(published: true)
|
|
20
31
|
# end
|
|
21
32
|
# end
|
|
22
33
|
#
|
|
34
|
+
# class User < ActiveRecord::Base
|
|
35
|
+
# has_many :posts
|
|
36
|
+
# end
|
|
37
|
+
#
|
|
23
38
|
# Post.all # Fires "SELECT * FROM posts WHERE published = true"
|
|
24
39
|
# Post.unscoped.all # Fires "SELECT * FROM posts"
|
|
25
40
|
# Post.where(published: false).unscoped.all # Fires "SELECT * FROM posts"
|
|
41
|
+
# User.find(1).posts # Fires "SELECT * FROM posts WHERE published = true AND posts.user_id = 1"
|
|
42
|
+
# User.find(1).posts.unscoped # Fires "SELECT * FROM posts"
|
|
26
43
|
#
|
|
27
44
|
# This method also accepts a block. All queries inside the block will
|
|
28
45
|
# not use the previously set scopes.
|
|
@@ -30,8 +47,8 @@ module ActiveRecord
|
|
|
30
47
|
# Post.unscoped {
|
|
31
48
|
# Post.limit(10) # Fires "SELECT * FROM posts LIMIT 10"
|
|
32
49
|
# }
|
|
33
|
-
def unscoped
|
|
34
|
-
block_given? ? relation.scoping
|
|
50
|
+
def unscoped(&block)
|
|
51
|
+
block_given? ? relation.scoping(&block) : relation
|
|
35
52
|
end
|
|
36
53
|
|
|
37
54
|
# Are there attributes associated with this scope?
|
|
@@ -39,12 +56,18 @@ module ActiveRecord
|
|
|
39
56
|
super || default_scopes.any? || respond_to?(:default_scope)
|
|
40
57
|
end
|
|
41
58
|
|
|
42
|
-
|
|
43
|
-
|
|
59
|
+
# Checks if the model has any default scopes. If all_queries
|
|
60
|
+
# is set to true, the method will check if there are any
|
|
61
|
+
# default_scopes for the model where +all_queries+ is true.
|
|
62
|
+
def default_scopes?(all_queries: false)
|
|
63
|
+
if all_queries
|
|
64
|
+
self.default_scopes.any?(&:all_queries)
|
|
65
|
+
else
|
|
66
|
+
self.default_scopes.any?
|
|
67
|
+
end
|
|
44
68
|
end
|
|
45
69
|
|
|
46
70
|
private
|
|
47
|
-
|
|
48
71
|
# Use this macro in your model to set a default scope for all operations on
|
|
49
72
|
# the model.
|
|
50
73
|
#
|
|
@@ -52,14 +75,30 @@ module ActiveRecord
|
|
|
52
75
|
# default_scope { where(published: true) }
|
|
53
76
|
# end
|
|
54
77
|
#
|
|
55
|
-
# Article.all
|
|
78
|
+
# Article.all
|
|
79
|
+
# # SELECT * FROM articles WHERE published = true
|
|
56
80
|
#
|
|
57
81
|
# The #default_scope is also applied while creating/building a record.
|
|
58
|
-
# It is not applied while updating a record.
|
|
82
|
+
# It is not applied while updating or deleting a record.
|
|
59
83
|
#
|
|
60
84
|
# Article.new.published # => true
|
|
61
85
|
# Article.create.published # => true
|
|
62
86
|
#
|
|
87
|
+
# To apply a #default_scope when updating or deleting a record, add
|
|
88
|
+
# <tt>all_queries: true</tt>:
|
|
89
|
+
#
|
|
90
|
+
# class Article < ActiveRecord::Base
|
|
91
|
+
# default_scope -> { where(blog_id: 1) }, all_queries: true
|
|
92
|
+
# end
|
|
93
|
+
#
|
|
94
|
+
# Applying a default scope to all queries will ensure that records
|
|
95
|
+
# are always queried by the additional conditions. Note that only
|
|
96
|
+
# where clauses apply, as it does not make sense to add order to
|
|
97
|
+
# queries that return a single object by primary key.
|
|
98
|
+
#
|
|
99
|
+
# Article.find(1).destroy
|
|
100
|
+
# # DELETE ... FROM `articles` where ID = 1 AND blog_id = 1;
|
|
101
|
+
#
|
|
63
102
|
# (You can also pass any object which responds to +call+ to the
|
|
64
103
|
# +default_scope+ macro, and it will be called when building the
|
|
65
104
|
# default scope.)
|
|
@@ -72,7 +111,8 @@ module ActiveRecord
|
|
|
72
111
|
# default_scope { where(rating: 'G') }
|
|
73
112
|
# end
|
|
74
113
|
#
|
|
75
|
-
# Article.all
|
|
114
|
+
# Article.all
|
|
115
|
+
# # SELECT * FROM articles WHERE published = true AND rating = 'G'
|
|
76
116
|
#
|
|
77
117
|
# This is also the case with inheritance and module includes where the
|
|
78
118
|
# parent or module defines a #default_scope and the child or including
|
|
@@ -86,7 +126,7 @@ module ActiveRecord
|
|
|
86
126
|
# # Should return a scope, you can call 'super' here etc.
|
|
87
127
|
# end
|
|
88
128
|
# end
|
|
89
|
-
def default_scope(scope = nil, &block) # :doc:
|
|
129
|
+
def default_scope(scope = nil, all_queries: nil, &block) # :doc:
|
|
90
130
|
scope = block if block_given?
|
|
91
131
|
|
|
92
132
|
if scope.is_a?(Relation) || !scope.respond_to?(:call)
|
|
@@ -97,10 +137,12 @@ module ActiveRecord
|
|
|
97
137
|
"self.default_scope.)"
|
|
98
138
|
end
|
|
99
139
|
|
|
100
|
-
|
|
140
|
+
default_scope = DefaultScope.new(scope, all_queries)
|
|
141
|
+
|
|
142
|
+
self.default_scopes += [default_scope]
|
|
101
143
|
end
|
|
102
144
|
|
|
103
|
-
def build_default_scope(relation = relation())
|
|
145
|
+
def build_default_scope(relation = relation(), all_queries: nil)
|
|
104
146
|
return if abstract_class?
|
|
105
147
|
|
|
106
148
|
if default_scope_override.nil?
|
|
@@ -110,26 +152,38 @@ module ActiveRecord
|
|
|
110
152
|
if default_scope_override
|
|
111
153
|
# The user has defined their own default scope method, so call that
|
|
112
154
|
evaluate_default_scope do
|
|
113
|
-
|
|
114
|
-
relation.merge!(scope)
|
|
115
|
-
end
|
|
155
|
+
relation.scoping { default_scope }
|
|
116
156
|
end
|
|
117
157
|
elsif default_scopes.any?
|
|
118
158
|
evaluate_default_scope do
|
|
119
|
-
default_scopes.inject(relation) do |
|
|
120
|
-
|
|
121
|
-
|
|
159
|
+
default_scopes.inject(relation) do |combined_scope, scope_obj|
|
|
160
|
+
if execute_scope?(all_queries, scope_obj)
|
|
161
|
+
scope = scope_obj.scope.respond_to?(:to_proc) ? scope_obj.scope : scope_obj.scope.method(:call)
|
|
162
|
+
|
|
163
|
+
combined_scope.instance_exec(&scope) || combined_scope
|
|
164
|
+
else
|
|
165
|
+
combined_scope
|
|
166
|
+
end
|
|
122
167
|
end
|
|
123
168
|
end
|
|
124
169
|
end
|
|
125
170
|
end
|
|
126
171
|
|
|
172
|
+
# If all_queries is nil, only execute on select and insert queries.
|
|
173
|
+
#
|
|
174
|
+
# If all_queries is true, check if the default_scope object has
|
|
175
|
+
# all_queries set, then execute on all queries; select, insert, update,
|
|
176
|
+
# delete, and reload.
|
|
177
|
+
def execute_scope?(all_queries, default_scope_obj)
|
|
178
|
+
all_queries.nil? || all_queries && default_scope_obj.all_queries
|
|
179
|
+
end
|
|
180
|
+
|
|
127
181
|
def ignore_default_scope?
|
|
128
|
-
ScopeRegistry.
|
|
182
|
+
ScopeRegistry.ignore_default_scope(base_class)
|
|
129
183
|
end
|
|
130
184
|
|
|
131
185
|
def ignore_default_scope=(ignore)
|
|
132
|
-
ScopeRegistry.
|
|
186
|
+
ScopeRegistry.set_ignore_default_scope(base_class, ignore)
|
|
133
187
|
end
|
|
134
188
|
|
|
135
189
|
# The ignore_default_scope flag is used to prevent an infinite recursion
|