omg-activerecord 8.0.0.alpha1
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 +7 -0
- data/CHANGELOG.md +355 -0
- data/MIT-LICENSE +22 -0
- data/README.rdoc +219 -0
- data/examples/performance.rb +185 -0
- data/examples/simple.rb +15 -0
- data/lib/active_record/aggregations.rb +287 -0
- data/lib/active_record/association_relation.rb +50 -0
- data/lib/active_record/associations/alias_tracker.rb +90 -0
- data/lib/active_record/associations/association.rb +417 -0
- data/lib/active_record/associations/association_scope.rb +175 -0
- data/lib/active_record/associations/belongs_to_association.rb +163 -0
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +50 -0
- data/lib/active_record/associations/builder/association.rb +170 -0
- data/lib/active_record/associations/builder/belongs_to.rb +160 -0
- data/lib/active_record/associations/builder/collection_association.rb +80 -0
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +107 -0
- data/lib/active_record/associations/builder/has_many.rb +23 -0
- data/lib/active_record/associations/builder/has_one.rb +61 -0
- data/lib/active_record/associations/builder/singular_association.rb +48 -0
- data/lib/active_record/associations/collection_association.rb +535 -0
- data/lib/active_record/associations/collection_proxy.rb +1163 -0
- 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 +40 -0
- data/lib/active_record/associations/has_many_association.rb +167 -0
- data/lib/active_record/associations/has_many_through_association.rb +232 -0
- data/lib/active_record/associations/has_one_association.rb +142 -0
- data/lib/active_record/associations/has_one_through_association.rb +45 -0
- data/lib/active_record/associations/join_dependency/join_association.rb +106 -0
- data/lib/active_record/associations/join_dependency/join_base.rb +23 -0
- data/lib/active_record/associations/join_dependency/join_part.rb +71 -0
- data/lib/active_record/associations/join_dependency.rb +301 -0
- data/lib/active_record/associations/nested_error.rb +47 -0
- data/lib/active_record/associations/preloader/association.rb +316 -0
- 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 +150 -0
- data/lib/active_record/associations/preloader.rb +135 -0
- data/lib/active_record/associations/singular_association.rb +76 -0
- data/lib/active_record/associations/through_association.rb +132 -0
- data/lib/active_record/associations.rb +1897 -0
- data/lib/active_record/asynchronous_queries_tracker.rb +64 -0
- data/lib/active_record/attribute_assignment.rb +82 -0
- data/lib/active_record/attribute_methods/before_type_cast.rb +106 -0
- data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
- data/lib/active_record/attribute_methods/dirty.rb +262 -0
- data/lib/active_record/attribute_methods/primary_key.rb +158 -0
- data/lib/active_record/attribute_methods/query.rb +50 -0
- data/lib/active_record/attribute_methods/read.rb +46 -0
- data/lib/active_record/attribute_methods/serialization.rb +232 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +94 -0
- data/lib/active_record/attribute_methods/write.rb +49 -0
- data/lib/active_record/attribute_methods.rb +542 -0
- data/lib/active_record/attributes.rb +307 -0
- data/lib/active_record/autosave_association.rb +586 -0
- data/lib/active_record/base.rb +338 -0
- data/lib/active_record/callbacks.rb +452 -0
- data/lib/active_record/coders/column_serializer.rb +61 -0
- data/lib/active_record/coders/json.rb +15 -0
- data/lib/active_record/coders/yaml_column.rb +95 -0
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +290 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +210 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +78 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +923 -0
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +31 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +747 -0
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +319 -0
- data/lib/active_record/connection_adapters/abstract/quoting.rb +239 -0
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +24 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +190 -0
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +961 -0
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +106 -0
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +1883 -0
- data/lib/active_record/connection_adapters/abstract/transaction.rb +676 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +1218 -0
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +1016 -0
- data/lib/active_record/connection_adapters/column.rb +122 -0
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +28 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +95 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +71 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +114 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +106 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +106 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +97 -0
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +300 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +40 -0
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +96 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +196 -0
- 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 +82 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +231 -0
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +91 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +53 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +17 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +54 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +31 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +36 -0
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +20 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +109 -0
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +42 -0
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +74 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +124 -0
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +18 -0
- 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 +125 -0
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +45 -0
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +28 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +38 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +238 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +71 -0
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +169 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +392 -0
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +127 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +1162 -0
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +79 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +1182 -0
- data/lib/active_record/connection_adapters/schema_cache.rb +478 -0
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +45 -0
- data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +145 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +116 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +37 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +39 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +47 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +221 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +843 -0
- data/lib/active_record/connection_adapters/statement_pool.rb +67 -0
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +69 -0
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +212 -0
- data/lib/active_record/connection_adapters.rb +176 -0
- data/lib/active_record/connection_handling.rb +413 -0
- data/lib/active_record/core.rb +836 -0
- data/lib/active_record/counter_cache.rb +230 -0
- data/lib/active_record/database_configurations/connection_url_resolver.rb +105 -0
- data/lib/active_record/database_configurations/database_config.rb +104 -0
- data/lib/active_record/database_configurations/hash_config.rb +172 -0
- data/lib/active_record/database_configurations/url_config.rb +78 -0
- data/lib/active_record/database_configurations.rb +309 -0
- data/lib/active_record/delegated_type.rb +289 -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 +121 -0
- 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 +70 -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 +184 -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 +177 -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 +159 -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 +107 -0
- data/lib/active_record/encryption.rb +58 -0
- data/lib/active_record/enum.rb +424 -0
- data/lib/active_record/errors.rb +614 -0
- data/lib/active_record/explain.rb +63 -0
- data/lib/active_record/explain_registry.rb +37 -0
- data/lib/active_record/explain_subscriber.rb +34 -0
- data/lib/active_record/fixture_set/file.rb +89 -0
- data/lib/active_record/fixture_set/model_metadata.rb +42 -0
- data/lib/active_record/fixture_set/render_context.rb +19 -0
- data/lib/active_record/fixture_set/table_row.rb +208 -0
- data/lib/active_record/fixture_set/table_rows.rb +46 -0
- data/lib/active_record/fixtures.rb +850 -0
- data/lib/active_record/future_result.rb +182 -0
- data/lib/active_record/gem_version.rb +17 -0
- data/lib/active_record/inheritance.rb +366 -0
- data/lib/active_record/insert_all.rb +328 -0
- data/lib/active_record/integration.rb +209 -0
- data/lib/active_record/internal_metadata.rb +164 -0
- data/lib/active_record/legacy_yaml_adapter.rb +15 -0
- data/lib/active_record/locale/en.yml +48 -0
- data/lib/active_record/locking/optimistic.rb +228 -0
- data/lib/active_record/locking/pessimistic.rb +102 -0
- data/lib/active_record/log_subscriber.rb +149 -0
- data/lib/active_record/marshalling.rb +56 -0
- data/lib/active_record/message_pack.rb +124 -0
- data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector.rb +87 -0
- data/lib/active_record/middleware/shard_selector.rb +62 -0
- data/lib/active_record/migration/command_recorder.rb +406 -0
- data/lib/active_record/migration/compatibility.rb +490 -0
- 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 +16 -0
- data/lib/active_record/migration/pending_migration_connection.rb +21 -0
- data/lib/active_record/migration.rb +1626 -0
- data/lib/active_record/model_schema.rb +635 -0
- data/lib/active_record/nested_attributes.rb +633 -0
- data/lib/active_record/no_touching.rb +65 -0
- data/lib/active_record/normalization.rb +163 -0
- data/lib/active_record/persistence.rb +968 -0
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +56 -0
- data/lib/active_record/query_logs.rb +247 -0
- data/lib/active_record/query_logs_formatter.rb +30 -0
- data/lib/active_record/querying.rb +122 -0
- data/lib/active_record/railtie.rb +440 -0
- data/lib/active_record/railties/console_sandbox.rb +5 -0
- data/lib/active_record/railties/controller_runtime.rb +65 -0
- data/lib/active_record/railties/databases.rake +641 -0
- data/lib/active_record/railties/job_runtime.rb +23 -0
- data/lib/active_record/readonly_attributes.rb +66 -0
- data/lib/active_record/reflection.rb +1287 -0
- data/lib/active_record/relation/batches/batch_enumerator.rb +115 -0
- data/lib/active_record/relation/batches.rb +491 -0
- data/lib/active_record/relation/calculations.rb +679 -0
- data/lib/active_record/relation/delegation.rb +154 -0
- data/lib/active_record/relation/finder_methods.rb +661 -0
- data/lib/active_record/relation/from_clause.rb +30 -0
- data/lib/active_record/relation/merger.rb +192 -0
- data/lib/active_record/relation/predicate_builder/array_handler.rb +48 -0
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +76 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +60 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +24 -0
- data/lib/active_record/relation/predicate_builder.rb +181 -0
- data/lib/active_record/relation/query_attribute.rb +68 -0
- data/lib/active_record/relation/query_methods.rb +2235 -0
- data/lib/active_record/relation/record_fetch_warning.rb +52 -0
- data/lib/active_record/relation/spawn_methods.rb +78 -0
- data/lib/active_record/relation/where_clause.rb +218 -0
- data/lib/active_record/relation.rb +1495 -0
- data/lib/active_record/result.rb +249 -0
- data/lib/active_record/runtime_registry.rb +82 -0
- data/lib/active_record/sanitization.rb +254 -0
- data/lib/active_record/schema.rb +77 -0
- data/lib/active_record/schema_dumper.rb +364 -0
- data/lib/active_record/schema_migration.rb +106 -0
- data/lib/active_record/scoping/default.rb +205 -0
- data/lib/active_record/scoping/named.rb +202 -0
- data/lib/active_record/scoping.rb +136 -0
- data/lib/active_record/secure_password.rb +60 -0
- data/lib/active_record/secure_token.rb +66 -0
- data/lib/active_record/serialization.rb +29 -0
- data/lib/active_record/signed_id.rb +137 -0
- data/lib/active_record/statement_cache.rb +164 -0
- data/lib/active_record/store.rb +299 -0
- data/lib/active_record/suppressor.rb +59 -0
- data/lib/active_record/table_metadata.rb +85 -0
- data/lib/active_record/tasks/database_tasks.rb +681 -0
- data/lib/active_record/tasks/mysql_database_tasks.rb +120 -0
- data/lib/active_record/tasks/postgresql_database_tasks.rb +147 -0
- data/lib/active_record/tasks/sqlite_database_tasks.rb +89 -0
- data/lib/active_record/test_databases.rb +24 -0
- data/lib/active_record/test_fixtures.rb +321 -0
- data/lib/active_record/testing/query_assertions.rb +121 -0
- data/lib/active_record/timestamp.rb +177 -0
- data/lib/active_record/token_for.rb +123 -0
- data/lib/active_record/touch_later.rb +70 -0
- data/lib/active_record/transaction.rb +132 -0
- data/lib/active_record/transactions.rb +523 -0
- data/lib/active_record/translation.rb +22 -0
- data/lib/active_record/type/adapter_specific_registry.rb +144 -0
- data/lib/active_record/type/date.rb +9 -0
- data/lib/active_record/type/date_time.rb +9 -0
- data/lib/active_record/type/decimal_without_scale.rb +15 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +57 -0
- data/lib/active_record/type/internal/timezone.rb +22 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +76 -0
- data/lib/active_record/type/text.rb +11 -0
- data/lib/active_record/type/time.rb +35 -0
- data/lib/active_record/type/type_map.rb +58 -0
- data/lib/active_record/type/unsigned_integer.rb +16 -0
- data/lib/active_record/type.rb +83 -0
- data/lib/active_record/type_caster/connection.rb +33 -0
- data/lib/active_record/type_caster/map.rb +23 -0
- data/lib/active_record/type_caster.rb +9 -0
- data/lib/active_record/validations/absence.rb +25 -0
- data/lib/active_record/validations/associated.rb +65 -0
- data/lib/active_record/validations/length.rb +26 -0
- data/lib/active_record/validations/numericality.rb +36 -0
- data/lib/active_record/validations/presence.rb +45 -0
- data/lib/active_record/validations/uniqueness.rb +295 -0
- data/lib/active_record/validations.rb +101 -0
- data/lib/active_record/version.rb +10 -0
- data/lib/active_record.rb +616 -0
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +33 -0
- data/lib/arel/collectors/bind.rb +31 -0
- data/lib/arel/collectors/composite.rb +46 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +27 -0
- data/lib/arel/collectors/substitute_binds.rb +35 -0
- data/lib/arel/crud.rb +48 -0
- data/lib/arel/delete_manager.rb +32 -0
- data/lib/arel/errors.rb +19 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +53 -0
- data/lib/arel/filter_predications.rb +9 -0
- data/lib/arel/insert_manager.rb +48 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +125 -0
- data/lib/arel/nodes/bind_param.rb +44 -0
- data/lib/arel/nodes/bound_sql_literal.rb +65 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +62 -0
- data/lib/arel/nodes/comment.rb +29 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/cte.rb +36 -0
- data/lib/arel/nodes/delete_statement.rb +44 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +15 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/filter.rb +10 -0
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +45 -0
- data/lib/arel/nodes/grouping.rb +11 -0
- data/lib/arel/nodes/homogeneous_in.rb +68 -0
- data/lib/arel/nodes/in.rb +15 -0
- data/lib/arel/nodes/infix_operation.rb +92 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/nary.rb +39 -0
- data/lib/arel/nodes/node.rb +161 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/ordering.rb +27 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +67 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +32 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +35 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +44 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +46 -0
- data/lib/arel/nodes/values_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/nodes.rb +75 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +260 -0
- data/lib/arel/select_manager.rb +276 -0
- data/lib/arel/table.rb +121 -0
- data/lib/arel/tree_manager.rb +65 -0
- data/lib/arel/update_manager.rb +49 -0
- data/lib/arel/visitors/dot.rb +299 -0
- data/lib/arel/visitors/mysql.rb +111 -0
- data/lib/arel/visitors/postgresql.rb +99 -0
- data/lib/arel/visitors/sqlite.rb +38 -0
- data/lib/arel/visitors/to_sql.rb +1033 -0
- data/lib/arel/visitors/visitor.rb +45 -0
- data/lib/arel/visitors.rb +13 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +73 -0
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +76 -0
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +29 -0
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +48 -0
- data/lib/rails/generators/active_record/migration.rb +54 -0
- data/lib/rails/generators/active_record/model/USAGE +113 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +94 -0
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
- data/lib/rails/generators/active_record/model/templates/module.rb.tt +7 -0
- 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
- data/lib/rails/generators/active_record.rb +19 -0
- metadata +505 -0
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "stringio"
|
|
4
|
+
|
|
5
|
+
module ActiveRecord
|
|
6
|
+
# = Active Record Schema Dumper
|
|
7
|
+
#
|
|
8
|
+
# This class is used to dump the database schema for some connection to some
|
|
9
|
+
# output format (i.e., ActiveRecord::Schema).
|
|
10
|
+
class SchemaDumper # :nodoc:
|
|
11
|
+
private_class_method :new
|
|
12
|
+
|
|
13
|
+
##
|
|
14
|
+
# :singleton-method:
|
|
15
|
+
# A list of tables which should not be dumped to the schema.
|
|
16
|
+
# Acceptable values are strings and regexps.
|
|
17
|
+
cattr_accessor :ignore_tables, default: []
|
|
18
|
+
|
|
19
|
+
##
|
|
20
|
+
# :singleton-method:
|
|
21
|
+
# Specify a custom regular expression matching foreign keys which name
|
|
22
|
+
# should not be dumped to db/schema.rb.
|
|
23
|
+
cattr_accessor :fk_ignore_pattern, default: /^fk_rails_[0-9a-f]{10}$/
|
|
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
|
+
|
|
43
|
+
class << self
|
|
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
|
|
48
|
+
stream
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
private
|
|
52
|
+
def generate_options(config)
|
|
53
|
+
{
|
|
54
|
+
table_name_prefix: config.table_name_prefix,
|
|
55
|
+
table_name_suffix: config.table_name_suffix
|
|
56
|
+
}
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def dump(stream)
|
|
61
|
+
header(stream)
|
|
62
|
+
schemas(stream)
|
|
63
|
+
extensions(stream)
|
|
64
|
+
types(stream)
|
|
65
|
+
tables(stream)
|
|
66
|
+
virtual_tables(stream)
|
|
67
|
+
trailer(stream)
|
|
68
|
+
stream
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
private
|
|
72
|
+
attr_accessor :table_name
|
|
73
|
+
|
|
74
|
+
def initialize(connection, options = {})
|
|
75
|
+
@connection = connection
|
|
76
|
+
@version = connection.pool.migration_context.current_version rescue nil
|
|
77
|
+
@options = options
|
|
78
|
+
@ignore_tables = [
|
|
79
|
+
ActiveRecord::Base.schema_migrations_table_name,
|
|
80
|
+
ActiveRecord::Base.internal_metadata_table_name,
|
|
81
|
+
self.class.ignore_tables
|
|
82
|
+
].flatten
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# turns 20170404131909 into "2017_04_04_131909"
|
|
86
|
+
def formatted_version
|
|
87
|
+
stringified = @version.to_s
|
|
88
|
+
return stringified unless stringified.length == 14
|
|
89
|
+
stringified.insert(4, "_").insert(7, "_").insert(10, "_")
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def define_params
|
|
93
|
+
@version ? "version: #{formatted_version}" : ""
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def header(stream)
|
|
97
|
+
stream.puts <<~HEADER
|
|
98
|
+
# This file is auto-generated from the current state of the database. Instead
|
|
99
|
+
# of editing this file, please use the migrations feature of Active Record to
|
|
100
|
+
# incrementally modify your database, and then regenerate this schema definition.
|
|
101
|
+
#
|
|
102
|
+
# This file is the source Rails uses to define your schema when running `bin/rails
|
|
103
|
+
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
|
|
104
|
+
# be faster and is potentially less error prone than running all of your
|
|
105
|
+
# migrations from scratch. Old migrations may fail to apply correctly if those
|
|
106
|
+
# migrations use external dependencies or application code.
|
|
107
|
+
#
|
|
108
|
+
# It's strongly recommended that you check this file into your version control system.
|
|
109
|
+
|
|
110
|
+
ActiveRecord::Schema[#{ActiveRecord::Migration.current_version}].define(#{define_params}) do
|
|
111
|
+
HEADER
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def trailer(stream)
|
|
115
|
+
stream.puts "end"
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# extensions are only supported by PostgreSQL
|
|
119
|
+
def extensions(stream)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# (enum) types are only supported by PostgreSQL
|
|
123
|
+
def types(stream)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# schemas are only supported by PostgreSQL
|
|
127
|
+
def schemas(stream)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# virtual tables are only supported by SQLite
|
|
131
|
+
def virtual_tables(stream)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def tables(stream)
|
|
135
|
+
sorted_tables = @connection.tables.sort
|
|
136
|
+
|
|
137
|
+
not_ignored_tables = sorted_tables.reject { |table_name| ignored?(table_name) }
|
|
138
|
+
|
|
139
|
+
not_ignored_tables.each_with_index do |table_name, index|
|
|
140
|
+
table(table_name, stream)
|
|
141
|
+
stream.puts if index < not_ignored_tables.count - 1
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# dump foreign keys at the end to make sure all dependent tables exist.
|
|
145
|
+
if @connection.supports_foreign_keys?
|
|
146
|
+
foreign_keys_stream = StringIO.new
|
|
147
|
+
not_ignored_tables.each do |tbl|
|
|
148
|
+
foreign_keys(tbl, foreign_keys_stream)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
foreign_keys_string = foreign_keys_stream.string
|
|
152
|
+
stream.puts if foreign_keys_string.length > 0
|
|
153
|
+
|
|
154
|
+
stream.print foreign_keys_string
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def table(table, stream)
|
|
159
|
+
columns = @connection.columns(table)
|
|
160
|
+
begin
|
|
161
|
+
self.table_name = table
|
|
162
|
+
|
|
163
|
+
tbl = StringIO.new
|
|
164
|
+
|
|
165
|
+
# first dump primary key column
|
|
166
|
+
pk = @connection.primary_key(table)
|
|
167
|
+
|
|
168
|
+
tbl.print " create_table #{remove_prefix_and_suffix(table).inspect}"
|
|
169
|
+
|
|
170
|
+
case pk
|
|
171
|
+
when String
|
|
172
|
+
tbl.print ", primary_key: #{pk.inspect}" unless pk == "id"
|
|
173
|
+
pkcol = columns.detect { |c| c.name == pk }
|
|
174
|
+
pkcolspec = column_spec_for_primary_key(pkcol)
|
|
175
|
+
unless pkcolspec.empty?
|
|
176
|
+
if pkcolspec != pkcolspec.slice(:id, :default)
|
|
177
|
+
pkcolspec = { id: { type: pkcolspec.delete(:id), **pkcolspec }.compact }
|
|
178
|
+
end
|
|
179
|
+
tbl.print ", #{format_colspec(pkcolspec)}"
|
|
180
|
+
end
|
|
181
|
+
when Array
|
|
182
|
+
tbl.print ", primary_key: #{pk.inspect}"
|
|
183
|
+
else
|
|
184
|
+
tbl.print ", id: false"
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
table_options = @connection.table_options(table)
|
|
188
|
+
if table_options.present?
|
|
189
|
+
tbl.print ", #{format_options(table_options)}"
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
tbl.puts ", force: :cascade do |t|"
|
|
193
|
+
|
|
194
|
+
# then dump all non-primary key columns
|
|
195
|
+
columns.each do |column|
|
|
196
|
+
raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" unless @connection.valid_type?(column.type)
|
|
197
|
+
next if column.name == pk
|
|
198
|
+
|
|
199
|
+
type, colspec = column_spec(column)
|
|
200
|
+
if type.is_a?(Symbol)
|
|
201
|
+
tbl.print " t.#{type} #{column.name.inspect}"
|
|
202
|
+
else
|
|
203
|
+
tbl.print " t.column #{column.name.inspect}, #{type.inspect}"
|
|
204
|
+
end
|
|
205
|
+
tbl.print ", #{format_colspec(colspec)}" if colspec.present?
|
|
206
|
+
tbl.puts
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
indexes_in_create(table, tbl)
|
|
210
|
+
check_constraints_in_create(table, tbl) if @connection.supports_check_constraints?
|
|
211
|
+
exclusion_constraints_in_create(table, tbl) if @connection.supports_exclusion_constraints?
|
|
212
|
+
unique_constraints_in_create(table, tbl) if @connection.supports_unique_constraints?
|
|
213
|
+
|
|
214
|
+
tbl.puts " end"
|
|
215
|
+
|
|
216
|
+
stream.print tbl.string
|
|
217
|
+
rescue => e
|
|
218
|
+
stream.puts "# Could not dump table #{table.inspect} because of following #{e.class}"
|
|
219
|
+
stream.puts "# #{e.message}"
|
|
220
|
+
stream.puts
|
|
221
|
+
ensure
|
|
222
|
+
self.table_name = nil
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
# Keep it for indexing materialized views
|
|
227
|
+
def indexes(table, stream)
|
|
228
|
+
if (indexes = @connection.indexes(table)).any?
|
|
229
|
+
add_index_statements = indexes.map do |index|
|
|
230
|
+
table_name = remove_prefix_and_suffix(index.table).inspect
|
|
231
|
+
" add_index #{([table_name] + index_parts(index)).join(', ')}"
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
stream.puts add_index_statements.sort.join("\n")
|
|
235
|
+
stream.puts
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
def indexes_in_create(table, stream)
|
|
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
|
+
|
|
253
|
+
index_statements = indexes.map do |index|
|
|
254
|
+
" t.index #{index_parts(index).join(', ')}"
|
|
255
|
+
end
|
|
256
|
+
stream.puts index_statements.sort.join("\n")
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
def index_parts(index)
|
|
261
|
+
index_parts = [
|
|
262
|
+
index.columns.inspect,
|
|
263
|
+
"name: #{index.name.inspect}",
|
|
264
|
+
]
|
|
265
|
+
index_parts << "unique: true" if index.unique
|
|
266
|
+
index_parts << "length: #{format_index_parts(index.lengths)}" if index.lengths.present?
|
|
267
|
+
index_parts << "order: #{format_index_parts(index.orders)}" if index.orders.present?
|
|
268
|
+
index_parts << "opclass: #{format_index_parts(index.opclasses)}" if index.opclasses.present?
|
|
269
|
+
index_parts << "where: #{index.where.inspect}" if index.where
|
|
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
|
|
273
|
+
index_parts << "type: #{index.type.inspect}" if index.type
|
|
274
|
+
index_parts << "comment: #{index.comment.inspect}" if index.comment
|
|
275
|
+
index_parts
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
def check_constraints_in_create(table, stream)
|
|
279
|
+
if (check_constraints = @connection.check_constraints(table)).any?
|
|
280
|
+
add_check_constraint_statements = check_constraints.map do |check_constraint|
|
|
281
|
+
parts = [
|
|
282
|
+
"t.check_constraint #{check_constraint.expression.inspect}"
|
|
283
|
+
]
|
|
284
|
+
|
|
285
|
+
if check_constraint.export_name_on_schema_dump?
|
|
286
|
+
parts << "name: #{check_constraint.name.inspect}"
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
parts << "validate: #{check_constraint.validate?.inspect}" unless check_constraint.validate?
|
|
290
|
+
|
|
291
|
+
" #{parts.join(', ')}"
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
stream.puts add_check_constraint_statements.sort.join("\n")
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
def foreign_keys(table, stream)
|
|
299
|
+
if (foreign_keys = @connection.foreign_keys(table)).any?
|
|
300
|
+
add_foreign_key_statements = foreign_keys.map do |foreign_key|
|
|
301
|
+
parts = [
|
|
302
|
+
"add_foreign_key #{remove_prefix_and_suffix(foreign_key.from_table).inspect}",
|
|
303
|
+
remove_prefix_and_suffix(foreign_key.to_table).inspect,
|
|
304
|
+
]
|
|
305
|
+
|
|
306
|
+
if foreign_key.column != @connection.foreign_key_column_for(foreign_key.to_table, "id")
|
|
307
|
+
parts << "column: #{foreign_key.column.inspect}"
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
if foreign_key.custom_primary_key?
|
|
311
|
+
parts << "primary_key: #{foreign_key.primary_key.inspect}"
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
if foreign_key.export_name_on_schema_dump?
|
|
315
|
+
parts << "name: #{foreign_key.name.inspect}"
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
parts << "on_update: #{foreign_key.on_update.inspect}" if foreign_key.on_update
|
|
319
|
+
parts << "on_delete: #{foreign_key.on_delete.inspect}" if foreign_key.on_delete
|
|
320
|
+
parts << "deferrable: #{foreign_key.deferrable.inspect}" if foreign_key.deferrable
|
|
321
|
+
parts << "validate: #{foreign_key.validate?.inspect}" unless foreign_key.validate?
|
|
322
|
+
|
|
323
|
+
" #{parts.join(', ')}"
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
stream.puts add_foreign_key_statements.sort.join("\n")
|
|
327
|
+
end
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
def format_colspec(colspec)
|
|
331
|
+
colspec.map do |key, value|
|
|
332
|
+
"#{key}: #{ value.is_a?(Hash) ? "{ #{format_colspec(value)} }" : value }"
|
|
333
|
+
end.join(", ")
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
def format_options(options)
|
|
337
|
+
options.map { |key, value| "#{key}: #{value.inspect}" }.join(", ")
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
def format_index_parts(options)
|
|
341
|
+
if options.is_a?(Hash)
|
|
342
|
+
"{ #{format_options(options)} }"
|
|
343
|
+
else
|
|
344
|
+
options.inspect
|
|
345
|
+
end
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
def remove_prefix_and_suffix(table)
|
|
349
|
+
# This method appears at the top when profiling active_record test cases run.
|
|
350
|
+
# Avoid costly calculation when there are no prefix and suffix.
|
|
351
|
+
return table if @options[:table_name_prefix].blank? && @options[:table_name_suffix].blank?
|
|
352
|
+
|
|
353
|
+
prefix = Regexp.escape(@options[:table_name_prefix].to_s)
|
|
354
|
+
suffix = Regexp.escape(@options[:table_name_suffix].to_s)
|
|
355
|
+
table.sub(/\A#{prefix}(.+)#{suffix}\z/, "\\1")
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
def ignored?(table_name)
|
|
359
|
+
@ignore_tables.any? do |ignored|
|
|
360
|
+
ignored === remove_prefix_and_suffix(table_name)
|
|
361
|
+
end
|
|
362
|
+
end
|
|
363
|
+
end
|
|
364
|
+
end
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
# This class is used to create a table that keeps track of which migrations
|
|
5
|
+
# have been applied to a given database. When a migration is run, its schema
|
|
6
|
+
# number is inserted in to the schema migrations table so it doesn't need
|
|
7
|
+
# to be executed the next time.
|
|
8
|
+
class SchemaMigration # :nodoc:
|
|
9
|
+
class NullSchemaMigration # :nodoc:
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
attr_reader :arel_table
|
|
13
|
+
|
|
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)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
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")
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def delete_all_versions
|
|
37
|
+
# Eagerly check in connection to avoid checking in/out many times in the called method.
|
|
38
|
+
@pool.with_connection do
|
|
39
|
+
versions.each do |version|
|
|
40
|
+
delete_version(version)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def primary_key
|
|
46
|
+
"version"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def table_name
|
|
50
|
+
"#{ActiveRecord::Base.table_name_prefix}#{ActiveRecord::Base.schema_migrations_table_name}#{ActiveRecord::Base.table_name_suffix}"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def create_table
|
|
54
|
+
@pool.with_connection do |connection|
|
|
55
|
+
unless connection.table_exists?(table_name)
|
|
56
|
+
connection.create_table(table_name, id: false) do |t|
|
|
57
|
+
t.string :version, **connection.internal_string_options_for_primary_key
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def drop_table
|
|
64
|
+
@pool.with_connection do |connection|
|
|
65
|
+
connection.drop_table table_name, if_exists: true
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def normalize_migration_number(number)
|
|
70
|
+
"%.3d" % number.to_i
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def normalized_versions
|
|
74
|
+
versions.map { |v| normalize_migration_number v }
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def versions
|
|
78
|
+
sm = Arel::SelectManager.new(arel_table)
|
|
79
|
+
sm.project(arel_table[primary_key])
|
|
80
|
+
sm.order(arel_table[primary_key].asc)
|
|
81
|
+
|
|
82
|
+
@pool.with_connection do |connection|
|
|
83
|
+
connection.select_values(sm, "#{self.class} Load")
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def integer_versions
|
|
88
|
+
versions.map(&:to_i)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def count
|
|
92
|
+
sm = Arel::SelectManager.new(arel_table)
|
|
93
|
+
sm.project(*Arel::Nodes::Count.new([Arel.star]))
|
|
94
|
+
|
|
95
|
+
@pool.with_connection do |connection|
|
|
96
|
+
connection.select_values(sm, "#{self.class} Count").first
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def table_exists?
|
|
101
|
+
@pool.with_connection do |connection|
|
|
102
|
+
connection.data_source_exists?(table_name)
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
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
|
+
|
|
14
|
+
module Default
|
|
15
|
+
extend ActiveSupport::Concern
|
|
16
|
+
|
|
17
|
+
included do
|
|
18
|
+
# Stores the default scope for the class.
|
|
19
|
+
class_attribute :default_scopes, instance_writer: false, instance_predicate: false, default: []
|
|
20
|
+
class_attribute :default_scope_override, instance_writer: false, instance_predicate: false, default: nil
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
module ClassMethods
|
|
24
|
+
# Returns a scope for the model without the previously set scopes.
|
|
25
|
+
#
|
|
26
|
+
# class Post < ActiveRecord::Base
|
|
27
|
+
# belongs_to :user
|
|
28
|
+
#
|
|
29
|
+
# def self.default_scope
|
|
30
|
+
# where(published: true)
|
|
31
|
+
# end
|
|
32
|
+
# end
|
|
33
|
+
#
|
|
34
|
+
# class User < ActiveRecord::Base
|
|
35
|
+
# has_many :posts
|
|
36
|
+
# end
|
|
37
|
+
#
|
|
38
|
+
# Post.all # Fires "SELECT * FROM posts WHERE published = true"
|
|
39
|
+
# Post.unscoped.all # Fires "SELECT * FROM posts"
|
|
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"
|
|
43
|
+
#
|
|
44
|
+
# This method also accepts a block. All queries inside the block will
|
|
45
|
+
# not use the previously set scopes.
|
|
46
|
+
#
|
|
47
|
+
# Post.unscoped {
|
|
48
|
+
# Post.limit(10) # Fires "SELECT * FROM posts LIMIT 10"
|
|
49
|
+
# }
|
|
50
|
+
def unscoped(&block)
|
|
51
|
+
block_given? ? relation.scoping(&block) : relation
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Are there attributes associated with this scope?
|
|
55
|
+
def scope_attributes? # :nodoc:
|
|
56
|
+
super || default_scopes.any? || respond_to?(:default_scope)
|
|
57
|
+
end
|
|
58
|
+
|
|
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
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
private
|
|
71
|
+
# Use this macro in your model to set a default scope for all operations on
|
|
72
|
+
# the model.
|
|
73
|
+
#
|
|
74
|
+
# class Article < ActiveRecord::Base
|
|
75
|
+
# default_scope { where(published: true) }
|
|
76
|
+
# end
|
|
77
|
+
#
|
|
78
|
+
# Article.all
|
|
79
|
+
# # SELECT * FROM articles WHERE published = true
|
|
80
|
+
#
|
|
81
|
+
# The #default_scope is also applied while creating/building a record.
|
|
82
|
+
# It is not applied while updating or deleting a record.
|
|
83
|
+
#
|
|
84
|
+
# Article.new.published # => true
|
|
85
|
+
# Article.create.published # => true
|
|
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
|
+
#
|
|
102
|
+
# (You can also pass any object which responds to +call+ to the
|
|
103
|
+
# +default_scope+ macro, and it will be called when building the
|
|
104
|
+
# default scope.)
|
|
105
|
+
#
|
|
106
|
+
# If you use multiple #default_scope declarations in your model then
|
|
107
|
+
# they will be merged together:
|
|
108
|
+
#
|
|
109
|
+
# class Article < ActiveRecord::Base
|
|
110
|
+
# default_scope { where(published: true) }
|
|
111
|
+
# default_scope { where(rating: 'G') }
|
|
112
|
+
# end
|
|
113
|
+
#
|
|
114
|
+
# Article.all
|
|
115
|
+
# # SELECT * FROM articles WHERE published = true AND rating = 'G'
|
|
116
|
+
#
|
|
117
|
+
# This is also the case with inheritance and module includes where the
|
|
118
|
+
# parent or module defines a #default_scope and the child or including
|
|
119
|
+
# class defines a second one.
|
|
120
|
+
#
|
|
121
|
+
# If you need to do more complex things with a default scope, you can
|
|
122
|
+
# alternatively define it as a class method:
|
|
123
|
+
#
|
|
124
|
+
# class Article < ActiveRecord::Base
|
|
125
|
+
# def self.default_scope
|
|
126
|
+
# # Should return a scope, you can call 'super' here etc.
|
|
127
|
+
# end
|
|
128
|
+
# end
|
|
129
|
+
def default_scope(scope = nil, all_queries: nil, &block) # :doc:
|
|
130
|
+
scope = block if block_given?
|
|
131
|
+
|
|
132
|
+
if scope.is_a?(Relation) || !scope.respond_to?(:call)
|
|
133
|
+
raise ArgumentError,
|
|
134
|
+
"Support for calling #default_scope without a block is removed. For example instead " \
|
|
135
|
+
"of `default_scope where(color: 'red')`, please use " \
|
|
136
|
+
"`default_scope { where(color: 'red') }`. (Alternatively you can just redefine " \
|
|
137
|
+
"self.default_scope.)"
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
default_scope = DefaultScope.new(scope, all_queries)
|
|
141
|
+
|
|
142
|
+
self.default_scopes += [default_scope]
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def build_default_scope(relation = relation(), all_queries: nil)
|
|
146
|
+
return if abstract_class?
|
|
147
|
+
|
|
148
|
+
if default_scope_override.nil?
|
|
149
|
+
self.default_scope_override = !Base.is_a?(method(:default_scope).owner)
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
if default_scope_override
|
|
153
|
+
# The user has defined their own default scope method, so call that
|
|
154
|
+
evaluate_default_scope do
|
|
155
|
+
relation.scoping { default_scope }
|
|
156
|
+
end
|
|
157
|
+
elsif default_scopes.any?
|
|
158
|
+
evaluate_default_scope do
|
|
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
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
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
|
+
|
|
181
|
+
def ignore_default_scope?
|
|
182
|
+
ScopeRegistry.ignore_default_scope(base_class)
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def ignore_default_scope=(ignore)
|
|
186
|
+
ScopeRegistry.set_ignore_default_scope(base_class, ignore)
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# The ignore_default_scope flag is used to prevent an infinite recursion
|
|
190
|
+
# situation where a default scope references a scope which has a default
|
|
191
|
+
# scope which references a scope...
|
|
192
|
+
def evaluate_default_scope
|
|
193
|
+
return if ignore_default_scope?
|
|
194
|
+
|
|
195
|
+
begin
|
|
196
|
+
self.ignore_default_scope = true
|
|
197
|
+
yield
|
|
198
|
+
ensure
|
|
199
|
+
self.ignore_default_scope = false
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
end
|