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,158 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "set"
|
4
|
+
|
5
|
+
module ActiveRecord
|
6
|
+
module AttributeMethods
|
7
|
+
# = Active Record Attribute Methods Primary Key
|
8
|
+
module PrimaryKey
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
# Returns this record's primary key value wrapped in an array if one is
|
12
|
+
# available.
|
13
|
+
def to_key
|
14
|
+
key = id
|
15
|
+
Array(key) if key
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns the primary key column's value. If the primary key is composite,
|
19
|
+
# returns an array of the primary key column values.
|
20
|
+
def id
|
21
|
+
_read_attribute(@primary_key)
|
22
|
+
end
|
23
|
+
|
24
|
+
def primary_key_values_present? # :nodoc:
|
25
|
+
!!id
|
26
|
+
end
|
27
|
+
|
28
|
+
# Sets the primary key column's value. If the primary key is composite,
|
29
|
+
# raises TypeError when the set value not enumerable.
|
30
|
+
def id=(value)
|
31
|
+
_write_attribute(@primary_key, value)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Queries the primary key column's value. If the primary key is composite,
|
35
|
+
# all primary key column values must be queryable.
|
36
|
+
def id?
|
37
|
+
_query_attribute(@primary_key)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns the primary key column's value before type cast. If the primary key is composite,
|
41
|
+
# returns an array of primary key column values before type cast.
|
42
|
+
def id_before_type_cast
|
43
|
+
attribute_before_type_cast(@primary_key)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns the primary key column's previous value. If the primary key is composite,
|
47
|
+
# returns an array of primary key column previous values.
|
48
|
+
def id_was
|
49
|
+
attribute_was(@primary_key)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Returns the primary key column's value from the database. If the primary key is composite,
|
53
|
+
# returns an array of primary key column values from database.
|
54
|
+
def id_in_database
|
55
|
+
attribute_in_database(@primary_key)
|
56
|
+
end
|
57
|
+
|
58
|
+
def id_for_database # :nodoc:
|
59
|
+
@attributes[@primary_key].value_for_database
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
def attribute_method?(attr_name)
|
64
|
+
attr_name == "id" || super
|
65
|
+
end
|
66
|
+
|
67
|
+
module ClassMethods
|
68
|
+
ID_ATTRIBUTE_METHODS = %w(id id= id? id_before_type_cast id_was id_in_database id_for_database).to_set
|
69
|
+
PRIMARY_KEY_NOT_SET = BasicObject.new
|
70
|
+
|
71
|
+
def instance_method_already_implemented?(method_name)
|
72
|
+
super || primary_key && ID_ATTRIBUTE_METHODS.include?(method_name)
|
73
|
+
end
|
74
|
+
|
75
|
+
def dangerous_attribute_method?(method_name)
|
76
|
+
super && !ID_ATTRIBUTE_METHODS.include?(method_name)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Defines the primary key field -- can be overridden in subclasses.
|
80
|
+
# Overwriting will negate any effect of the +primary_key_prefix_type+
|
81
|
+
# setting, though.
|
82
|
+
def primary_key
|
83
|
+
reset_primary_key if PRIMARY_KEY_NOT_SET.equal?(@primary_key)
|
84
|
+
@primary_key
|
85
|
+
end
|
86
|
+
|
87
|
+
def composite_primary_key? # :nodoc:
|
88
|
+
reset_primary_key if PRIMARY_KEY_NOT_SET.equal?(@primary_key)
|
89
|
+
@composite_primary_key
|
90
|
+
end
|
91
|
+
|
92
|
+
# Returns a quoted version of the primary key name, used to construct
|
93
|
+
# SQL statements.
|
94
|
+
def quoted_primary_key
|
95
|
+
@quoted_primary_key ||= adapter_class.quote_column_name(primary_key)
|
96
|
+
end
|
97
|
+
|
98
|
+
def reset_primary_key # :nodoc:
|
99
|
+
if base_class?
|
100
|
+
self.primary_key = get_primary_key(base_class.name)
|
101
|
+
else
|
102
|
+
self.primary_key = base_class.primary_key
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def get_primary_key(base_name) # :nodoc:
|
107
|
+
if base_name && primary_key_prefix_type == :table_name
|
108
|
+
base_name.foreign_key(false)
|
109
|
+
elsif base_name && primary_key_prefix_type == :table_name_with_underscore
|
110
|
+
base_name.foreign_key
|
111
|
+
elsif ActiveRecord::Base != self && table_exists?
|
112
|
+
schema_cache.primary_keys(table_name)
|
113
|
+
else
|
114
|
+
"id"
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# Sets the name of the primary key column.
|
119
|
+
#
|
120
|
+
# class Project < ActiveRecord::Base
|
121
|
+
# self.primary_key = 'sysid'
|
122
|
+
# end
|
123
|
+
#
|
124
|
+
# You can also define the #primary_key method yourself:
|
125
|
+
#
|
126
|
+
# class Project < ActiveRecord::Base
|
127
|
+
# def self.primary_key
|
128
|
+
# 'foo_' + super
|
129
|
+
# end
|
130
|
+
# end
|
131
|
+
#
|
132
|
+
# Project.primary_key # => "foo_id"
|
133
|
+
def primary_key=(value)
|
134
|
+
@primary_key = if value.is_a?(Array)
|
135
|
+
@composite_primary_key = true
|
136
|
+
include CompositePrimaryKey
|
137
|
+
@primary_key = value.map { |v| -v.to_s }.freeze
|
138
|
+
elsif value
|
139
|
+
-value.to_s
|
140
|
+
end
|
141
|
+
@quoted_primary_key = nil
|
142
|
+
@attributes_builder = nil
|
143
|
+
end
|
144
|
+
|
145
|
+
private
|
146
|
+
def inherited(base)
|
147
|
+
super
|
148
|
+
base.class_eval do
|
149
|
+
@primary_key = PRIMARY_KEY_NOT_SET
|
150
|
+
@composite_primary_key = false
|
151
|
+
@quoted_primary_key = nil
|
152
|
+
@attributes_builder = nil
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module AttributeMethods
|
5
|
+
# = Active Record Attribute Methods \Query
|
6
|
+
module Query
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
attribute_method_suffix "?", parameters: false
|
11
|
+
end
|
12
|
+
|
13
|
+
def query_attribute(attr_name)
|
14
|
+
value = self.public_send(attr_name)
|
15
|
+
|
16
|
+
query_cast_attribute(attr_name, value)
|
17
|
+
end
|
18
|
+
|
19
|
+
def _query_attribute(attr_name) # :nodoc:
|
20
|
+
value = self._read_attribute(attr_name.to_s)
|
21
|
+
|
22
|
+
query_cast_attribute(attr_name, value)
|
23
|
+
end
|
24
|
+
|
25
|
+
alias :attribute? :query_attribute
|
26
|
+
private :attribute?
|
27
|
+
|
28
|
+
private
|
29
|
+
def query_cast_attribute(attr_name, value)
|
30
|
+
case value
|
31
|
+
when true then true
|
32
|
+
when false, nil then false
|
33
|
+
else
|
34
|
+
if !type_for_attribute(attr_name) { false }
|
35
|
+
if Numeric === value || !value.match?(/[^0-9]/)
|
36
|
+
!value.to_i.zero?
|
37
|
+
else
|
38
|
+
return false if ActiveModel::Type::Boolean::FALSE_VALUES.include?(value)
|
39
|
+
!value.blank?
|
40
|
+
end
|
41
|
+
elsif value.respond_to?(:zero?)
|
42
|
+
!value.zero?
|
43
|
+
else
|
44
|
+
!value.blank?
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module AttributeMethods
|
5
|
+
# = Active Record Attribute Methods \Read
|
6
|
+
module Read
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
module ClassMethods # :nodoc:
|
10
|
+
private
|
11
|
+
def define_method_attribute(canonical_name, owner:, as: canonical_name)
|
12
|
+
ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method(
|
13
|
+
owner, canonical_name
|
14
|
+
) do |temp_method_name, attr_name_expr|
|
15
|
+
owner.define_cached_method(temp_method_name, as: as, namespace: :active_record) do |batch|
|
16
|
+
batch <<
|
17
|
+
"def #{temp_method_name}" <<
|
18
|
+
" _read_attribute(#{attr_name_expr}) { |n| missing_attribute(n, caller) }" <<
|
19
|
+
"end"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns the value of the attribute identified by +attr_name+ after it
|
26
|
+
# has been type cast. For example, a date attribute will cast "2004-12-12"
|
27
|
+
# to <tt>Date.new(2004, 12, 12)</tt>. (For information about specific type
|
28
|
+
# casting behavior, see the types under ActiveModel::Type.)
|
29
|
+
def read_attribute(attr_name, &block)
|
30
|
+
name = attr_name.to_s
|
31
|
+
name = self.class.attribute_aliases[name] || name
|
32
|
+
|
33
|
+
@attributes.fetch_value(name, &block)
|
34
|
+
end
|
35
|
+
|
36
|
+
# This method exists to avoid the expensive primary_key check internally, without
|
37
|
+
# breaking compatibility with the read_attribute API
|
38
|
+
def _read_attribute(attr_name, &block) # :nodoc:
|
39
|
+
@attributes.fetch_value(attr_name, &block)
|
40
|
+
end
|
41
|
+
|
42
|
+
alias :attribute :_read_attribute
|
43
|
+
private :attribute
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,232 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module AttributeMethods
|
5
|
+
# = Active Record Attribute Methods \Serialization
|
6
|
+
module Serialization
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
class ColumnNotSerializableError < StandardError
|
10
|
+
def initialize(name, type)
|
11
|
+
super <<~EOS
|
12
|
+
Column `#{name}` of type #{type.class} does not support `serialize` feature.
|
13
|
+
Usually it means that you are trying to use `serialize`
|
14
|
+
on a column that already implements serialization natively.
|
15
|
+
EOS
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
included do
|
20
|
+
class_attribute :default_column_serializer, instance_accessor: false, default: Coders::YAMLColumn
|
21
|
+
end
|
22
|
+
|
23
|
+
module ClassMethods
|
24
|
+
# If you have an attribute that needs to be saved to the database as a
|
25
|
+
# serialized object, and retrieved by deserializing into the same object,
|
26
|
+
# then specify the name of that attribute using this method and serialization
|
27
|
+
# will be handled automatically.
|
28
|
+
#
|
29
|
+
# The serialization format may be YAML, JSON, or any custom format using a
|
30
|
+
# custom coder class.
|
31
|
+
#
|
32
|
+
# Keep in mind that database adapters handle certain serialization tasks
|
33
|
+
# for you. For instance: +json+ and +jsonb+ types in PostgreSQL will be
|
34
|
+
# converted between JSON object/array syntax and Ruby +Hash+ or +Array+
|
35
|
+
# objects transparently. There is no need to use #serialize in this
|
36
|
+
# case.
|
37
|
+
#
|
38
|
+
# For more complex cases, such as conversion to or from your application
|
39
|
+
# domain objects, consider using the ActiveRecord::Attributes API.
|
40
|
+
#
|
41
|
+
# ==== Parameters
|
42
|
+
#
|
43
|
+
# * +attr_name+ - The name of the attribute to serialize.
|
44
|
+
# * +coder+ The serializer implementation to use, e.g. +JSON+.
|
45
|
+
# * The attribute value will be serialized
|
46
|
+
# using the coder's <tt>dump(value)</tt> method, and will be
|
47
|
+
# deserialized using the coder's <tt>load(string)</tt> method. The
|
48
|
+
# +dump+ method may return +nil+ to serialize the value as +NULL+.
|
49
|
+
# * +type+ - Optional. What the type of the serialized object should be.
|
50
|
+
# * Attempting to serialize another type will raise an
|
51
|
+
# ActiveRecord::SerializationTypeMismatch error.
|
52
|
+
# * If the column is +NULL+ or starting from a new record, the default value
|
53
|
+
# will set to +type.new+
|
54
|
+
# * +yaml+ - Optional. Yaml specific options. The allowed config is:
|
55
|
+
# * +:permitted_classes+ - +Array+ with the permitted classes.
|
56
|
+
# * +:unsafe_load+ - Unsafely load YAML blobs, allow YAML to load any class.
|
57
|
+
#
|
58
|
+
# ==== Options
|
59
|
+
#
|
60
|
+
# * +:default+ - The default value to use when no value is provided. If
|
61
|
+
# this option is not passed, the previous default value (if any) will
|
62
|
+
# be used. Otherwise, the default will be +nil+.
|
63
|
+
#
|
64
|
+
# ==== Choosing a serializer
|
65
|
+
#
|
66
|
+
# While any serialization format can be used, it is recommended to carefully
|
67
|
+
# evaluate the properties of a serializer before using it, as migrating to
|
68
|
+
# another format later on can be difficult.
|
69
|
+
#
|
70
|
+
# ===== Avoid accepting arbitrary types
|
71
|
+
#
|
72
|
+
# When serializing data in a column, it is heavily recommended to make sure
|
73
|
+
# only expected types will be serialized. For instance some serializer like
|
74
|
+
# +Marshal+ or +YAML+ are capable of serializing almost any Ruby object.
|
75
|
+
#
|
76
|
+
# This can lead to unexpected types being serialized, and it is important
|
77
|
+
# that type serialization remains backward and forward compatible as long
|
78
|
+
# as some database records still contain these serialized types.
|
79
|
+
#
|
80
|
+
# class Address
|
81
|
+
# def initialize(line, city, country)
|
82
|
+
# @line, @city, @country = line, city, country
|
83
|
+
# end
|
84
|
+
# end
|
85
|
+
#
|
86
|
+
# In the above example, if any of the +Address+ attributes is renamed,
|
87
|
+
# instances that were persisted before the change will be loaded with the
|
88
|
+
# old attributes. This problem is even worse when the serialized type comes
|
89
|
+
# from a dependency which doesn't expect to be serialized this way and may
|
90
|
+
# change its internal representation without notice.
|
91
|
+
#
|
92
|
+
# As such, it is heavily recommended to instead convert these objects into
|
93
|
+
# primitives of the serialization format, for example:
|
94
|
+
#
|
95
|
+
# class Address
|
96
|
+
# attr_reader :line, :city, :country
|
97
|
+
#
|
98
|
+
# def self.load(payload)
|
99
|
+
# data = YAML.safe_load(payload)
|
100
|
+
# new(data["line"], data["city"], data["country"])
|
101
|
+
# end
|
102
|
+
#
|
103
|
+
# def self.dump(address)
|
104
|
+
# YAML.safe_dump(
|
105
|
+
# "line" => address.line,
|
106
|
+
# "city" => address.city,
|
107
|
+
# "country" => address.country,
|
108
|
+
# )
|
109
|
+
# end
|
110
|
+
#
|
111
|
+
# def initialize(line, city, country)
|
112
|
+
# @line, @city, @country = line, city, country
|
113
|
+
# end
|
114
|
+
# end
|
115
|
+
#
|
116
|
+
# class User < ActiveRecord::Base
|
117
|
+
# serialize :address, coder: Address
|
118
|
+
# end
|
119
|
+
#
|
120
|
+
# This pattern allows to be more deliberate about what is serialized, and
|
121
|
+
# to evolve the format in a backward compatible way.
|
122
|
+
#
|
123
|
+
# ===== Ensure serialization stability
|
124
|
+
#
|
125
|
+
# Some serialization methods may accept some types they don't support by
|
126
|
+
# silently casting them to other types. This can cause bugs when the
|
127
|
+
# data is deserialized.
|
128
|
+
#
|
129
|
+
# For instance the +JSON+ serializer provided in the standard library will
|
130
|
+
# silently cast unsupported types to +String+:
|
131
|
+
#
|
132
|
+
# >> JSON.parse(JSON.dump(Struct.new(:foo)))
|
133
|
+
# => "#<Class:0x000000013090b4c0>"
|
134
|
+
#
|
135
|
+
# ==== Examples
|
136
|
+
#
|
137
|
+
# ===== Serialize the +preferences+ attribute using YAML
|
138
|
+
#
|
139
|
+
# class User < ActiveRecord::Base
|
140
|
+
# serialize :preferences, coder: YAML
|
141
|
+
# end
|
142
|
+
#
|
143
|
+
# ===== Serialize the +preferences+ attribute using JSON
|
144
|
+
#
|
145
|
+
# class User < ActiveRecord::Base
|
146
|
+
# serialize :preferences, coder: JSON
|
147
|
+
# end
|
148
|
+
#
|
149
|
+
# ===== Serialize the +preferences+ +Hash+ using YAML
|
150
|
+
#
|
151
|
+
# class User < ActiveRecord::Base
|
152
|
+
# serialize :preferences, type: Hash, coder: YAML
|
153
|
+
# end
|
154
|
+
#
|
155
|
+
# ===== Serializes +preferences+ to YAML, permitting select classes
|
156
|
+
#
|
157
|
+
# class User < ActiveRecord::Base
|
158
|
+
# serialize :preferences, coder: YAML, yaml: { permitted_classes: [Symbol, Time] }
|
159
|
+
# end
|
160
|
+
#
|
161
|
+
# ===== Serialize the +preferences+ attribute using a custom coder
|
162
|
+
#
|
163
|
+
# class Rot13JSON
|
164
|
+
# def self.rot13(string)
|
165
|
+
# string.tr("a-zA-Z", "n-za-mN-ZA-M")
|
166
|
+
# end
|
167
|
+
#
|
168
|
+
# # Serializes an attribute value to a string that will be stored in the database.
|
169
|
+
# def self.dump(value)
|
170
|
+
# rot13(ActiveSupport::JSON.dump(value))
|
171
|
+
# end
|
172
|
+
#
|
173
|
+
# # Deserializes a string from the database to an attribute value.
|
174
|
+
# def self.load(string)
|
175
|
+
# ActiveSupport::JSON.load(rot13(string))
|
176
|
+
# end
|
177
|
+
# end
|
178
|
+
#
|
179
|
+
# class User < ActiveRecord::Base
|
180
|
+
# serialize :preferences, coder: Rot13JSON
|
181
|
+
# end
|
182
|
+
#
|
183
|
+
def serialize(attr_name, coder: nil, type: Object, yaml: {}, **options)
|
184
|
+
coder ||= default_column_serializer
|
185
|
+
unless coder
|
186
|
+
raise ArgumentError, <<~MSG.squish
|
187
|
+
missing keyword: :coder
|
188
|
+
|
189
|
+
If no default coder is configured, a coder must be provided to `serialize`.
|
190
|
+
MSG
|
191
|
+
end
|
192
|
+
|
193
|
+
column_serializer = build_column_serializer(attr_name, coder, type, yaml)
|
194
|
+
|
195
|
+
attribute(attr_name, **options)
|
196
|
+
|
197
|
+
decorate_attributes([attr_name]) do |attr_name, cast_type|
|
198
|
+
if type_incompatible_with_serialize?(cast_type, coder, type)
|
199
|
+
raise ColumnNotSerializableError.new(attr_name, cast_type)
|
200
|
+
end
|
201
|
+
|
202
|
+
cast_type = cast_type.subtype if Type::Serialized === cast_type
|
203
|
+
Type::Serialized.new(cast_type, column_serializer)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
private
|
208
|
+
def build_column_serializer(attr_name, coder, type, yaml = nil)
|
209
|
+
# When ::JSON is used, force it to go through the Active Support JSON encoder
|
210
|
+
# to ensure special objects (e.g. Active Record models) are dumped correctly
|
211
|
+
# using the #as_json hook.
|
212
|
+
coder = Coders::JSON if coder == ::JSON
|
213
|
+
|
214
|
+
if coder == ::YAML || coder == Coders::YAMLColumn
|
215
|
+
Coders::YAMLColumn.new(attr_name, type, **(yaml || {}))
|
216
|
+
elsif coder.respond_to?(:new) && !coder.respond_to?(:load)
|
217
|
+
coder.new(attr_name, type)
|
218
|
+
elsif type && type != Object
|
219
|
+
Coders::ColumnSerializer.new(attr_name, coder, type)
|
220
|
+
else
|
221
|
+
coder
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
def type_incompatible_with_serialize?(cast_type, coder, type)
|
226
|
+
cast_type.is_a?(ActiveRecord::Type::Json) && coder == ::JSON ||
|
227
|
+
cast_type.respond_to?(:type_cast_array, true) && type == ::Array
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/object/try"
|
4
|
+
|
5
|
+
module ActiveRecord
|
6
|
+
module AttributeMethods
|
7
|
+
module TimeZoneConversion
|
8
|
+
class TimeZoneConverter < DelegateClass(Type::Value) # :nodoc:
|
9
|
+
def self.new(subtype)
|
10
|
+
self === subtype ? subtype : super
|
11
|
+
end
|
12
|
+
|
13
|
+
def deserialize(value)
|
14
|
+
convert_time_to_time_zone(super)
|
15
|
+
end
|
16
|
+
|
17
|
+
def cast(value)
|
18
|
+
return if value.nil?
|
19
|
+
|
20
|
+
if value.is_a?(Hash)
|
21
|
+
set_time_zone_without_conversion(super)
|
22
|
+
elsif value.respond_to?(:in_time_zone)
|
23
|
+
begin
|
24
|
+
super(user_input_in_time_zone(value)) || super
|
25
|
+
rescue ArgumentError
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
elsif value.respond_to?(:infinite?) && value.infinite?
|
29
|
+
value
|
30
|
+
else
|
31
|
+
map_avoiding_infinite_recursion(super) { |v| cast(v) }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def ==(other)
|
36
|
+
other.is_a?(self.class) && __getobj__ == other.__getobj__
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
def convert_time_to_time_zone(value)
|
41
|
+
return if value.nil?
|
42
|
+
|
43
|
+
if value.acts_like?(:time)
|
44
|
+
value.in_time_zone
|
45
|
+
elsif value.respond_to?(:infinite?) && value.infinite?
|
46
|
+
value
|
47
|
+
else
|
48
|
+
map_avoiding_infinite_recursion(value) { |v| convert_time_to_time_zone(v) }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def set_time_zone_without_conversion(value)
|
53
|
+
::Time.zone.local_to_utc(value).try(:in_time_zone) if value
|
54
|
+
end
|
55
|
+
|
56
|
+
def map_avoiding_infinite_recursion(value)
|
57
|
+
map(value) do |v|
|
58
|
+
if value.equal?(v)
|
59
|
+
nil
|
60
|
+
else
|
61
|
+
yield(v)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
extend ActiveSupport::Concern
|
68
|
+
|
69
|
+
included do
|
70
|
+
class_attribute :time_zone_aware_attributes, instance_writer: false, default: false
|
71
|
+
class_attribute :skip_time_zone_conversion_for_attributes, instance_writer: false, default: []
|
72
|
+
class_attribute :time_zone_aware_types, instance_writer: false, default: [ :datetime, :time ]
|
73
|
+
end
|
74
|
+
|
75
|
+
module ClassMethods # :nodoc:
|
76
|
+
private
|
77
|
+
def hook_attribute_type(name, cast_type)
|
78
|
+
if create_time_zone_conversion_attribute?(name, cast_type)
|
79
|
+
cast_type = TimeZoneConverter.new(cast_type)
|
80
|
+
end
|
81
|
+
|
82
|
+
super
|
83
|
+
end
|
84
|
+
|
85
|
+
def create_time_zone_conversion_attribute?(name, cast_type)
|
86
|
+
enabled_for_column = time_zone_aware_attributes &&
|
87
|
+
!skip_time_zone_conversion_for_attributes.include?(name.to_sym)
|
88
|
+
|
89
|
+
enabled_for_column && time_zone_aware_types.include?(cast_type.type)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module AttributeMethods
|
5
|
+
# = Active Record Attribute Methods \Write
|
6
|
+
module Write
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
attribute_method_suffix "=", parameters: "value"
|
11
|
+
end
|
12
|
+
|
13
|
+
module ClassMethods # :nodoc:
|
14
|
+
private
|
15
|
+
def define_method_attribute=(canonical_name, owner:, as: canonical_name)
|
16
|
+
ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method(
|
17
|
+
owner, canonical_name, writer: true,
|
18
|
+
) do |temp_method_name, attr_name_expr|
|
19
|
+
owner.define_cached_method(temp_method_name, as: "#{as}=", namespace: :active_record) do |batch|
|
20
|
+
batch <<
|
21
|
+
"def #{temp_method_name}(value)" <<
|
22
|
+
" _write_attribute(#{attr_name_expr}, value)" <<
|
23
|
+
"end"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Updates the attribute identified by +attr_name+ using the specified
|
30
|
+
# +value+. The attribute value will be type cast upon being read.
|
31
|
+
def write_attribute(attr_name, value)
|
32
|
+
name = attr_name.to_s
|
33
|
+
name = self.class.attribute_aliases[name] || name
|
34
|
+
|
35
|
+
name = @primary_key if name == "id" && @primary_key
|
36
|
+
@attributes.write_from_user(name, value)
|
37
|
+
end
|
38
|
+
|
39
|
+
# This method exists to avoid the expensive primary_key check internally, without
|
40
|
+
# breaking compatibility with the write_attribute API
|
41
|
+
def _write_attribute(attr_name, value) # :nodoc:
|
42
|
+
@attributes.write_from_user(attr_name, value)
|
43
|
+
end
|
44
|
+
|
45
|
+
alias :attribute= :_write_attribute
|
46
|
+
private :attribute=
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|