activerecord 6.1.7 → 7.2.0
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 +4 -4
- data/CHANGELOG.md +520 -1385
- data/MIT-LICENSE +1 -1
- data/README.rdoc +31 -31
- data/examples/performance.rb +2 -2
- data/lib/active_record/aggregations.rb +17 -14
- data/lib/active_record/association_relation.rb +2 -12
- data/lib/active_record/associations/alias_tracker.rb +25 -19
- data/lib/active_record/associations/association.rb +60 -21
- data/lib/active_record/associations/association_scope.rb +17 -12
- data/lib/active_record/associations/belongs_to_association.rb +37 -11
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -4
- data/lib/active_record/associations/builder/association.rb +11 -5
- data/lib/active_record/associations/builder/belongs_to.rb +41 -14
- data/lib/active_record/associations/builder/collection_association.rb +10 -3
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -7
- data/lib/active_record/associations/builder/has_many.rb +4 -4
- data/lib/active_record/associations/builder/has_one.rb +4 -4
- data/lib/active_record/associations/builder/singular_association.rb +6 -2
- data/lib/active_record/associations/collection_association.rb +46 -36
- data/lib/active_record/associations/collection_proxy.rb +44 -16
- 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 +10 -3
- data/lib/active_record/associations/has_many_association.rb +29 -19
- data/lib/active_record/associations/has_many_through_association.rb +12 -7
- data/lib/active_record/associations/has_one_association.rb +20 -10
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +27 -25
- data/lib/active_record/associations/join_dependency.rb +23 -15
- data/lib/active_record/associations/nested_error.rb +47 -0
- data/lib/active_record/associations/preloader/association.rb +212 -53
- 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 +50 -16
- data/lib/active_record/associations/preloader.rb +50 -121
- data/lib/active_record/associations/singular_association.rb +15 -3
- data/lib/active_record/associations/through_association.rb +25 -14
- data/lib/active_record/associations.rb +404 -509
- data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
- data/lib/active_record/attribute_assignment.rb +2 -14
- data/lib/active_record/attribute_methods/before_type_cast.rb +24 -2
- data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
- data/lib/active_record/attribute_methods/dirty.rb +73 -22
- data/lib/active_record/attribute_methods/primary_key.rb +47 -27
- data/lib/active_record/attribute_methods/query.rb +31 -19
- data/lib/active_record/attribute_methods/read.rb +14 -11
- data/lib/active_record/attribute_methods/serialization.rb +174 -37
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +11 -9
- data/lib/active_record/attribute_methods/write.rb +12 -15
- data/lib/active_record/attribute_methods.rb +164 -52
- data/lib/active_record/attributes.rb +51 -49
- data/lib/active_record/autosave_association.rb +74 -57
- data/lib/active_record/base.rb +27 -5
- data/lib/active_record/callbacks.rb +18 -34
- data/lib/active_record/coders/column_serializer.rb +61 -0
- data/lib/active_record/coders/json.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +70 -46
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +284 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +211 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +79 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +327 -612
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -17
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +199 -60
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +201 -64
- data/lib/active_record/connection_adapters/abstract/quoting.rb +119 -131
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +21 -20
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +186 -31
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +377 -142
- data/lib/active_record/connection_adapters/abstract/transaction.rb +361 -76
- data/lib/active_record/connection_adapters/abstract_adapter.rb +624 -163
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +345 -166
- data/lib/active_record/connection_adapters/column.rb +13 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +29 -130
- data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -55
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +10 -1
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +8 -2
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +45 -14
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +152 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +107 -68
- data/lib/active_record/connection_adapters/pool_config.rb +26 -16
- data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/column.rb +30 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +114 -54
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +8 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +5 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -14
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -2
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +12 -3
- 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 +18 -6
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +137 -104
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +28 -0
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +92 -2
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +173 -3
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +401 -77
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +518 -251
- data/lib/active_record/connection_adapters/schema_cache.rb +326 -102
- data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +78 -55
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +68 -54
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +20 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +66 -22
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +372 -130
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +229 -0
- data/lib/active_record/connection_adapters.rb +130 -6
- data/lib/active_record/connection_handling.rb +132 -146
- data/lib/active_record/core.rb +276 -251
- data/lib/active_record/counter_cache.rb +68 -34
- data/lib/active_record/database_configurations/connection_url_resolver.rb +9 -3
- data/lib/active_record/database_configurations/database_config.rb +34 -10
- data/lib/active_record/database_configurations/hash_config.rb +107 -31
- data/lib/active_record/database_configurations/url_config.rb +38 -13
- data/lib/active_record/database_configurations.rb +96 -60
- data/lib/active_record/delegated_type.rb +90 -20
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +4 -2
- data/lib/active_record/disable_joins_association_relation.rb +39 -0
- data/lib/active_record/dynamic_matchers.rb +3 -3
- 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 +68 -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 +175 -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 +170 -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 +157 -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 +100 -0
- data/lib/active_record/encryption.rb +56 -0
- data/lib/active_record/enum.rb +163 -63
- data/lib/active_record/errors.rb +210 -27
- data/lib/active_record/explain.rb +21 -12
- data/lib/active_record/explain_registry.rb +11 -6
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +15 -1
- data/lib/active_record/fixture_set/model_metadata.rb +14 -4
- data/lib/active_record/fixture_set/render_context.rb +2 -0
- data/lib/active_record/fixture_set/table_row.rb +70 -14
- data/lib/active_record/fixture_set/table_rows.rb +4 -4
- data/lib/active_record/fixtures.rb +179 -112
- data/lib/active_record/future_result.rb +178 -0
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +85 -31
- data/lib/active_record/insert_all.rb +148 -32
- data/lib/active_record/integration.rb +14 -10
- data/lib/active_record/internal_metadata.rb +123 -23
- data/lib/active_record/legacy_yaml_adapter.rb +2 -39
- data/lib/active_record/locking/optimistic.rb +43 -27
- data/lib/active_record/locking/pessimistic.rb +15 -6
- data/lib/active_record/log_subscriber.rb +41 -29
- 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.rb +10 -10
- data/lib/active_record/middleware/database_selector.rb +23 -13
- data/lib/active_record/middleware/shard_selector.rb +62 -0
- data/lib/active_record/migration/command_recorder.rb +113 -16
- data/lib/active_record/migration/compatibility.rb +235 -46
- 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 +1 -1
- data/lib/active_record/migration/pending_migration_connection.rb +21 -0
- data/lib/active_record/migration.rb +374 -177
- data/lib/active_record/model_schema.rb +143 -159
- data/lib/active_record/nested_attributes.rb +48 -21
- data/lib/active_record/no_touching.rb +3 -3
- data/lib/active_record/normalization.rb +163 -0
- data/lib/active_record/persistence.rb +282 -283
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +19 -25
- data/lib/active_record/query_logs.rb +189 -0
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +44 -9
- data/lib/active_record/railtie.rb +234 -71
- data/lib/active_record/railties/controller_runtime.rb +25 -11
- data/lib/active_record/railties/databases.rake +189 -256
- data/lib/active_record/railties/job_runtime.rb +23 -0
- data/lib/active_record/readonly_attributes.rb +41 -3
- data/lib/active_record/reflection.rb +325 -103
- data/lib/active_record/relation/batches/batch_enumerator.rb +38 -9
- data/lib/active_record/relation/batches.rb +198 -63
- data/lib/active_record/relation/calculations.rb +300 -111
- data/lib/active_record/relation/delegation.rb +33 -22
- data/lib/active_record/relation/finder_methods.rb +123 -52
- data/lib/active_record/relation/merger.rb +26 -19
- data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +38 -4
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -7
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
- data/lib/active_record/relation/predicate_builder.rb +29 -22
- data/lib/active_record/relation/query_attribute.rb +30 -12
- data/lib/active_record/relation/query_methods.rb +842 -150
- data/lib/active_record/relation/record_fetch_warning.rb +10 -9
- data/lib/active_record/relation/spawn_methods.rb +7 -6
- data/lib/active_record/relation/where_clause.rb +15 -36
- data/lib/active_record/relation.rb +736 -145
- data/lib/active_record/result.rb +67 -54
- data/lib/active_record/runtime_registry.rb +71 -13
- data/lib/active_record/sanitization.rb +84 -34
- data/lib/active_record/schema.rb +39 -23
- data/lib/active_record/schema_dumper.rb +90 -31
- data/lib/active_record/schema_migration.rb +74 -23
- data/lib/active_record/scoping/default.rb +72 -15
- data/lib/active_record/scoping/named.rb +5 -13
- data/lib/active_record/scoping.rb +65 -34
- data/lib/active_record/secure_password.rb +60 -0
- data/lib/active_record/secure_token.rb +21 -3
- data/lib/active_record/serialization.rb +6 -1
- data/lib/active_record/signed_id.rb +30 -9
- data/lib/active_record/statement_cache.rb +7 -7
- data/lib/active_record/store.rb +10 -10
- data/lib/active_record/suppressor.rb +13 -15
- data/lib/active_record/table_metadata.rb +7 -3
- data/lib/active_record/tasks/database_tasks.rb +277 -149
- data/lib/active_record/tasks/mysql_database_tasks.rb +16 -7
- data/lib/active_record/tasks/postgresql_database_tasks.rb +35 -26
- data/lib/active_record/tasks/sqlite_database_tasks.rb +16 -7
- data/lib/active_record/test_databases.rb +1 -1
- data/lib/active_record/test_fixtures.rb +173 -155
- data/lib/active_record/testing/query_assertions.rb +121 -0
- data/lib/active_record/timestamp.rb +32 -19
- data/lib/active_record/token_for.rb +123 -0
- data/lib/active_record/touch_later.rb +12 -7
- data/lib/active_record/transaction.rb +132 -0
- data/lib/active_record/transactions.rb +118 -41
- data/lib/active_record/translation.rb +3 -5
- data/lib/active_record/type/adapter_specific_registry.rb +32 -14
- data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
- data/lib/active_record/type/internal/timezone.rb +7 -2
- data/lib/active_record/type/serialized.rb +9 -7
- data/lib/active_record/type/time.rb +4 -0
- data/lib/active_record/type/type_map.rb +17 -20
- data/lib/active_record/type.rb +1 -2
- data/lib/active_record/type_caster/connection.rb +4 -4
- data/lib/active_record/validations/absence.rb +1 -1
- data/lib/active_record/validations/associated.rb +13 -7
- data/lib/active_record/validations/numericality.rb +5 -4
- data/lib/active_record/validations/presence.rb +5 -28
- data/lib/active_record/validations/uniqueness.rb +64 -15
- data/lib/active_record/validations.rb +12 -5
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +444 -32
- data/lib/arel/alias_predication.rb +1 -1
- data/lib/arel/attributes/attribute.rb +0 -8
- data/lib/arel/collectors/bind.rb +2 -0
- data/lib/arel/collectors/composite.rb +7 -0
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +1 -1
- data/lib/arel/crud.rb +28 -22
- data/lib/arel/delete_manager.rb +18 -4
- data/lib/arel/errors.rb +10 -0
- data/lib/arel/factory_methods.rb +4 -0
- data/lib/arel/filter_predications.rb +9 -0
- data/lib/arel/insert_manager.rb +2 -3
- data/lib/arel/nodes/binary.rb +6 -7
- data/lib/arel/nodes/bound_sql_literal.rb +65 -0
- data/lib/arel/nodes/casted.rb +1 -1
- data/lib/arel/nodes/cte.rb +36 -0
- data/lib/arel/nodes/delete_statement.rb +12 -13
- data/lib/arel/nodes/filter.rb +10 -0
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/function.rb +1 -0
- data/lib/arel/nodes/homogeneous_in.rb +1 -9
- data/lib/arel/nodes/insert_statement.rb +2 -2
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/{and.rb → nary.rb} +9 -2
- data/lib/arel/nodes/node.rb +115 -5
- data/lib/arel/nodes/select_core.rb +2 -2
- data/lib/arel/nodes/select_statement.rb +2 -2
- data/lib/arel/nodes/sql_literal.rb +13 -0
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes/update_statement.rb +8 -3
- data/lib/arel/nodes.rb +7 -2
- data/lib/arel/predications.rb +14 -4
- data/lib/arel/select_manager.rb +11 -5
- data/lib/arel/table.rb +9 -6
- data/lib/arel/tree_manager.rb +8 -15
- data/lib/arel/update_manager.rb +20 -5
- data/lib/arel/visitors/dot.rb +81 -90
- data/lib/arel/visitors/mysql.rb +23 -5
- data/lib/arel/visitors/postgresql.rb +1 -22
- data/lib/arel/visitors/to_sql.rb +170 -36
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel.rb +23 -4
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +4 -1
- data/lib/rails/generators/active_record/migration.rb +3 -1
- data/lib/rails/generators/active_record/model/USAGE +113 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
- 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
- metadata +100 -14
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
- data/lib/active_record/null_relation.rb +0 -67
@@ -5,30 +5,49 @@ require "active_support/core_ext/enumerable"
|
|
5
5
|
module ActiveRecord
|
6
6
|
class InsertAll # :nodoc:
|
7
7
|
attr_reader :model, :connection, :inserts, :keys
|
8
|
-
attr_reader :on_duplicate, :returning, :unique_by
|
8
|
+
attr_reader :on_duplicate, :update_only, :returning, :unique_by, :update_sql
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
class << self
|
11
|
+
def execute(relation, ...)
|
12
|
+
relation.model.with_connection do |c|
|
13
|
+
new(relation, c, ...).execute
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
15
17
|
|
16
|
-
|
17
|
-
|
18
|
-
|
18
|
+
def initialize(relation, connection, inserts, on_duplicate:, update_only: nil, returning: nil, unique_by: nil, record_timestamps: nil)
|
19
|
+
@relation = relation
|
20
|
+
@model, @connection, @inserts = relation.model, connection, inserts.map(&:stringify_keys)
|
21
|
+
@on_duplicate, @update_only, @returning, @unique_by = on_duplicate, update_only, returning, unique_by
|
22
|
+
@record_timestamps = record_timestamps.nil? ? model.record_timestamps : record_timestamps
|
23
|
+
|
24
|
+
disallow_raw_sql!(on_duplicate)
|
25
|
+
disallow_raw_sql!(returning)
|
26
|
+
|
27
|
+
if @inserts.empty?
|
28
|
+
@keys = []
|
29
|
+
else
|
30
|
+
resolve_sti
|
31
|
+
resolve_attribute_aliases
|
32
|
+
@keys = @inserts.first.keys
|
19
33
|
end
|
34
|
+
|
35
|
+
@scope_attributes = relation.scope_for_create.except(@model.inheritance_column)
|
36
|
+
@keys |= @scope_attributes.keys
|
20
37
|
@keys = @keys.to_set
|
21
38
|
|
22
39
|
@returning = (connection.supports_insert_returning? ? primary_keys : false) if @returning.nil?
|
23
40
|
@returning = false if @returning == []
|
24
41
|
|
25
|
-
@unique_by = find_unique_index_for(unique_by)
|
26
|
-
@on_duplicate = :skip if @on_duplicate == :update && updatable_columns.empty?
|
42
|
+
@unique_by = find_unique_index_for(@unique_by)
|
27
43
|
|
44
|
+
configure_on_duplicate_update_logic
|
28
45
|
ensure_valid_options_for_connection!
|
29
46
|
end
|
30
47
|
|
31
48
|
def execute
|
49
|
+
return ActiveRecord::Result.empty if inserts.empty?
|
50
|
+
|
32
51
|
message = +"#{model} "
|
33
52
|
message << "Bulk " if inserts.many?
|
34
53
|
message << (on_duplicate == :update ? "Upsert" : "Insert")
|
@@ -36,14 +55,13 @@ module ActiveRecord
|
|
36
55
|
end
|
37
56
|
|
38
57
|
def updatable_columns
|
39
|
-
keys - readonly_columns - unique_by_columns
|
58
|
+
@updatable_columns ||= keys - readonly_columns - unique_by_columns
|
40
59
|
end
|
41
60
|
|
42
61
|
def primary_keys
|
43
|
-
Array(
|
62
|
+
Array(@model.schema_cache.primary_keys(model.table_name))
|
44
63
|
end
|
45
64
|
|
46
|
-
|
47
65
|
def skip_duplicates?
|
48
66
|
on_duplicate == :skip
|
49
67
|
end
|
@@ -55,18 +73,78 @@ module ActiveRecord
|
|
55
73
|
def map_key_with_value
|
56
74
|
inserts.map do |attributes|
|
57
75
|
attributes = attributes.stringify_keys
|
58
|
-
attributes.merge!(scope_attributes)
|
76
|
+
attributes.merge!(@scope_attributes)
|
77
|
+
attributes.reverse_merge!(timestamps_for_create) if record_timestamps?
|
59
78
|
|
60
79
|
verify_attributes(attributes)
|
61
80
|
|
62
|
-
|
81
|
+
keys_including_timestamps.map do |key|
|
63
82
|
yield key, attributes[key]
|
64
83
|
end
|
65
84
|
end
|
66
85
|
end
|
67
86
|
|
87
|
+
def record_timestamps?
|
88
|
+
@record_timestamps
|
89
|
+
end
|
90
|
+
|
91
|
+
# TODO: Consider renaming this method, as it only conditionally extends keys, not always
|
92
|
+
def keys_including_timestamps
|
93
|
+
@keys_including_timestamps ||= if record_timestamps?
|
94
|
+
keys + model.all_timestamp_attributes_in_model
|
95
|
+
else
|
96
|
+
keys
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
68
100
|
private
|
69
|
-
|
101
|
+
def has_attribute_aliases?(attributes)
|
102
|
+
attributes.keys.any? { |attribute| model.attribute_alias?(attribute) }
|
103
|
+
end
|
104
|
+
|
105
|
+
def resolve_sti
|
106
|
+
return if model.descends_from_active_record?
|
107
|
+
|
108
|
+
sti_type = model.sti_name
|
109
|
+
@inserts = @inserts.map do |insert|
|
110
|
+
insert.reverse_merge(model.inheritance_column.to_s => sti_type)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def resolve_attribute_aliases
|
115
|
+
return unless has_attribute_aliases?(@inserts.first)
|
116
|
+
|
117
|
+
@inserts = @inserts.map do |insert|
|
118
|
+
insert.transform_keys { |attribute| resolve_attribute_alias(attribute) }
|
119
|
+
end
|
120
|
+
|
121
|
+
@update_only = Array(@update_only).map { |attribute| resolve_attribute_alias(attribute) } if @update_only
|
122
|
+
@unique_by = Array(@unique_by).map { |attribute| resolve_attribute_alias(attribute) } if @unique_by
|
123
|
+
end
|
124
|
+
|
125
|
+
def resolve_attribute_alias(attribute)
|
126
|
+
model.attribute_alias(attribute) || attribute
|
127
|
+
end
|
128
|
+
|
129
|
+
def configure_on_duplicate_update_logic
|
130
|
+
if custom_update_sql_provided? && update_only.present?
|
131
|
+
raise ArgumentError, "You can't set :update_only and provide custom update SQL via :on_duplicate at the same time"
|
132
|
+
end
|
133
|
+
|
134
|
+
if update_only.present?
|
135
|
+
@updatable_columns = Array(update_only)
|
136
|
+
@on_duplicate = :update
|
137
|
+
elsif custom_update_sql_provided?
|
138
|
+
@update_sql = on_duplicate
|
139
|
+
@on_duplicate = :update
|
140
|
+
elsif @on_duplicate == :update && updatable_columns.empty?
|
141
|
+
@on_duplicate = :skip
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def custom_update_sql_provided?
|
146
|
+
@custom_update_sql_provided ||= Arel.arel_node?(on_duplicate)
|
147
|
+
end
|
70
148
|
|
71
149
|
def find_unique_index_for(unique_by)
|
72
150
|
if !connection.supports_insert_conflict_target?
|
@@ -77,8 +155,9 @@ module ActiveRecord
|
|
77
155
|
|
78
156
|
name_or_columns = unique_by || model.primary_key
|
79
157
|
match = Array(name_or_columns).map(&:to_s)
|
158
|
+
sorted_match = match.sort
|
80
159
|
|
81
|
-
if index = unique_indexes.find { |i| match.include?(i.name) || i.columns ==
|
160
|
+
if index = unique_indexes.find { |i| match.include?(i.name) || Array(i.columns).sort == sorted_match }
|
82
161
|
index
|
83
162
|
elsif match == primary_keys
|
84
163
|
unique_by.nil? ? nil : ActiveRecord::ConnectionAdapters::IndexDefinition.new(model.table_name, "#{model.table_name}_primary_key", true, match)
|
@@ -88,10 +167,9 @@ module ActiveRecord
|
|
88
167
|
end
|
89
168
|
|
90
169
|
def unique_indexes
|
91
|
-
|
170
|
+
@model.schema_cache.indexes(model.table_name).select(&:unique)
|
92
171
|
end
|
93
172
|
|
94
|
-
|
95
173
|
def ensure_valid_options_for_connection!
|
96
174
|
if returning && !connection.supports_insert_returning?
|
97
175
|
raise ArgumentError, "#{connection.class} does not support :returning"
|
@@ -117,7 +195,7 @@ module ActiveRecord
|
|
117
195
|
|
118
196
|
|
119
197
|
def readonly_columns
|
120
|
-
primary_keys + model.readonly_attributes
|
198
|
+
primary_keys + model.readonly_attributes
|
121
199
|
end
|
122
200
|
|
123
201
|
def unique_by_columns
|
@@ -126,15 +204,28 @@ module ActiveRecord
|
|
126
204
|
|
127
205
|
|
128
206
|
def verify_attributes(attributes)
|
129
|
-
if
|
207
|
+
if keys_including_timestamps != attributes.keys.to_set
|
130
208
|
raise ArgumentError, "All objects being inserted must have the same keys"
|
131
209
|
end
|
132
210
|
end
|
133
211
|
|
212
|
+
def disallow_raw_sql!(value)
|
213
|
+
return if !value.is_a?(String) || Arel.arel_node?(value)
|
214
|
+
|
215
|
+
raise ArgumentError, "Dangerous query method (method whose arguments are used as raw " \
|
216
|
+
"SQL) called: #{value}. " \
|
217
|
+
"Known-safe values can be passed " \
|
218
|
+
"by wrapping them in Arel.sql()."
|
219
|
+
end
|
220
|
+
|
221
|
+
def timestamps_for_create
|
222
|
+
model.all_timestamp_attributes_in_model.index_with(connection.high_precision_current_timestamp)
|
223
|
+
end
|
224
|
+
|
134
225
|
class Builder # :nodoc:
|
135
226
|
attr_reader :model
|
136
227
|
|
137
|
-
delegate :skip_duplicates?, :update_duplicates?, :keys, to: :insert_all
|
228
|
+
delegate :skip_duplicates?, :update_duplicates?, :keys, :keys_including_timestamps, :record_timestamps?, to: :insert_all
|
138
229
|
|
139
230
|
def initialize(insert_all)
|
140
231
|
@insert_all, @model, @connection = insert_all, insert_all.model, insert_all.connection
|
@@ -145,9 +236,10 @@ module ActiveRecord
|
|
145
236
|
end
|
146
237
|
|
147
238
|
def values_list
|
148
|
-
types = extract_types_from_columns_on(model.table_name, keys:
|
239
|
+
types = extract_types_from_columns_on(model.table_name, keys: keys_including_timestamps)
|
149
240
|
|
150
241
|
values_list = insert_all.map_key_with_value do |key, value|
|
242
|
+
next value if Arel::Nodes::SqlLiteral === value
|
151
243
|
connection.with_yaml_fallback(types[key].serialize(value))
|
152
244
|
end
|
153
245
|
|
@@ -155,7 +247,19 @@ module ActiveRecord
|
|
155
247
|
end
|
156
248
|
|
157
249
|
def returning
|
158
|
-
|
250
|
+
return unless insert_all.returning
|
251
|
+
|
252
|
+
if insert_all.returning.is_a?(String)
|
253
|
+
insert_all.returning
|
254
|
+
else
|
255
|
+
Array(insert_all.returning).map do |attribute|
|
256
|
+
if model.attribute_alias?(attribute)
|
257
|
+
"#{quote_column(model.attribute_alias(attribute))} AS #{quote_column(attribute)}"
|
258
|
+
else
|
259
|
+
quote_column(attribute)
|
260
|
+
end
|
261
|
+
end.join(",")
|
262
|
+
end
|
159
263
|
end
|
160
264
|
|
161
265
|
def conflict_target
|
@@ -173,26 +277,34 @@ module ActiveRecord
|
|
173
277
|
end
|
174
278
|
|
175
279
|
def touch_model_timestamps_unless(&block)
|
176
|
-
|
280
|
+
return "" unless update_duplicates? && record_timestamps?
|
281
|
+
|
282
|
+
model.timestamp_attributes_for_update_in_model.filter_map do |column_name|
|
177
283
|
if touch_timestamp_attribute?(column_name)
|
178
|
-
"#{column_name}=(CASE WHEN (#{updatable_columns.map(&block).join(" AND ")}) THEN #{model.quoted_table_name}.#{column_name} ELSE
|
284
|
+
"#{column_name}=(CASE WHEN (#{updatable_columns.map(&block).join(" AND ")}) THEN #{model.quoted_table_name}.#{column_name} ELSE #{connection.high_precision_current_timestamp} END),"
|
179
285
|
end
|
180
|
-
end.
|
286
|
+
end.join
|
181
287
|
end
|
182
288
|
|
289
|
+
def raw_update_sql
|
290
|
+
insert_all.update_sql
|
291
|
+
end
|
292
|
+
|
293
|
+
alias raw_update_sql? raw_update_sql
|
294
|
+
|
183
295
|
private
|
184
296
|
attr_reader :connection, :insert_all
|
185
297
|
|
186
298
|
def touch_timestamp_attribute?(column_name)
|
187
|
-
|
299
|
+
insert_all.updatable_columns.exclude?(column_name)
|
188
300
|
end
|
189
301
|
|
190
302
|
def columns_list
|
191
|
-
format_columns(insert_all.
|
303
|
+
format_columns(insert_all.keys_including_timestamps)
|
192
304
|
end
|
193
305
|
|
194
306
|
def extract_types_from_columns_on(table_name, keys:)
|
195
|
-
columns =
|
307
|
+
columns = @model.schema_cache.columns_hash(table_name)
|
196
308
|
|
197
309
|
unknown_column = (keys - columns.keys).first
|
198
310
|
raise UnknownAttributeError.new(model.new, unknown_column) if unknown_column
|
@@ -205,7 +317,11 @@ module ActiveRecord
|
|
205
317
|
end
|
206
318
|
|
207
319
|
def quote_columns(columns)
|
208
|
-
columns.map(
|
320
|
+
columns.map { |column| quote_column(column) }
|
321
|
+
end
|
322
|
+
|
323
|
+
def quote_column(column)
|
324
|
+
connection.quote_column_name(column)
|
209
325
|
end
|
210
326
|
end
|
211
327
|
end
|
@@ -10,7 +10,7 @@ module ActiveRecord
|
|
10
10
|
##
|
11
11
|
# :singleton-method:
|
12
12
|
# Indicates the format used to generate the timestamp in the cache key, if
|
13
|
-
# versioning is off. Accepts any of the symbols in
|
13
|
+
# versioning is off. Accepts any of the symbols in +Time::DATE_FORMATS+.
|
14
14
|
#
|
15
15
|
# This is +:usec+, by default.
|
16
16
|
class_attribute :cache_timestamp_format, instance_writer: false, default: :usec
|
@@ -20,7 +20,7 @@ module ActiveRecord
|
|
20
20
|
# Indicates whether to use a stable #cache_key method that is accompanied
|
21
21
|
# by a changing version in the #cache_version method.
|
22
22
|
#
|
23
|
-
# This is +true+, by default on Rails 5.2 and above.
|
23
|
+
# This is +true+, by default on \Rails 5.2 and above.
|
24
24
|
class_attribute :cache_versioning, instance_writer: false, default: false
|
25
25
|
|
26
26
|
##
|
@@ -28,7 +28,7 @@ module ActiveRecord
|
|
28
28
|
# Indicates whether to use a stable #cache_key method that is accompanied
|
29
29
|
# by a changing version in the #cache_version method on collections.
|
30
30
|
#
|
31
|
-
# This is +false+, by default until Rails 6.1.
|
31
|
+
# This is +false+, by default until \Rails 6.1.
|
32
32
|
class_attribute :collection_cache_versioning, instance_writer: false, default: false
|
33
33
|
end
|
34
34
|
|
@@ -55,8 +55,8 @@ module ActiveRecord
|
|
55
55
|
# user = User.find_by(name: 'Phusion')
|
56
56
|
# user_path(user) # => "/users/Phusion"
|
57
57
|
def to_param
|
58
|
-
|
59
|
-
id
|
58
|
+
return unless id
|
59
|
+
Array(id).join(self.class.param_delimiter)
|
60
60
|
end
|
61
61
|
|
62
62
|
# Returns a stable cache key that can be used to identify this record.
|
@@ -64,7 +64,7 @@ module ActiveRecord
|
|
64
64
|
# Product.new.cache_key # => "products/new"
|
65
65
|
# Product.find(5).cache_key # => "products/5"
|
66
66
|
#
|
67
|
-
# If ActiveRecord::Base.cache_versioning is turned off, as it was in Rails 5.1 and earlier,
|
67
|
+
# If ActiveRecord::Base.cache_versioning is turned off, as it was in \Rails 5.1 and earlier,
|
68
68
|
# the cache key will also include a version.
|
69
69
|
#
|
70
70
|
# Product.cache_versioning = false
|
@@ -79,7 +79,7 @@ module ActiveRecord
|
|
79
79
|
timestamp = max_updated_column_timestamp
|
80
80
|
|
81
81
|
if timestamp
|
82
|
-
timestamp = timestamp.utc.
|
82
|
+
timestamp = timestamp.utc.to_fs(cache_timestamp_format)
|
83
83
|
"#{model_name.cache_key}/#{id}-#{timestamp}"
|
84
84
|
else
|
85
85
|
"#{model_name.cache_key}/#{id}"
|
@@ -101,11 +101,12 @@ module ActiveRecord
|
|
101
101
|
timestamp = updated_at_before_type_cast
|
102
102
|
if can_use_fast_cache_version?(timestamp)
|
103
103
|
raw_timestamp_to_cache_version(timestamp)
|
104
|
+
|
104
105
|
elsif timestamp = updated_at
|
105
|
-
timestamp.utc.
|
106
|
+
timestamp.utc.to_fs(cache_timestamp_format)
|
106
107
|
end
|
107
108
|
elsif self.class.has_attribute?("updated_at")
|
108
|
-
raise ActiveModel::MissingAttributeError, "missing attribute
|
109
|
+
raise ActiveModel::MissingAttributeError, "missing attribute 'updated_at' for #{self.class}"
|
109
110
|
end
|
110
111
|
end
|
111
112
|
|
@@ -177,7 +178,10 @@ module ActiveRecord
|
|
177
178
|
def can_use_fast_cache_version?(timestamp)
|
178
179
|
timestamp.is_a?(String) &&
|
179
180
|
cache_timestamp_format == :usec &&
|
180
|
-
|
181
|
+
# FIXME: checking out a connection for this is wasteful
|
182
|
+
# we should store/cache this information in the schema cache
|
183
|
+
# or similar.
|
184
|
+
self.class.with_connection(&:default_timezone) == :utc &&
|
181
185
|
!updated_at_came_from_user?
|
182
186
|
end
|
183
187
|
|
@@ -9,42 +9,83 @@ module ActiveRecord
|
|
9
9
|
#
|
10
10
|
# This is enabled by default. To disable this functionality set
|
11
11
|
# `use_metadata_table` to false in your database configuration.
|
12
|
-
class InternalMetadata
|
13
|
-
|
12
|
+
class InternalMetadata # :nodoc:
|
13
|
+
class NullInternalMetadata # :nodoc:
|
14
|
+
end
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
attr_reader :arel_table
|
17
|
+
|
18
|
+
def initialize(pool)
|
19
|
+
@pool = pool
|
20
|
+
@arel_table = Arel::Table.new(table_name)
|
21
|
+
end
|
22
|
+
|
23
|
+
def primary_key
|
24
|
+
"key"
|
25
|
+
end
|
19
26
|
|
20
|
-
|
21
|
-
|
27
|
+
def value_key
|
28
|
+
"value"
|
29
|
+
end
|
30
|
+
|
31
|
+
def table_name
|
32
|
+
"#{ActiveRecord::Base.table_name_prefix}#{ActiveRecord::Base.internal_metadata_table_name}#{ActiveRecord::Base.table_name_suffix}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def enabled?
|
36
|
+
@pool.db_config.use_metadata_table?
|
37
|
+
end
|
38
|
+
|
39
|
+
def []=(key, value)
|
40
|
+
return unless enabled?
|
41
|
+
|
42
|
+
@pool.with_connection do |connection|
|
43
|
+
update_or_create_entry(connection, key, value)
|
22
44
|
end
|
45
|
+
end
|
23
46
|
|
24
|
-
|
25
|
-
|
47
|
+
def [](key)
|
48
|
+
return unless enabled?
|
49
|
+
|
50
|
+
@pool.with_connection do |connection|
|
51
|
+
if entry = select_entry(connection, key)
|
52
|
+
entry[value_key]
|
53
|
+
end
|
26
54
|
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def delete_all_entries
|
58
|
+
dm = Arel::DeleteManager.new(arel_table)
|
27
59
|
|
28
|
-
|
29
|
-
"#{
|
60
|
+
@pool.with_connection do |connection|
|
61
|
+
connection.delete(dm, "#{self.class} Destroy")
|
30
62
|
end
|
63
|
+
end
|
31
64
|
|
32
|
-
|
33
|
-
|
65
|
+
def count
|
66
|
+
sm = Arel::SelectManager.new(arel_table)
|
67
|
+
sm.project(*Arel::Nodes::Count.new([Arel.star]))
|
34
68
|
|
35
|
-
|
69
|
+
@pool.with_connection do |connection|
|
70
|
+
connection.select_values(sm, "#{self.class} Count").first
|
36
71
|
end
|
72
|
+
end
|
37
73
|
|
38
|
-
|
39
|
-
|
74
|
+
def create_table_and_set_flags(environment, schema_sha1 = nil)
|
75
|
+
return unless enabled?
|
40
76
|
|
41
|
-
|
77
|
+
@pool.with_connection do |connection|
|
78
|
+
create_table
|
79
|
+
update_or_create_entry(connection, :environment, environment)
|
80
|
+
update_or_create_entry(connection, :schema_sha1, schema_sha1) if schema_sha1
|
42
81
|
end
|
82
|
+
end
|
43
83
|
|
44
|
-
|
45
|
-
|
46
|
-
|
84
|
+
# Creates an internal metadata table with columns +key+ and +value+
|
85
|
+
def create_table
|
86
|
+
return unless enabled?
|
47
87
|
|
88
|
+
@pool.with_connection do |connection|
|
48
89
|
unless connection.table_exists?(table_name)
|
49
90
|
connection.create_table(table_name, id: false) do |t|
|
50
91
|
t.string :key, **connection.internal_string_options_for_primary_key
|
@@ -53,12 +94,71 @@ module ActiveRecord
|
|
53
94
|
end
|
54
95
|
end
|
55
96
|
end
|
97
|
+
end
|
56
98
|
|
57
|
-
|
58
|
-
|
99
|
+
def drop_table
|
100
|
+
return unless enabled?
|
59
101
|
|
102
|
+
@pool.with_connection do |connection|
|
60
103
|
connection.drop_table table_name, if_exists: true
|
61
104
|
end
|
62
105
|
end
|
106
|
+
|
107
|
+
def table_exists?
|
108
|
+
@pool.schema_cache.data_source_exists?(table_name)
|
109
|
+
end
|
110
|
+
|
111
|
+
private
|
112
|
+
def update_or_create_entry(connection, key, value)
|
113
|
+
entry = select_entry(connection, key)
|
114
|
+
|
115
|
+
if entry
|
116
|
+
if entry[value_key] != value
|
117
|
+
update_entry(connection, key, value)
|
118
|
+
else
|
119
|
+
entry[value_key]
|
120
|
+
end
|
121
|
+
else
|
122
|
+
create_entry(connection, key, value)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def current_time(connection)
|
127
|
+
connection.default_timezone == :utc ? Time.now.utc : Time.now
|
128
|
+
end
|
129
|
+
|
130
|
+
def create_entry(connection, key, value)
|
131
|
+
im = Arel::InsertManager.new(arel_table)
|
132
|
+
im.insert [
|
133
|
+
[arel_table[primary_key], key],
|
134
|
+
[arel_table[value_key], value],
|
135
|
+
[arel_table[:created_at], current_time(connection)],
|
136
|
+
[arel_table[:updated_at], current_time(connection)]
|
137
|
+
]
|
138
|
+
|
139
|
+
connection.insert(im, "#{self.class} Create", primary_key, key)
|
140
|
+
end
|
141
|
+
|
142
|
+
def update_entry(connection, key, new_value)
|
143
|
+
um = Arel::UpdateManager.new(arel_table)
|
144
|
+
um.set [
|
145
|
+
[arel_table[value_key], new_value],
|
146
|
+
[arel_table[:updated_at], current_time(connection)]
|
147
|
+
]
|
148
|
+
|
149
|
+
um.where(arel_table[primary_key].eq(key))
|
150
|
+
|
151
|
+
connection.update(um, "#{self.class} Update")
|
152
|
+
end
|
153
|
+
|
154
|
+
def select_entry(connection, key)
|
155
|
+
sm = Arel::SelectManager.new(arel_table)
|
156
|
+
sm.project(Arel::Nodes::SqlLiteral.new("*", retryable: true))
|
157
|
+
sm.where(arel_table[primary_key].eq(Arel::Nodes::BindParam.new(key)))
|
158
|
+
sm.order(arel_table[primary_key].asc)
|
159
|
+
sm.limit = 1
|
160
|
+
|
161
|
+
connection.select_all(sm, "#{self.class} Load").first
|
162
|
+
end
|
63
163
|
end
|
64
164
|
end
|
@@ -2,50 +2,13 @@
|
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
module LegacyYamlAdapter # :nodoc:
|
5
|
-
def self.convert(
|
5
|
+
def self.convert(coder)
|
6
6
|
return coder unless coder.is_a?(Psych::Coder)
|
7
7
|
|
8
8
|
case coder["active_record_yaml_version"]
|
9
9
|
when 1, 2 then coder
|
10
10
|
else
|
11
|
-
|
12
|
-
YAML loading from legacy format older than Rails 5.0 is deprecated
|
13
|
-
and will be removed in Rails 7.0.
|
14
|
-
MSG
|
15
|
-
if coder["attributes"].is_a?(ActiveModel::AttributeSet)
|
16
|
-
Rails420.convert(klass, coder)
|
17
|
-
else
|
18
|
-
Rails41.convert(klass, coder)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
module Rails420 # :nodoc:
|
24
|
-
def self.convert(klass, coder)
|
25
|
-
attribute_set = coder["attributes"]
|
26
|
-
|
27
|
-
klass.attribute_names.each do |attr_name|
|
28
|
-
attribute = attribute_set[attr_name]
|
29
|
-
if attribute.type.is_a?(Delegator)
|
30
|
-
type_from_klass = klass.type_for_attribute(attr_name)
|
31
|
-
attribute_set[attr_name] = attribute.with_type(type_from_klass)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
coder
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
module Rails41 # :nodoc:
|
40
|
-
def self.convert(klass, coder)
|
41
|
-
attributes = klass.attributes_builder
|
42
|
-
.build_from_database(coder["attributes"])
|
43
|
-
new_record = coder["attributes"][klass.primary_key].blank?
|
44
|
-
|
45
|
-
{
|
46
|
-
"attributes" => attributes,
|
47
|
-
"new_record" => new_record,
|
48
|
-
}
|
11
|
+
raise("Active Record doesn't know how to load YAML with this format.")
|
49
12
|
end
|
50
13
|
end
|
51
14
|
end
|