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,164 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
# Statement cache is used to cache a single statement in order to avoid creating the AST again.
|
5
|
+
# Initializing the cache is done by passing the statement in the create block:
|
6
|
+
#
|
7
|
+
# cache = StatementCache.create(ClothingItem.lease_connection) do |params|
|
8
|
+
# Book.where(name: "my book").where("author_id > 3")
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# The cached statement is executed by using the
|
12
|
+
# {connection.execute}[rdoc-ref:ConnectionAdapters::DatabaseStatements#execute] method:
|
13
|
+
#
|
14
|
+
# cache.execute([], ClothingItem.lease_connection)
|
15
|
+
#
|
16
|
+
# The relation returned by the block is cached, and for each
|
17
|
+
# {execute}[rdoc-ref:ConnectionAdapters::DatabaseStatements#execute]
|
18
|
+
# call the cached relation gets duped. Database is queried when +to_a+ is called on the relation.
|
19
|
+
#
|
20
|
+
# If you want to cache the statement without the values you can use the +bind+ method of the
|
21
|
+
# block parameter.
|
22
|
+
#
|
23
|
+
# cache = StatementCache.create(ClothingItem.lease_connection) do |params|
|
24
|
+
# Book.where(name: params.bind)
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# And pass the bind values as the first argument of +execute+ call.
|
28
|
+
#
|
29
|
+
# cache.execute(["my book"], ClothingItem.lease_connection)
|
30
|
+
class StatementCache # :nodoc:
|
31
|
+
class Substitute; end # :nodoc:
|
32
|
+
|
33
|
+
class Query # :nodoc:
|
34
|
+
def initialize(sql)
|
35
|
+
@sql = sql
|
36
|
+
end
|
37
|
+
|
38
|
+
def sql_for(binds, connection)
|
39
|
+
@sql
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class PartialQuery < Query # :nodoc:
|
44
|
+
def initialize(values)
|
45
|
+
@values = values
|
46
|
+
@indexes = values.each_with_index.find_all { |thing, i|
|
47
|
+
Substitute === thing
|
48
|
+
}.map(&:last)
|
49
|
+
end
|
50
|
+
|
51
|
+
def sql_for(binds, connection)
|
52
|
+
val = @values.dup
|
53
|
+
@indexes.each do |i|
|
54
|
+
value = binds.shift
|
55
|
+
if ActiveModel::Attribute === value
|
56
|
+
value = value.value_for_database
|
57
|
+
end
|
58
|
+
val[i] = connection.quote(value)
|
59
|
+
end
|
60
|
+
val.join
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
class PartialQueryCollector
|
65
|
+
attr_accessor :preparable, :retryable
|
66
|
+
|
67
|
+
def initialize
|
68
|
+
@parts = []
|
69
|
+
@binds = []
|
70
|
+
end
|
71
|
+
|
72
|
+
def <<(str)
|
73
|
+
@parts << str
|
74
|
+
self
|
75
|
+
end
|
76
|
+
|
77
|
+
def add_bind(obj)
|
78
|
+
@binds << obj
|
79
|
+
@parts << Substitute.new
|
80
|
+
self
|
81
|
+
end
|
82
|
+
|
83
|
+
def add_binds(binds, proc_for_binds = nil)
|
84
|
+
@binds.concat proc_for_binds ? binds.map(&proc_for_binds) : binds
|
85
|
+
binds.size.times do |i|
|
86
|
+
@parts << ", " unless i == 0
|
87
|
+
@parts << Substitute.new
|
88
|
+
end
|
89
|
+
self
|
90
|
+
end
|
91
|
+
|
92
|
+
def value
|
93
|
+
[@parts, @binds]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.query(sql)
|
98
|
+
Query.new(sql)
|
99
|
+
end
|
100
|
+
|
101
|
+
def self.partial_query(values)
|
102
|
+
PartialQuery.new(values)
|
103
|
+
end
|
104
|
+
|
105
|
+
def self.partial_query_collector
|
106
|
+
PartialQueryCollector.new
|
107
|
+
end
|
108
|
+
|
109
|
+
class Params # :nodoc:
|
110
|
+
def bind; Substitute.new; end
|
111
|
+
end
|
112
|
+
|
113
|
+
class BindMap # :nodoc:
|
114
|
+
def initialize(bound_attributes)
|
115
|
+
@indexes = []
|
116
|
+
@bound_attributes = bound_attributes
|
117
|
+
|
118
|
+
bound_attributes.each_with_index do |attr, i|
|
119
|
+
if ActiveModel::Attribute === attr && Substitute === attr.value
|
120
|
+
@indexes << i
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def bind(values)
|
126
|
+
bas = @bound_attributes.dup
|
127
|
+
@indexes.each_with_index { |offset, i| bas[offset] = bas[offset].with_cast_value(values[i]) }
|
128
|
+
bas
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def self.create(connection, callable = nil, &block)
|
133
|
+
relation = (callable || block).call Params.new
|
134
|
+
query_builder, binds = connection.cacheable_query(self, relation.arel)
|
135
|
+
bind_map = BindMap.new(binds)
|
136
|
+
new(query_builder, bind_map, relation.model)
|
137
|
+
end
|
138
|
+
|
139
|
+
def initialize(query_builder, bind_map, model)
|
140
|
+
@query_builder = query_builder
|
141
|
+
@bind_map = bind_map
|
142
|
+
@model = model
|
143
|
+
end
|
144
|
+
|
145
|
+
def execute(params, connection, allow_retry: false, async: false, &block)
|
146
|
+
bind_values = @bind_map.bind params
|
147
|
+
sql = @query_builder.sql_for bind_values, connection
|
148
|
+
|
149
|
+
if async
|
150
|
+
@model.async_find_by_sql(sql, bind_values, preparable: true, allow_retry: allow_retry, &block)
|
151
|
+
else
|
152
|
+
@model.find_by_sql(sql, bind_values, preparable: true, allow_retry: allow_retry, &block)
|
153
|
+
end
|
154
|
+
rescue ::RangeError
|
155
|
+
async ? Promise.wrap([]) : []
|
156
|
+
end
|
157
|
+
|
158
|
+
def self.unsupported_value?(value)
|
159
|
+
case value
|
160
|
+
when NilClass, Array, Range, Hash, Relation, Base then true
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
@@ -0,0 +1,299 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/hash/indifferent_access"
|
4
|
+
|
5
|
+
module ActiveRecord
|
6
|
+
# = Active Record \Store
|
7
|
+
#
|
8
|
+
# Store gives you a thin wrapper around serialize for the purpose of storing hashes in a single column.
|
9
|
+
# It's like a simple key/value store baked into your record when you don't care about being able to
|
10
|
+
# query that store outside the context of a single record.
|
11
|
+
#
|
12
|
+
# You can then declare accessors to this store that are then accessible just like any other attribute
|
13
|
+
# of the model. This is very helpful for easily exposing store keys to a form or elsewhere that's
|
14
|
+
# already built around just accessing attributes on the model.
|
15
|
+
#
|
16
|
+
# Every accessor comes with dirty tracking methods (+key_changed?+, +key_was+ and +key_change+) and
|
17
|
+
# methods to access the changes made during the last save (+saved_change_to_key?+, +saved_change_to_key+ and
|
18
|
+
# +key_before_last_save+).
|
19
|
+
#
|
20
|
+
# NOTE: There is no +key_will_change!+ method for accessors, use +store_will_change!+ instead.
|
21
|
+
#
|
22
|
+
# Make sure that you declare the database column used for the serialized store as a text, so there's
|
23
|
+
# plenty of room.
|
24
|
+
#
|
25
|
+
# You can set custom coder to encode/decode your serialized attributes to/from different formats.
|
26
|
+
# JSON, YAML, Marshal are supported out of the box. Generally it can be any wrapper that provides +load+ and +dump+.
|
27
|
+
#
|
28
|
+
# NOTE: If you are using structured database data types (e.g. PostgreSQL +hstore+/+json+, MySQL 5.7+
|
29
|
+
# +json+, or SQLite 3.38+ +json+) there is no need for the serialization provided by {.store}[rdoc-ref:rdoc-ref:ClassMethods#store].
|
30
|
+
# Simply use {.store_accessor}[rdoc-ref:ClassMethods#store_accessor] instead to generate
|
31
|
+
# the accessor methods. Be aware that these columns use a string keyed hash and do not allow access
|
32
|
+
# using a symbol.
|
33
|
+
#
|
34
|
+
# NOTE: The default validations with the exception of +uniqueness+ will work.
|
35
|
+
# For example, if you want to check for +uniqueness+ with +hstore+ you will
|
36
|
+
# need to use a custom validation to handle it.
|
37
|
+
#
|
38
|
+
# Examples:
|
39
|
+
#
|
40
|
+
# class User < ActiveRecord::Base
|
41
|
+
# store :settings, accessors: [ :color, :homepage ], coder: JSON
|
42
|
+
# store :parent, accessors: [ :name ], coder: JSON, prefix: true
|
43
|
+
# store :spouse, accessors: [ :name ], coder: JSON, prefix: :partner
|
44
|
+
# store :settings, accessors: [ :two_factor_auth ], suffix: true
|
45
|
+
# store :settings, accessors: [ :login_retry ], suffix: :config
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
# u = User.new(color: 'black', homepage: '37signals.com', parent_name: 'Mary', partner_name: 'Lily')
|
49
|
+
# u.color # Accessor stored attribute
|
50
|
+
# u.parent_name # Accessor stored attribute with prefix
|
51
|
+
# u.partner_name # Accessor stored attribute with custom prefix
|
52
|
+
# u.two_factor_auth_settings # Accessor stored attribute with suffix
|
53
|
+
# u.login_retry_config # Accessor stored attribute with custom suffix
|
54
|
+
# u.settings[:country] = 'Denmark' # Any attribute, even if not specified with an accessor
|
55
|
+
#
|
56
|
+
# # There is no difference between strings and symbols for accessing custom attributes
|
57
|
+
# u.settings[:country] # => 'Denmark'
|
58
|
+
# u.settings['country'] # => 'Denmark'
|
59
|
+
#
|
60
|
+
# # Dirty tracking
|
61
|
+
# u.color = 'green'
|
62
|
+
# u.color_changed? # => true
|
63
|
+
# u.color_was # => 'black'
|
64
|
+
# u.color_change # => ['black', 'green']
|
65
|
+
#
|
66
|
+
# # Add additional accessors to an existing store through store_accessor
|
67
|
+
# class SuperUser < User
|
68
|
+
# store_accessor :settings, :privileges, :servants
|
69
|
+
# store_accessor :parent, :birthday, prefix: true
|
70
|
+
# store_accessor :settings, :secret_question, suffix: :config
|
71
|
+
# end
|
72
|
+
#
|
73
|
+
# The stored attribute names can be retrieved using {.stored_attributes}[rdoc-ref:rdoc-ref:ClassMethods#stored_attributes].
|
74
|
+
#
|
75
|
+
# User.stored_attributes[:settings] # => [:color, :homepage, :two_factor_auth, :login_retry]
|
76
|
+
#
|
77
|
+
# == Overwriting default accessors
|
78
|
+
#
|
79
|
+
# All stored values are automatically available through accessors on the Active Record
|
80
|
+
# object, but sometimes you want to specialize this behavior. This can be done by overwriting
|
81
|
+
# the default accessors (using the same name as the attribute) and calling <tt>super</tt>
|
82
|
+
# to actually change things.
|
83
|
+
#
|
84
|
+
# class Song < ActiveRecord::Base
|
85
|
+
# # Uses a stored integer to hold the volume adjustment of the song
|
86
|
+
# store :settings, accessors: [:volume_adjustment]
|
87
|
+
#
|
88
|
+
# def volume_adjustment=(decibels)
|
89
|
+
# super(decibels.to_i)
|
90
|
+
# end
|
91
|
+
#
|
92
|
+
# def volume_adjustment
|
93
|
+
# super.to_i
|
94
|
+
# end
|
95
|
+
# end
|
96
|
+
module Store
|
97
|
+
extend ActiveSupport::Concern
|
98
|
+
|
99
|
+
included do
|
100
|
+
class << self
|
101
|
+
attr_accessor :local_stored_attributes
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
module ClassMethods
|
106
|
+
def store(store_attribute, options = {})
|
107
|
+
coder = build_column_serializer(store_attribute, options[:coder], Object, options[:yaml])
|
108
|
+
serialize store_attribute, coder: IndifferentCoder.new(store_attribute, coder)
|
109
|
+
store_accessor(store_attribute, options[:accessors], **options.slice(:prefix, :suffix)) if options.has_key? :accessors
|
110
|
+
end
|
111
|
+
|
112
|
+
def store_accessor(store_attribute, *keys, prefix: nil, suffix: nil)
|
113
|
+
keys = keys.flatten
|
114
|
+
|
115
|
+
accessor_prefix =
|
116
|
+
case prefix
|
117
|
+
when String, Symbol
|
118
|
+
"#{prefix}_"
|
119
|
+
when TrueClass
|
120
|
+
"#{store_attribute}_"
|
121
|
+
else
|
122
|
+
""
|
123
|
+
end
|
124
|
+
accessor_suffix =
|
125
|
+
case suffix
|
126
|
+
when String, Symbol
|
127
|
+
"_#{suffix}"
|
128
|
+
when TrueClass
|
129
|
+
"_#{store_attribute}"
|
130
|
+
else
|
131
|
+
""
|
132
|
+
end
|
133
|
+
|
134
|
+
_store_accessors_module.module_eval do
|
135
|
+
keys.each do |key|
|
136
|
+
accessor_key = "#{accessor_prefix}#{key}#{accessor_suffix}"
|
137
|
+
|
138
|
+
define_method("#{accessor_key}=") do |value|
|
139
|
+
write_store_attribute(store_attribute, key, value)
|
140
|
+
end
|
141
|
+
|
142
|
+
define_method(accessor_key) do
|
143
|
+
read_store_attribute(store_attribute, key)
|
144
|
+
end
|
145
|
+
|
146
|
+
define_method("#{accessor_key}_changed?") do
|
147
|
+
return false unless attribute_changed?(store_attribute)
|
148
|
+
prev_store, new_store = changes[store_attribute]
|
149
|
+
prev_store&.dig(key) != new_store&.dig(key)
|
150
|
+
end
|
151
|
+
|
152
|
+
define_method("#{accessor_key}_change") do
|
153
|
+
return unless attribute_changed?(store_attribute)
|
154
|
+
prev_store, new_store = changes[store_attribute]
|
155
|
+
[prev_store&.dig(key), new_store&.dig(key)]
|
156
|
+
end
|
157
|
+
|
158
|
+
define_method("#{accessor_key}_was") do
|
159
|
+
return unless attribute_changed?(store_attribute)
|
160
|
+
prev_store, _new_store = changes[store_attribute]
|
161
|
+
prev_store&.dig(key)
|
162
|
+
end
|
163
|
+
|
164
|
+
define_method("saved_change_to_#{accessor_key}?") do
|
165
|
+
return false unless saved_change_to_attribute?(store_attribute)
|
166
|
+
prev_store, new_store = saved_changes[store_attribute]
|
167
|
+
prev_store&.dig(key) != new_store&.dig(key)
|
168
|
+
end
|
169
|
+
|
170
|
+
define_method("saved_change_to_#{accessor_key}") do
|
171
|
+
return unless saved_change_to_attribute?(store_attribute)
|
172
|
+
prev_store, new_store = saved_changes[store_attribute]
|
173
|
+
[prev_store&.dig(key), new_store&.dig(key)]
|
174
|
+
end
|
175
|
+
|
176
|
+
define_method("#{accessor_key}_before_last_save") do
|
177
|
+
return unless saved_change_to_attribute?(store_attribute)
|
178
|
+
prev_store, _new_store = saved_changes[store_attribute]
|
179
|
+
prev_store&.dig(key)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
# assign new store attribute and create new hash to ensure that each class in the hierarchy
|
185
|
+
# has its own hash of stored attributes.
|
186
|
+
self.local_stored_attributes ||= {}
|
187
|
+
self.local_stored_attributes[store_attribute] ||= []
|
188
|
+
self.local_stored_attributes[store_attribute] |= keys
|
189
|
+
end
|
190
|
+
|
191
|
+
def _store_accessors_module # :nodoc:
|
192
|
+
@_store_accessors_module ||= begin
|
193
|
+
mod = Module.new
|
194
|
+
include mod
|
195
|
+
mod
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def stored_attributes
|
200
|
+
parent = superclass.respond_to?(:stored_attributes) ? superclass.stored_attributes : {}
|
201
|
+
if local_stored_attributes
|
202
|
+
parent.merge!(local_stored_attributes) { |k, a, b| a | b }
|
203
|
+
end
|
204
|
+
parent
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
private
|
209
|
+
def read_store_attribute(store_attribute, key) # :doc:
|
210
|
+
accessor = store_accessor_for(store_attribute)
|
211
|
+
accessor.read(self, store_attribute, key)
|
212
|
+
end
|
213
|
+
|
214
|
+
def write_store_attribute(store_attribute, key, value) # :doc:
|
215
|
+
accessor = store_accessor_for(store_attribute)
|
216
|
+
accessor.write(self, store_attribute, key, value)
|
217
|
+
end
|
218
|
+
|
219
|
+
def store_accessor_for(store_attribute)
|
220
|
+
type_for_attribute(store_attribute).tap do |type|
|
221
|
+
unless type.respond_to?(:accessor)
|
222
|
+
raise ConfigurationError, "the column '#{store_attribute}' has not been configured as a store. Please make sure the column is declared serializable via 'ActiveRecord.store' or, if your database supports it, use a structured column type like hstore or json."
|
223
|
+
end
|
224
|
+
end.accessor
|
225
|
+
end
|
226
|
+
|
227
|
+
class HashAccessor # :nodoc:
|
228
|
+
def self.read(object, attribute, key)
|
229
|
+
prepare(object, attribute)
|
230
|
+
object.public_send(attribute)[key]
|
231
|
+
end
|
232
|
+
|
233
|
+
def self.write(object, attribute, key, value)
|
234
|
+
prepare(object, attribute)
|
235
|
+
object.public_send(attribute)[key] = value if value != read(object, attribute, key)
|
236
|
+
end
|
237
|
+
|
238
|
+
def self.prepare(object, attribute)
|
239
|
+
object.public_send :"#{attribute}=", {} unless object.send(attribute)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
class StringKeyedHashAccessor < HashAccessor # :nodoc:
|
244
|
+
def self.read(object, attribute, key)
|
245
|
+
super object, attribute, key.to_s
|
246
|
+
end
|
247
|
+
|
248
|
+
def self.write(object, attribute, key, value)
|
249
|
+
super object, attribute, key.to_s, value
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
class IndifferentHashAccessor < ActiveRecord::Store::HashAccessor # :nodoc:
|
254
|
+
def self.prepare(object, store_attribute)
|
255
|
+
attribute = object.send(store_attribute)
|
256
|
+
unless attribute.is_a?(ActiveSupport::HashWithIndifferentAccess)
|
257
|
+
attribute = IndifferentCoder.as_indifferent_hash(attribute)
|
258
|
+
object.public_send :"#{store_attribute}=", attribute
|
259
|
+
end
|
260
|
+
attribute
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
class IndifferentCoder # :nodoc:
|
265
|
+
def initialize(attr_name, coder_or_class_name)
|
266
|
+
@coder =
|
267
|
+
if coder_or_class_name.respond_to?(:load) && coder_or_class_name.respond_to?(:dump)
|
268
|
+
coder_or_class_name
|
269
|
+
else
|
270
|
+
ActiveRecord::Coders::YAMLColumn.new(attr_name, coder_or_class_name || Object)
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
def dump(obj)
|
275
|
+
@coder.dump as_regular_hash(obj)
|
276
|
+
end
|
277
|
+
|
278
|
+
def load(yaml)
|
279
|
+
self.class.as_indifferent_hash(@coder.load(yaml || ""))
|
280
|
+
end
|
281
|
+
|
282
|
+
def self.as_indifferent_hash(obj)
|
283
|
+
case obj
|
284
|
+
when ActiveSupport::HashWithIndifferentAccess
|
285
|
+
obj
|
286
|
+
when Hash
|
287
|
+
obj.with_indifferent_access
|
288
|
+
else
|
289
|
+
ActiveSupport::HashWithIndifferentAccess.new
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
private
|
294
|
+
def as_regular_hash(obj)
|
295
|
+
obj.respond_to?(:to_hash) ? obj.to_hash : {}
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
# = Active Record \Suppressor
|
5
|
+
#
|
6
|
+
# ActiveRecord::Suppressor prevents the receiver from being saved during
|
7
|
+
# a given block.
|
8
|
+
#
|
9
|
+
# For example, here's a pattern of creating notifications when new comments
|
10
|
+
# are posted. (The notification may in turn trigger an email, a push
|
11
|
+
# notification, or just appear in the UI somewhere):
|
12
|
+
#
|
13
|
+
# class Comment < ActiveRecord::Base
|
14
|
+
# belongs_to :commentable, polymorphic: true
|
15
|
+
# after_create -> { Notification.create! comment: self,
|
16
|
+
# recipients: commentable.recipients }
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# That's what you want the bulk of the time. New comment creates a new
|
20
|
+
# Notification. But there may well be off cases, like copying a commentable
|
21
|
+
# and its comments, where you don't want that. So you'd have a concern
|
22
|
+
# something like this:
|
23
|
+
#
|
24
|
+
# module Copyable
|
25
|
+
# def copy_to(destination)
|
26
|
+
# Notification.suppress do
|
27
|
+
# # Copy logic that creates new comments that we do not want
|
28
|
+
# # triggering notifications.
|
29
|
+
# end
|
30
|
+
# end
|
31
|
+
# end
|
32
|
+
module Suppressor
|
33
|
+
extend ActiveSupport::Concern
|
34
|
+
|
35
|
+
class << self
|
36
|
+
def registry # :nodoc:
|
37
|
+
ActiveSupport::IsolatedExecutionState[:active_record_suppressor_registry] ||= {}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
module ClassMethods
|
42
|
+
def suppress(&block)
|
43
|
+
previous_state = Suppressor.registry[name]
|
44
|
+
Suppressor.registry[name] = true
|
45
|
+
yield
|
46
|
+
ensure
|
47
|
+
Suppressor.registry[name] = previous_state
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def save(**) # :nodoc:
|
52
|
+
Suppressor.registry[self.class.name] ? true : super
|
53
|
+
end
|
54
|
+
|
55
|
+
def save!(**) # :nodoc:
|
56
|
+
Suppressor.registry[self.class.name] ? true : super
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
class TableMetadata # :nodoc:
|
5
|
+
delegate :join_primary_key, :join_primary_type, :join_foreign_key, :join_foreign_type, to: :reflection
|
6
|
+
|
7
|
+
def initialize(klass, arel_table, reflection = nil)
|
8
|
+
@klass = klass
|
9
|
+
@arel_table = arel_table
|
10
|
+
@reflection = reflection
|
11
|
+
end
|
12
|
+
|
13
|
+
def primary_key
|
14
|
+
klass&.primary_key
|
15
|
+
end
|
16
|
+
|
17
|
+
def type(column_name)
|
18
|
+
arel_table.type_for_attribute(column_name)
|
19
|
+
end
|
20
|
+
|
21
|
+
def has_column?(column_name)
|
22
|
+
klass&.columns_hash&.key?(column_name)
|
23
|
+
end
|
24
|
+
|
25
|
+
def associated_with?(table_name)
|
26
|
+
klass&._reflect_on_association(table_name)
|
27
|
+
end
|
28
|
+
|
29
|
+
def associated_table(table_name)
|
30
|
+
reflection = klass._reflect_on_association(table_name) || klass._reflect_on_association(table_name.singularize)
|
31
|
+
|
32
|
+
if !reflection && table_name == arel_table.name
|
33
|
+
return self
|
34
|
+
end
|
35
|
+
|
36
|
+
if reflection
|
37
|
+
association_klass = reflection.klass unless reflection.polymorphic?
|
38
|
+
elsif block_given?
|
39
|
+
association_klass = yield table_name
|
40
|
+
end
|
41
|
+
|
42
|
+
if association_klass
|
43
|
+
arel_table = association_klass.arel_table
|
44
|
+
arel_table = arel_table.alias(table_name) if arel_table.name != table_name
|
45
|
+
TableMetadata.new(association_klass, arel_table, reflection)
|
46
|
+
else
|
47
|
+
type_caster = TypeCaster::Connection.new(klass, table_name)
|
48
|
+
arel_table = Arel::Table.new(table_name, type_caster: type_caster)
|
49
|
+
TableMetadata.new(nil, arel_table, reflection)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def polymorphic_association?
|
54
|
+
reflection&.polymorphic?
|
55
|
+
end
|
56
|
+
|
57
|
+
def polymorphic_name_association
|
58
|
+
reflection&.polymorphic_name
|
59
|
+
end
|
60
|
+
|
61
|
+
def through_association?
|
62
|
+
reflection&.through_reflection?
|
63
|
+
end
|
64
|
+
|
65
|
+
def reflect_on_aggregation(aggregation_name)
|
66
|
+
klass&.reflect_on_aggregation(aggregation_name)
|
67
|
+
end
|
68
|
+
alias :aggregated_with? :reflect_on_aggregation
|
69
|
+
|
70
|
+
def predicate_builder
|
71
|
+
if klass
|
72
|
+
predicate_builder = klass.predicate_builder.dup
|
73
|
+
predicate_builder.instance_variable_set(:@table, self)
|
74
|
+
predicate_builder
|
75
|
+
else
|
76
|
+
PredicateBuilder.new(self)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
attr_reader :arel_table
|
81
|
+
|
82
|
+
private
|
83
|
+
attr_reader :klass, :reflection
|
84
|
+
end
|
85
|
+
end
|