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,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
module Associations
|
|
5
|
+
class DisableJoinsAssociationScope < AssociationScope # :nodoc:
|
|
6
|
+
def scope(association)
|
|
7
|
+
source_reflection = association.reflection
|
|
8
|
+
owner = association.owner
|
|
9
|
+
unscoped = association.klass.unscoped
|
|
10
|
+
reverse_chain = get_chain(source_reflection, association, unscoped.alias_tracker).reverse
|
|
11
|
+
|
|
12
|
+
last_reflection, last_ordered, last_join_ids = last_scope_chain(reverse_chain, owner)
|
|
13
|
+
|
|
14
|
+
add_constraints(last_reflection, last_reflection.join_primary_key, last_join_ids, owner, last_ordered)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
def last_scope_chain(reverse_chain, owner)
|
|
19
|
+
first_item = reverse_chain.shift
|
|
20
|
+
first_scope = [first_item, false, [owner._read_attribute(first_item.join_foreign_key)]]
|
|
21
|
+
|
|
22
|
+
reverse_chain.inject(first_scope) do |(reflection, ordered, join_ids), next_reflection|
|
|
23
|
+
key = reflection.join_primary_key
|
|
24
|
+
records = add_constraints(reflection, key, join_ids, owner, ordered)
|
|
25
|
+
foreign_key = next_reflection.join_foreign_key
|
|
26
|
+
record_ids = records.pluck(foreign_key)
|
|
27
|
+
records_ordered = records && records.order_values.any?
|
|
28
|
+
|
|
29
|
+
[next_reflection, records_ordered, record_ids]
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def add_constraints(reflection, key, join_ids, owner, ordered)
|
|
34
|
+
scope = reflection.build_scope(reflection.aliased_table).where(key => join_ids)
|
|
35
|
+
|
|
36
|
+
relation = reflection.klass.scope_for_association
|
|
37
|
+
scope.merge!(
|
|
38
|
+
relation.except(:select, :create_with, :includes, :preload, :eager_load, :joins, :left_outer_joins)
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
scope = reflection.constraints.inject(scope) do |memo, scope_chain_item|
|
|
42
|
+
item = eval_scope(reflection, scope_chain_item, owner)
|
|
43
|
+
scope.unscope!(*item.unscope_values)
|
|
44
|
+
scope.where_clause += item.where_clause
|
|
45
|
+
scope.order_values = item.order_values | scope.order_values
|
|
46
|
+
scope
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
if scope.order_values.empty? && ordered
|
|
50
|
+
split_scope = DisableJoinsAssociationRelation.create(scope.model, key, join_ids)
|
|
51
|
+
split_scope.where_clause += scope.where_clause
|
|
52
|
+
split_scope
|
|
53
|
+
else
|
|
54
|
+
scope
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
class AssociationNotFoundError < ConfigurationError # :nodoc:
|
|
5
|
+
attr_reader :record, :association_name
|
|
6
|
+
|
|
7
|
+
def initialize(record = nil, association_name = nil)
|
|
8
|
+
@record = record
|
|
9
|
+
@association_name = association_name
|
|
10
|
+
if record && association_name
|
|
11
|
+
super("Association named '#{association_name}' was not found on #{record.class.name}; perhaps you misspelled it?")
|
|
12
|
+
else
|
|
13
|
+
super("Association was not found.")
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
if defined?(DidYouMean::Correctable) && defined?(DidYouMean::SpellChecker)
|
|
18
|
+
include DidYouMean::Correctable
|
|
19
|
+
|
|
20
|
+
def corrections
|
|
21
|
+
if record && association_name
|
|
22
|
+
@corrections ||= begin
|
|
23
|
+
maybe_these = record.class.reflections.keys
|
|
24
|
+
DidYouMean::SpellChecker.new(dictionary: maybe_these).correct(association_name)
|
|
25
|
+
end
|
|
26
|
+
else
|
|
27
|
+
[]
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
class InverseOfAssociationNotFoundError < ActiveRecordError # :nodoc:
|
|
34
|
+
attr_reader :reflection, :associated_class
|
|
35
|
+
|
|
36
|
+
def initialize(reflection = nil, associated_class = nil)
|
|
37
|
+
if reflection
|
|
38
|
+
@reflection = reflection
|
|
39
|
+
@associated_class = associated_class.nil? ? reflection.klass : associated_class
|
|
40
|
+
super("Could not find the inverse association for #{reflection.name} (#{reflection.options[:inverse_of].inspect} in #{associated_class.nil? ? reflection.class_name : associated_class.name})")
|
|
41
|
+
else
|
|
42
|
+
super("Could not find the inverse association.")
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
if defined?(DidYouMean::Correctable) && defined?(DidYouMean::SpellChecker)
|
|
47
|
+
include DidYouMean::Correctable
|
|
48
|
+
|
|
49
|
+
def corrections
|
|
50
|
+
if reflection && associated_class
|
|
51
|
+
@corrections ||= begin
|
|
52
|
+
maybe_these = associated_class.reflections.keys
|
|
53
|
+
DidYouMean::SpellChecker.new(dictionary: maybe_these).correct(reflection.options[:inverse_of].to_s)
|
|
54
|
+
end
|
|
55
|
+
else
|
|
56
|
+
[]
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
class InverseOfAssociationRecursiveError < ActiveRecordError # :nodoc:
|
|
63
|
+
attr_reader :reflection
|
|
64
|
+
def initialize(reflection = nil)
|
|
65
|
+
if reflection
|
|
66
|
+
@reflection = reflection
|
|
67
|
+
super("Inverse association #{reflection.name} (#{reflection.options[:inverse_of].inspect} in #{reflection.class_name}) is recursive.")
|
|
68
|
+
else
|
|
69
|
+
super("Inverse association is recursive.")
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
class HasManyThroughAssociationNotFoundError < ActiveRecordError # :nodoc:
|
|
75
|
+
attr_reader :owner_class, :reflection
|
|
76
|
+
|
|
77
|
+
def initialize(owner_class = nil, reflection = nil)
|
|
78
|
+
if owner_class && reflection
|
|
79
|
+
@owner_class = owner_class
|
|
80
|
+
@reflection = reflection
|
|
81
|
+
super("Could not find the association #{reflection.options[:through].inspect} in model #{owner_class.name}")
|
|
82
|
+
else
|
|
83
|
+
super("Could not find the association.")
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
if defined?(DidYouMean::Correctable) && defined?(DidYouMean::SpellChecker)
|
|
88
|
+
include DidYouMean::Correctable
|
|
89
|
+
|
|
90
|
+
def corrections
|
|
91
|
+
if owner_class && reflection
|
|
92
|
+
@corrections ||= begin
|
|
93
|
+
maybe_these = owner_class.reflections.keys
|
|
94
|
+
maybe_these -= [reflection.name.to_s] # remove failing reflection
|
|
95
|
+
DidYouMean::SpellChecker.new(dictionary: maybe_these).correct(reflection.options[:through].to_s)
|
|
96
|
+
end
|
|
97
|
+
else
|
|
98
|
+
[]
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
class HasManyThroughAssociationPolymorphicSourceError < ActiveRecordError # :nodoc:
|
|
105
|
+
def initialize(owner_class_name = nil, reflection = nil, source_reflection = nil)
|
|
106
|
+
if owner_class_name && reflection && source_reflection
|
|
107
|
+
super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' on the polymorphic object '#{source_reflection.class_name}##{source_reflection.name}' without 'source_type'. Try adding 'source_type: \"#{reflection.name.to_s.classify}\"' to 'has_many :through' definition.")
|
|
108
|
+
else
|
|
109
|
+
super("Cannot have a has_many :through association.")
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
class HasManyThroughAssociationPolymorphicThroughError < ActiveRecordError # :nodoc:
|
|
115
|
+
def initialize(owner_class_name = nil, reflection = nil)
|
|
116
|
+
if owner_class_name && reflection
|
|
117
|
+
super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' which goes through the polymorphic association '#{owner_class_name}##{reflection.through_reflection.name}'.")
|
|
118
|
+
else
|
|
119
|
+
super("Cannot have a has_many :through association.")
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
class HasManyThroughAssociationPointlessSourceTypeError < ActiveRecordError # :nodoc:
|
|
125
|
+
def initialize(owner_class_name = nil, reflection = nil, source_reflection = nil)
|
|
126
|
+
if owner_class_name && reflection && source_reflection
|
|
127
|
+
super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' with a :source_type option if the '#{reflection.through_reflection.class_name}##{source_reflection.name}' is not polymorphic. Try removing :source_type on your association.")
|
|
128
|
+
else
|
|
129
|
+
super("Cannot have a has_many :through association.")
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
class HasOneThroughCantAssociateThroughCollection < ActiveRecordError # :nodoc:
|
|
135
|
+
def initialize(owner_class_name = nil, reflection = nil, through_reflection = nil)
|
|
136
|
+
if owner_class_name && reflection && through_reflection
|
|
137
|
+
super("Cannot have a has_one :through association '#{owner_class_name}##{reflection.name}' where the :through association '#{owner_class_name}##{through_reflection.name}' is a collection. Specify a has_one or belongs_to association in the :through option instead.")
|
|
138
|
+
else
|
|
139
|
+
super("Cannot have a has_one :through association.")
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
class HasOneAssociationPolymorphicThroughError < ActiveRecordError # :nodoc:
|
|
145
|
+
def initialize(owner_class_name = nil, reflection = nil)
|
|
146
|
+
if owner_class_name && reflection
|
|
147
|
+
super("Cannot have a has_one :through association '#{owner_class_name}##{reflection.name}' which goes through the polymorphic association '#{owner_class_name}##{reflection.through_reflection.name}'.")
|
|
148
|
+
else
|
|
149
|
+
super("Cannot have a has_one :through association.")
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
class HasManyThroughSourceAssociationNotFoundError < ActiveRecordError # :nodoc:
|
|
155
|
+
def initialize(reflection = nil)
|
|
156
|
+
if reflection
|
|
157
|
+
through_reflection = reflection.through_reflection
|
|
158
|
+
source_reflection_names = reflection.source_reflection_names
|
|
159
|
+
source_associations = reflection.through_reflection.klass._reflections.keys
|
|
160
|
+
super("Could not find the source association(s) #{source_reflection_names.collect(&:inspect).to_sentence(two_words_connector: ' or ', last_word_connector: ', or ')} in model #{through_reflection.klass}. Try 'has_many #{reflection.name.inspect}, :through => #{through_reflection.name.inspect}, :source => <name>'. Is it one of #{source_associations.to_sentence(two_words_connector: ' or ', last_word_connector: ', or ')}?")
|
|
161
|
+
else
|
|
162
|
+
super("Could not find the source association(s).")
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
class HasManyThroughOrderError < ActiveRecordError # :nodoc:
|
|
168
|
+
def initialize(owner_class_name = nil, reflection = nil, through_reflection = nil)
|
|
169
|
+
if owner_class_name && reflection && through_reflection
|
|
170
|
+
super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' which goes through '#{owner_class_name}##{through_reflection.name}' before the through association is defined.")
|
|
171
|
+
else
|
|
172
|
+
super("Cannot have a has_many :through association before the through association is defined.")
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
class ThroughCantAssociateThroughHasOneOrManyReflection < ActiveRecordError # :nodoc:
|
|
178
|
+
def initialize(owner = nil, reflection = nil)
|
|
179
|
+
if owner && reflection
|
|
180
|
+
super("Cannot modify association '#{owner.class.name}##{reflection.name}' because the source reflection class '#{reflection.source_reflection.class_name}' is associated to '#{reflection.through_reflection.class_name}' via :#{reflection.source_reflection.macro}.")
|
|
181
|
+
else
|
|
182
|
+
super("Cannot modify association.")
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
class CompositePrimaryKeyMismatchError < ActiveRecordError # :nodoc:
|
|
188
|
+
attr_reader :reflection
|
|
189
|
+
|
|
190
|
+
def initialize(reflection = nil)
|
|
191
|
+
if reflection
|
|
192
|
+
if reflection.has_one? || reflection.collection?
|
|
193
|
+
super("Association #{reflection.active_record}##{reflection.name} primary key #{reflection.active_record_primary_key} doesn't match with foreign key #{reflection.foreign_key}. Please specify query_constraints, or primary_key and foreign_key values.")
|
|
194
|
+
else
|
|
195
|
+
super("Association #{reflection.active_record}##{reflection.name} primary key #{reflection.association_primary_key} doesn't match with foreign key #{reflection.foreign_key}. Please specify query_constraints, or primary_key and foreign_key values.")
|
|
196
|
+
end
|
|
197
|
+
else
|
|
198
|
+
super("Association primary key doesn't match with foreign key.")
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
class AmbiguousSourceReflectionForThroughAssociation < ActiveRecordError # :nodoc:
|
|
204
|
+
def initialize(klass, macro, association_name, options, possible_sources)
|
|
205
|
+
example_options = options.dup
|
|
206
|
+
example_options[:source] = possible_sources.first
|
|
207
|
+
|
|
208
|
+
super("Ambiguous source reflection for through association. Please " \
|
|
209
|
+
"specify a :source directive on your declaration like:\n" \
|
|
210
|
+
"\n" \
|
|
211
|
+
" class #{klass} < ActiveRecord::Base\n" \
|
|
212
|
+
" #{macro} :#{association_name}, #{example_options}\n" \
|
|
213
|
+
" end"
|
|
214
|
+
)
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
class HasManyThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection # :nodoc:
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
class HasOneThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection # :nodoc:
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
class ThroughNestedAssociationsAreReadonly < ActiveRecordError # :nodoc:
|
|
225
|
+
def initialize(owner = nil, reflection = nil)
|
|
226
|
+
if owner && reflection
|
|
227
|
+
super("Cannot modify association '#{owner.class.name}##{reflection.name}' because it goes through more than one other association.")
|
|
228
|
+
else
|
|
229
|
+
super("Through nested associations are read-only.")
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
class HasManyThroughNestedAssociationsAreReadonly < ThroughNestedAssociationsAreReadonly # :nodoc:
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
class HasOneThroughNestedAssociationsAreReadonly < ThroughNestedAssociationsAreReadonly # :nodoc:
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
# This error is raised when trying to eager load a polymorphic association using a JOIN.
|
|
241
|
+
# Eager loading polymorphic associations is only possible with
|
|
242
|
+
# {ActiveRecord::Relation#preload}[rdoc-ref:QueryMethods#preload].
|
|
243
|
+
class EagerLoadPolymorphicError < ActiveRecordError
|
|
244
|
+
def initialize(reflection = nil)
|
|
245
|
+
if reflection
|
|
246
|
+
super("Cannot eagerly load the polymorphic association #{reflection.name.inspect}")
|
|
247
|
+
else
|
|
248
|
+
super("Eager load polymorphic error.")
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
# This error is raised when trying to destroy a parent instance in N:1 or 1:1 associations
|
|
254
|
+
# (has_many, has_one) when there is at least 1 child associated instance.
|
|
255
|
+
# ex: if @project.tasks.size > 0, DeleteRestrictionError will be raised when trying to destroy @project
|
|
256
|
+
class DeleteRestrictionError < ActiveRecordError # :nodoc:
|
|
257
|
+
def initialize(name = nil)
|
|
258
|
+
if name
|
|
259
|
+
super("Cannot delete record because of dependent #{name}")
|
|
260
|
+
else
|
|
261
|
+
super("Delete restriction error.")
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord::Associations
|
|
4
|
+
module ForeignAssociation # :nodoc:
|
|
5
|
+
def foreign_key_present?
|
|
6
|
+
if reflection.klass.primary_key
|
|
7
|
+
owner.attribute_present?(reflection.active_record_primary_key)
|
|
8
|
+
else
|
|
9
|
+
false
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def nullified_owner_attributes
|
|
14
|
+
Hash.new.tap do |attrs|
|
|
15
|
+
Array(reflection.foreign_key).each { |foreign_key| attrs[foreign_key] = nil }
|
|
16
|
+
attrs[reflection.type] = nil if reflection.type.present?
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
# Sets the owner attributes on the given record
|
|
22
|
+
def set_owner_attributes(record)
|
|
23
|
+
return if options[:through]
|
|
24
|
+
|
|
25
|
+
primary_key_attribute_names = Array(reflection.join_primary_key)
|
|
26
|
+
foreign_key_attribute_names = Array(reflection.join_foreign_key)
|
|
27
|
+
|
|
28
|
+
primary_key_foreign_key_pairs = primary_key_attribute_names.zip(foreign_key_attribute_names)
|
|
29
|
+
|
|
30
|
+
primary_key_foreign_key_pairs.each do |primary_key, foreign_key|
|
|
31
|
+
value = owner._read_attribute(foreign_key)
|
|
32
|
+
record._write_attribute(primary_key, value)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
if reflection.type
|
|
36
|
+
record._write_attribute(reflection.type, owner.class.polymorphic_name)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
module Associations
|
|
5
|
+
# = Active Record Has Many Association
|
|
6
|
+
#
|
|
7
|
+
# This is the proxy that handles a has many association.
|
|
8
|
+
#
|
|
9
|
+
# If the association has a <tt>:through</tt> option further specialization
|
|
10
|
+
# is provided by its child HasManyThroughAssociation.
|
|
11
|
+
class HasManyAssociation < CollectionAssociation # :nodoc:
|
|
12
|
+
include ForeignAssociation
|
|
13
|
+
|
|
14
|
+
def handle_dependency
|
|
15
|
+
case options[:dependent]
|
|
16
|
+
when :restrict_with_exception
|
|
17
|
+
raise ActiveRecord::DeleteRestrictionError.new(reflection.name) unless empty?
|
|
18
|
+
|
|
19
|
+
when :restrict_with_error
|
|
20
|
+
unless empty?
|
|
21
|
+
record = owner.class.human_attribute_name(reflection.name).downcase
|
|
22
|
+
owner.errors.add(:base, :'restrict_dependent_destroy.has_many', record: record)
|
|
23
|
+
throw(:abort)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
when :destroy
|
|
27
|
+
# No point in executing the counter update since we're going to destroy the parent anyway
|
|
28
|
+
load_target.each { |t| t.destroyed_by_association = reflection }
|
|
29
|
+
destroy_all
|
|
30
|
+
when :destroy_async
|
|
31
|
+
load_target.each do |t|
|
|
32
|
+
t.destroyed_by_association = reflection
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
unless target.empty?
|
|
36
|
+
association_class = target.first.class
|
|
37
|
+
if association_class.query_constraints_list
|
|
38
|
+
primary_key_column = association_class.query_constraints_list
|
|
39
|
+
ids = target.collect { |assoc| primary_key_column.map { |col| assoc.public_send(col) } }
|
|
40
|
+
else
|
|
41
|
+
primary_key_column = association_class.primary_key
|
|
42
|
+
ids = target.collect { |assoc| assoc.public_send(primary_key_column) }
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
ids.each_slice(owner.class.destroy_association_async_batch_size || ids.size) do |ids_batch|
|
|
46
|
+
enqueue_destroy_association(
|
|
47
|
+
owner_model_name: owner.class.to_s,
|
|
48
|
+
owner_id: owner.id,
|
|
49
|
+
association_class: reflection.klass.to_s,
|
|
50
|
+
association_ids: ids_batch,
|
|
51
|
+
association_primary_key_column: primary_key_column,
|
|
52
|
+
ensuring_owner_was_method: options.fetch(:ensuring_owner_was, nil)
|
|
53
|
+
)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
else
|
|
57
|
+
delete_all
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def insert_record(record, validate = true, raise = false)
|
|
62
|
+
set_owner_attributes(record)
|
|
63
|
+
super
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
private
|
|
67
|
+
# Returns the number of records in this collection.
|
|
68
|
+
#
|
|
69
|
+
# If the association has a counter cache it gets that value. Otherwise
|
|
70
|
+
# it will attempt to do a count via SQL, bounded to <tt>:limit</tt> if
|
|
71
|
+
# there's one. Some configuration options like :group make it impossible
|
|
72
|
+
# to do an SQL count, in those cases the array count will be used.
|
|
73
|
+
#
|
|
74
|
+
# That does not depend on whether the collection has already been loaded
|
|
75
|
+
# or not. The +size+ method is the one that takes the loaded flag into
|
|
76
|
+
# account and delegates to +count_records+ if needed.
|
|
77
|
+
#
|
|
78
|
+
# If the collection is empty the target is set to an empty array and
|
|
79
|
+
# the loaded flag is set to true as well.
|
|
80
|
+
def count_records
|
|
81
|
+
count = if reflection.has_active_cached_counter?
|
|
82
|
+
owner.read_attribute(reflection.counter_cache_column).to_i
|
|
83
|
+
else
|
|
84
|
+
scope.count(:all)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# If there's nothing in the database, @target should only contain new
|
|
88
|
+
# records or be an empty array. This is a documented side-effect of
|
|
89
|
+
# the method that may avoid an extra SELECT.
|
|
90
|
+
if count == 0
|
|
91
|
+
target.select!(&:new_record?)
|
|
92
|
+
loaded!
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
[association_scope.limit_value, count].compact.min
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def update_counter(difference, reflection = reflection())
|
|
99
|
+
if reflection.has_cached_counter?
|
|
100
|
+
owner.increment!(reflection.counter_cache_column, difference)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def update_counter_in_memory(difference, reflection = reflection())
|
|
105
|
+
if reflection.counter_must_be_updated_by_has_many?
|
|
106
|
+
counter = reflection.counter_cache_column
|
|
107
|
+
owner.increment(counter, difference)
|
|
108
|
+
owner.send(:"clear_#{counter}_change")
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def delete_count(method, scope)
|
|
113
|
+
if method == :delete_all
|
|
114
|
+
scope.delete_all
|
|
115
|
+
else
|
|
116
|
+
scope.update_all(nullified_owner_attributes)
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def delete_or_nullify_all_records(method)
|
|
121
|
+
count = delete_count(method, scope)
|
|
122
|
+
update_counter(-count)
|
|
123
|
+
count
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Deletes the records according to the <tt>:dependent</tt> option.
|
|
127
|
+
def delete_records(records, method)
|
|
128
|
+
if method == :destroy
|
|
129
|
+
records.each(&:destroy!)
|
|
130
|
+
update_counter(-records.length) unless reflection.inverse_updates_counter_cache?
|
|
131
|
+
else
|
|
132
|
+
query_constraints = reflection.klass.composite_query_constraints_list
|
|
133
|
+
values = records.map { |r| query_constraints.map { |col| r._read_attribute(col) } }
|
|
134
|
+
scope = self.scope.where(query_constraints => values)
|
|
135
|
+
update_counter(-delete_count(method, scope))
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def concat_records(records, *)
|
|
140
|
+
update_counter_if_success(super, records.length)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def _create_record(attributes, *)
|
|
144
|
+
if attributes.is_a?(Array)
|
|
145
|
+
super
|
|
146
|
+
else
|
|
147
|
+
update_counter_if_success(super, 1)
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def update_counter_if_success(saved_successfully, difference)
|
|
152
|
+
if saved_successfully
|
|
153
|
+
update_counter_in_memory(difference)
|
|
154
|
+
end
|
|
155
|
+
saved_successfully
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def difference(a, b)
|
|
159
|
+
a - b
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def intersection(a, b)
|
|
163
|
+
a & b
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|