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,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
module Type
|
|
5
|
+
class DecimalWithoutScale < ActiveModel::Type::BigInteger # :nodoc:
|
|
6
|
+
def type
|
|
7
|
+
:decimal
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def type_cast_for_schema(value)
|
|
11
|
+
value.to_s.inspect
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
module Type
|
|
5
|
+
class HashLookupTypeMap # :nodoc:
|
|
6
|
+
def initialize(parent = nil)
|
|
7
|
+
@mapping = {}
|
|
8
|
+
@cache = Concurrent::Map.new do |h, key|
|
|
9
|
+
h.fetch_or_store(key, Concurrent::Map.new)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def lookup(lookup_key, *args)
|
|
14
|
+
fetch(lookup_key, *args) { Type.default_value }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def fetch(lookup_key, *args, &block)
|
|
18
|
+
@cache[lookup_key].fetch_or_store(args) do
|
|
19
|
+
perform_fetch(lookup_key, *args, &block)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def register_type(key, value = nil, &block)
|
|
24
|
+
raise ::ArgumentError unless value || block
|
|
25
|
+
|
|
26
|
+
if block
|
|
27
|
+
@mapping[key] = block
|
|
28
|
+
else
|
|
29
|
+
@mapping[key] = proc { value }
|
|
30
|
+
end
|
|
31
|
+
@cache.clear
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def clear
|
|
35
|
+
@mapping.clear
|
|
36
|
+
@cache.clear
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def alias_type(type, alias_type)
|
|
40
|
+
register_type(type) { |_, *args| lookup(alias_type, *args) }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def key?(key)
|
|
44
|
+
@mapping.key?(key)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def keys
|
|
48
|
+
@mapping.keys
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
private
|
|
52
|
+
def perform_fetch(type, *args, &block)
|
|
53
|
+
@mapping.fetch(type, block).call(type, *args)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
module Type
|
|
5
|
+
module Internal
|
|
6
|
+
module Timezone
|
|
7
|
+
def initialize(timezone: nil, **kwargs)
|
|
8
|
+
super(**kwargs)
|
|
9
|
+
@timezone = timezone
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def is_utc?
|
|
13
|
+
default_timezone == :utc
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def default_timezone
|
|
17
|
+
@timezone || ActiveRecord.default_timezone
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
module Type
|
|
5
|
+
class Json < ActiveModel::Type::Value
|
|
6
|
+
include ActiveModel::Type::Helpers::Mutable
|
|
7
|
+
|
|
8
|
+
def type
|
|
9
|
+
:json
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def deserialize(value)
|
|
13
|
+
return value unless value.is_a?(::String)
|
|
14
|
+
ActiveSupport::JSON.decode(value) rescue nil
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def serialize(value)
|
|
18
|
+
ActiveSupport::JSON.encode(value) unless value.nil?
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def changed_in_place?(raw_old_value, new_value)
|
|
22
|
+
deserialize(raw_old_value) != new_value
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def accessor
|
|
26
|
+
ActiveRecord::Store::StringKeyedHashAccessor
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
module Type
|
|
5
|
+
class Serialized < DelegateClass(ActiveModel::Type::Value) # :nodoc:
|
|
6
|
+
undef to_yaml if method_defined?(:to_yaml)
|
|
7
|
+
|
|
8
|
+
include ActiveModel::Type::Helpers::Mutable
|
|
9
|
+
|
|
10
|
+
attr_reader :subtype, :coder
|
|
11
|
+
|
|
12
|
+
def initialize(subtype, coder)
|
|
13
|
+
@subtype = subtype
|
|
14
|
+
@coder = coder
|
|
15
|
+
super(subtype)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def deserialize(value)
|
|
19
|
+
if default_value?(value)
|
|
20
|
+
value
|
|
21
|
+
else
|
|
22
|
+
coder.load(super)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def serialize(value)
|
|
27
|
+
return if value.nil?
|
|
28
|
+
unless default_value?(value)
|
|
29
|
+
super coder.dump(value)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
define_method(:inspect, Kernel.instance_method(:inspect))
|
|
34
|
+
|
|
35
|
+
def changed_in_place?(raw_old_value, value)
|
|
36
|
+
return false if value.nil?
|
|
37
|
+
raw_new_value = encoded(value)
|
|
38
|
+
raw_old_value.nil? != raw_new_value.nil? ||
|
|
39
|
+
subtype.changed_in_place?(raw_old_value, raw_new_value)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def accessor
|
|
43
|
+
ActiveRecord::Store::IndifferentHashAccessor
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def assert_valid_value(value)
|
|
47
|
+
if coder.respond_to?(:assert_valid_value)
|
|
48
|
+
coder.assert_valid_value(value, action: "serialize")
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def force_equality?(value)
|
|
53
|
+
coder.respond_to?(:object_class) && value.is_a?(coder.object_class)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def serialized? # :nodoc:
|
|
57
|
+
true
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
private
|
|
61
|
+
def default_value?(value)
|
|
62
|
+
value == coder.load(nil)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def encoded(value)
|
|
66
|
+
return if default_value?(value)
|
|
67
|
+
payload = coder.dump(value)
|
|
68
|
+
if payload && @subtype.binary?
|
|
69
|
+
ActiveModel::Type::Binary::Data.new(payload)
|
|
70
|
+
else
|
|
71
|
+
payload
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
module Type
|
|
5
|
+
class Time < ActiveModel::Type::Time
|
|
6
|
+
include Internal::Timezone
|
|
7
|
+
|
|
8
|
+
class Value < DelegateClass(::Time) # :nodoc:
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def serialize(value)
|
|
12
|
+
case value = super
|
|
13
|
+
when ::Time
|
|
14
|
+
Value.new(value)
|
|
15
|
+
else
|
|
16
|
+
value
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def serialize_cast_value(value) # :nodoc:
|
|
21
|
+
Value.new(super) if value
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
def cast_value(value)
|
|
26
|
+
case value = super
|
|
27
|
+
when Value
|
|
28
|
+
value.__getobj__
|
|
29
|
+
else
|
|
30
|
+
value
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "concurrent/map"
|
|
4
|
+
|
|
5
|
+
module ActiveRecord
|
|
6
|
+
module Type
|
|
7
|
+
class TypeMap # :nodoc:
|
|
8
|
+
def initialize(parent = nil)
|
|
9
|
+
@mapping = {}
|
|
10
|
+
@parent = parent
|
|
11
|
+
@cache = Concurrent::Map.new
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def lookup(lookup_key)
|
|
15
|
+
fetch(lookup_key) { Type.default_value }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def fetch(lookup_key, &block)
|
|
19
|
+
@cache.fetch_or_store(lookup_key) do
|
|
20
|
+
perform_fetch(lookup_key, &block)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def register_type(key, value = nil, &block)
|
|
25
|
+
raise ::ArgumentError unless value || block
|
|
26
|
+
|
|
27
|
+
if block
|
|
28
|
+
@mapping[key] = block
|
|
29
|
+
else
|
|
30
|
+
@mapping[key] = proc { value }
|
|
31
|
+
end
|
|
32
|
+
@cache.clear
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def alias_type(key, target_key)
|
|
36
|
+
register_type(key) do |sql_type|
|
|
37
|
+
metadata = sql_type[/\(.*\)/, 0]
|
|
38
|
+
lookup("#{target_key}#{metadata}")
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
protected
|
|
43
|
+
def perform_fetch(lookup_key, &block)
|
|
44
|
+
matching_pair = @mapping.reverse_each.detect do |key, _|
|
|
45
|
+
key === lookup_key
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
if matching_pair
|
|
49
|
+
matching_pair.last.call(lookup_key)
|
|
50
|
+
elsif @parent
|
|
51
|
+
@parent.perform_fetch(lookup_key, &block)
|
|
52
|
+
else
|
|
53
|
+
yield lookup_key
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_model/type"
|
|
4
|
+
|
|
5
|
+
require "active_record/type/internal/timezone"
|
|
6
|
+
|
|
7
|
+
require "active_record/type/date"
|
|
8
|
+
require "active_record/type/date_time"
|
|
9
|
+
require "active_record/type/decimal_without_scale"
|
|
10
|
+
require "active_record/type/json"
|
|
11
|
+
require "active_record/type/time"
|
|
12
|
+
require "active_record/type/text"
|
|
13
|
+
require "active_record/type/unsigned_integer"
|
|
14
|
+
|
|
15
|
+
require "active_record/type/serialized"
|
|
16
|
+
require "active_record/type/adapter_specific_registry"
|
|
17
|
+
|
|
18
|
+
require "active_record/type/type_map"
|
|
19
|
+
require "active_record/type/hash_lookup_type_map"
|
|
20
|
+
|
|
21
|
+
module ActiveRecord
|
|
22
|
+
module Type
|
|
23
|
+
@registry = AdapterSpecificRegistry.new
|
|
24
|
+
|
|
25
|
+
class << self
|
|
26
|
+
attr_accessor :registry # :nodoc:
|
|
27
|
+
delegate :add_modifier, to: :registry
|
|
28
|
+
|
|
29
|
+
# Add a new type to the registry, allowing it to be referenced as a
|
|
30
|
+
# symbol by {ActiveRecord::Base.attribute}[rdoc-ref:Attributes::ClassMethods#attribute].
|
|
31
|
+
# If your type is only meant to be used with a specific database adapter, you can
|
|
32
|
+
# do so by passing <tt>adapter: :postgresql</tt>. If your type has the same
|
|
33
|
+
# name as a native type for the current adapter, an exception will be
|
|
34
|
+
# raised unless you specify an +:override+ option. <tt>override: true</tt> will
|
|
35
|
+
# cause your type to be used instead of the native type. <tt>override:
|
|
36
|
+
# false</tt> will cause the native type to be used over yours if one exists.
|
|
37
|
+
def register(type_name, klass = nil, **options, &block)
|
|
38
|
+
registry.register(type_name, klass, **options, &block)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def lookup(*args, adapter: current_adapter_name, **kwargs) # :nodoc:
|
|
42
|
+
registry.lookup(*args, adapter: adapter, **kwargs)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def default_value # :nodoc:
|
|
46
|
+
@default_value ||= Value.new
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def adapter_name_from(model) # :nodoc:
|
|
50
|
+
model.connection_db_config.adapter.to_sym
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
def current_adapter_name
|
|
55
|
+
adapter_name_from(ActiveRecord::Base)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
BigInteger = ActiveModel::Type::BigInteger
|
|
60
|
+
Binary = ActiveModel::Type::Binary
|
|
61
|
+
Boolean = ActiveModel::Type::Boolean
|
|
62
|
+
Decimal = ActiveModel::Type::Decimal
|
|
63
|
+
Float = ActiveModel::Type::Float
|
|
64
|
+
Integer = ActiveModel::Type::Integer
|
|
65
|
+
ImmutableString = ActiveModel::Type::ImmutableString
|
|
66
|
+
String = ActiveModel::Type::String
|
|
67
|
+
Value = ActiveModel::Type::Value
|
|
68
|
+
|
|
69
|
+
register(:big_integer, Type::BigInteger, override: false)
|
|
70
|
+
register(:binary, Type::Binary, override: false)
|
|
71
|
+
register(:boolean, Type::Boolean, override: false)
|
|
72
|
+
register(:date, Type::Date, override: false)
|
|
73
|
+
register(:datetime, Type::DateTime, override: false)
|
|
74
|
+
register(:decimal, Type::Decimal, override: false)
|
|
75
|
+
register(:float, Type::Float, override: false)
|
|
76
|
+
register(:integer, Type::Integer, override: false)
|
|
77
|
+
register(:immutable_string, Type::ImmutableString, override: false)
|
|
78
|
+
register(:json, Type::Json, override: false)
|
|
79
|
+
register(:string, Type::String, override: false)
|
|
80
|
+
register(:text, Type::Text, override: false)
|
|
81
|
+
register(:time, Type::Time, override: false)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
module TypeCaster
|
|
5
|
+
class Connection # :nodoc:
|
|
6
|
+
def initialize(klass, table_name)
|
|
7
|
+
@klass = klass
|
|
8
|
+
@table_name = table_name
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def type_cast_for_database(attr_name, value)
|
|
12
|
+
type = type_for_attribute(attr_name)
|
|
13
|
+
type.serialize(value)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def type_for_attribute(attr_name)
|
|
17
|
+
schema_cache = @klass.schema_cache
|
|
18
|
+
|
|
19
|
+
if schema_cache.data_source_exists?(table_name)
|
|
20
|
+
column = schema_cache.columns_hash(table_name)[attr_name.to_s]
|
|
21
|
+
if column
|
|
22
|
+
type = @klass.with_connection { |connection| connection.lookup_cast_type_from_column(column) }
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
type || Type.default_value
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
attr_reader :table_name
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
module TypeCaster
|
|
5
|
+
class Map # :nodoc:
|
|
6
|
+
def initialize(klass)
|
|
7
|
+
@klass = klass
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def type_cast_for_database(attr_name, value)
|
|
11
|
+
type = type_for_attribute(attr_name)
|
|
12
|
+
type.serialize(value)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def type_for_attribute(name)
|
|
16
|
+
klass.type_for_attribute(name)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
attr_reader :klass
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
module Validations
|
|
5
|
+
class AbsenceValidator < ActiveModel::Validations::AbsenceValidator # :nodoc:
|
|
6
|
+
def validate_each(record, attribute, association_or_value)
|
|
7
|
+
if record.class._reflect_on_association(attribute)
|
|
8
|
+
association_or_value = Array.wrap(association_or_value).reject(&:marked_for_destruction?)
|
|
9
|
+
end
|
|
10
|
+
super
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
module ClassMethods
|
|
15
|
+
# Validates that the specified attributes are not present (as defined by
|
|
16
|
+
# Object#present?). If the attribute is an association, the associated object
|
|
17
|
+
# is also considered not present if it is marked for destruction.
|
|
18
|
+
#
|
|
19
|
+
# See ActiveModel::Validations::HelperMethods.validates_absence_of for more information.
|
|
20
|
+
def validates_absence_of(*attr_names)
|
|
21
|
+
validates_with AbsenceValidator, _merge_attributes(attr_names)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
module Validations
|
|
5
|
+
class AssociatedValidator < ActiveModel::EachValidator # :nodoc:
|
|
6
|
+
def validate_each(record, attribute, value)
|
|
7
|
+
context = record_validation_context_for_association(record)
|
|
8
|
+
|
|
9
|
+
if Array(value).reject { |association| valid_object?(association, context) }.any?
|
|
10
|
+
record.errors.add(attribute, :invalid, **options.merge(value: value))
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
def valid_object?(record, context)
|
|
16
|
+
(record.respond_to?(:marked_for_destruction?) && record.marked_for_destruction?) || record.valid?(context)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def record_validation_context_for_association(record)
|
|
20
|
+
record.custom_validation_context? ? record.validation_context : nil
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
module ClassMethods
|
|
25
|
+
# Validates whether the associated object or objects are all valid.
|
|
26
|
+
# Works with any kind of association.
|
|
27
|
+
#
|
|
28
|
+
# class Book < ActiveRecord::Base
|
|
29
|
+
# has_many :pages
|
|
30
|
+
# belongs_to :library
|
|
31
|
+
#
|
|
32
|
+
# validates_associated :pages, :library
|
|
33
|
+
# end
|
|
34
|
+
#
|
|
35
|
+
# WARNING: This validation must not be used on both ends of an association.
|
|
36
|
+
# Doing so will lead to a circular dependency and cause infinite recursion.
|
|
37
|
+
#
|
|
38
|
+
# NOTE: This validation will not fail if the association hasn't been
|
|
39
|
+
# assigned. If you want to ensure that the association is both present and
|
|
40
|
+
# guaranteed to be valid, you also need to use
|
|
41
|
+
# {validates_presence_of}[rdoc-ref:Validations::ClassMethods#validates_presence_of].
|
|
42
|
+
#
|
|
43
|
+
# Configuration options:
|
|
44
|
+
#
|
|
45
|
+
# * <tt>:message</tt> - A custom error message (default is: "is invalid").
|
|
46
|
+
# * <tt>:on</tt> - Specifies the contexts where this validation is active.
|
|
47
|
+
# Runs in all validation contexts by default +nil+. You can pass a symbol
|
|
48
|
+
# or an array of symbols. (e.g. <tt>on: :create</tt> or
|
|
49
|
+
# <tt>on: :custom_validation_context</tt> or
|
|
50
|
+
# <tt>on: [:create, :custom_validation_context]</tt>)
|
|
51
|
+
# * <tt>:if</tt> - Specifies a method, proc, or string to call to determine
|
|
52
|
+
# if the validation should occur (e.g. <tt>if: :allow_validation</tt>,
|
|
53
|
+
# or <tt>if: Proc.new { |user| user.signup_step > 2 }</tt>). The method,
|
|
54
|
+
# proc or string should return or evaluate to a +true+ or +false+ value.
|
|
55
|
+
# * <tt>:unless</tt> - Specifies a method, proc, or string to call to
|
|
56
|
+
# determine if the validation should not occur (e.g. <tt>unless: :skip_validation</tt>,
|
|
57
|
+
# or <tt>unless: Proc.new { |user| user.signup_step <= 2 }</tt>). The
|
|
58
|
+
# method, proc, or string should return or evaluate to a +true+ or +false+
|
|
59
|
+
# value.
|
|
60
|
+
def validates_associated(*attr_names)
|
|
61
|
+
validates_with AssociatedValidator, _merge_attributes(attr_names)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
module Validations
|
|
5
|
+
class LengthValidator < ActiveModel::Validations::LengthValidator # :nodoc:
|
|
6
|
+
def validate_each(record, attribute, association_or_value)
|
|
7
|
+
if association_or_value.respond_to?(:loaded?) && association_or_value.loaded?
|
|
8
|
+
association_or_value = association_or_value.target.reject(&:marked_for_destruction?)
|
|
9
|
+
end
|
|
10
|
+
super
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
module ClassMethods
|
|
15
|
+
# Validates that the specified attributes match the length restrictions supplied.
|
|
16
|
+
# If the attribute is an association, records that are marked for destruction are not counted.
|
|
17
|
+
#
|
|
18
|
+
# See ActiveModel::Validations::HelperMethods.validates_length_of for more information.
|
|
19
|
+
def validates_length_of(*attr_names)
|
|
20
|
+
validates_with LengthValidator, _merge_attributes(attr_names)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
alias_method :validates_size_of, :validates_length_of
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
module Validations
|
|
5
|
+
class NumericalityValidator < ActiveModel::Validations::NumericalityValidator # :nodoc:
|
|
6
|
+
def validate_each(record, attribute, value, precision: nil, scale: nil)
|
|
7
|
+
precision = [column_precision_for(record, attribute) || Float::DIG, Float::DIG].min
|
|
8
|
+
scale = column_scale_for(record, attribute)
|
|
9
|
+
super(record, attribute, value, precision: precision, scale: scale)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
def column_precision_for(record, attribute)
|
|
14
|
+
record.class.type_for_attribute(attribute.to_s)&.precision
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def column_scale_for(record, attribute)
|
|
18
|
+
record.class.type_for_attribute(attribute.to_s)&.scale
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
module ClassMethods
|
|
23
|
+
# Validates whether the value of the specified attribute is numeric by
|
|
24
|
+
# trying to convert it to a float with +Kernel.Float+ (if
|
|
25
|
+
# <tt>only_integer</tt> is +false+) or applying it to the regular
|
|
26
|
+
# expression <tt>/\A[\+\-]?\d+\z/</tt> (if <tt>only_integer</tt> is set to
|
|
27
|
+
# +true+). +Kernel.Float+ precision defaults to the column's precision
|
|
28
|
+
# value or 15.
|
|
29
|
+
#
|
|
30
|
+
# See ActiveModel::Validations::HelperMethods.validates_numericality_of for more information.
|
|
31
|
+
def validates_numericality_of(*attr_names)
|
|
32
|
+
validates_with NumericalityValidator, _merge_attributes(attr_names)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|