activerecord 7.0.8.1 → 7.2.2.1
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 +642 -1925
- data/MIT-LICENSE +1 -1
- data/README.rdoc +29 -29
- data/examples/performance.rb +2 -2
- data/lib/active_record/aggregations.rb +16 -13
- data/lib/active_record/association_relation.rb +2 -2
- data/lib/active_record/associations/alias_tracker.rb +25 -19
- data/lib/active_record/associations/association.rb +35 -12
- data/lib/active_record/associations/association_scope.rb +16 -9
- data/lib/active_record/associations/belongs_to_association.rb +23 -8
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -2
- data/lib/active_record/associations/builder/association.rb +3 -3
- data/lib/active_record/associations/builder/belongs_to.rb +22 -8
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -7
- data/lib/active_record/associations/builder/has_many.rb +3 -4
- data/lib/active_record/associations/builder/has_one.rb +3 -4
- data/lib/active_record/associations/builder/singular_association.rb +4 -0
- data/lib/active_record/associations/collection_association.rb +26 -14
- data/lib/active_record/associations/collection_proxy.rb +29 -11
- 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 +21 -14
- data/lib/active_record/associations/has_many_through_association.rb +17 -7
- data/lib/active_record/associations/has_one_association.rb +10 -3
- data/lib/active_record/associations/join_dependency/join_association.rb +30 -27
- data/lib/active_record/associations/join_dependency.rb +10 -10
- data/lib/active_record/associations/nested_error.rb +47 -0
- data/lib/active_record/associations/preloader/association.rb +33 -8
- data/lib/active_record/associations/preloader/branch.rb +7 -1
- data/lib/active_record/associations/preloader/through_association.rb +1 -3
- data/lib/active_record/associations/preloader.rb +13 -10
- data/lib/active_record/associations/singular_association.rb +7 -1
- data/lib/active_record/associations/through_association.rb +22 -11
- data/lib/active_record/associations.rb +354 -485
- data/lib/active_record/attribute_assignment.rb +0 -4
- data/lib/active_record/attribute_methods/before_type_cast.rb +17 -0
- data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
- data/lib/active_record/attribute_methods/dirty.rb +53 -35
- data/lib/active_record/attribute_methods/primary_key.rb +45 -25
- data/lib/active_record/attribute_methods/query.rb +28 -16
- data/lib/active_record/attribute_methods/read.rb +8 -7
- data/lib/active_record/attribute_methods/serialization.rb +131 -32
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +11 -6
- data/lib/active_record/attribute_methods/write.rb +6 -6
- data/lib/active_record/attribute_methods.rb +148 -33
- data/lib/active_record/attributes.rb +64 -50
- data/lib/active_record/autosave_association.rb +69 -37
- data/lib/active_record/base.rb +9 -5
- data/lib/active_record/callbacks.rb +11 -25
- 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 -42
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +123 -131
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +4 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +323 -88
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +160 -45
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +217 -63
- data/lib/active_record/connection_adapters/abstract/quoting.rb +72 -63
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +18 -4
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +137 -11
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +307 -129
- data/lib/active_record/connection_adapters/abstract/transaction.rb +367 -75
- data/lib/active_record/connection_adapters/abstract_adapter.rb +510 -111
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +278 -125
- data/lib/active_record/connection_adapters/column.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +26 -139
- data/lib/active_record/connection_adapters/mysql/quoting.rb +53 -54
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +6 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +25 -13
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +152 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +101 -68
- data/lib/active_record/connection_adapters/pool_config.rb +20 -10
- data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/column.rb +14 -3
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +100 -43
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
- 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 +11 -2
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +65 -61
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +3 -9
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -6
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +151 -2
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +53 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +370 -63
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +367 -201
- data/lib/active_record/connection_adapters/schema_cache.rb +302 -79
- data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +60 -43
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +45 -46
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +14 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +50 -8
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +290 -110
- 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 +124 -1
- data/lib/active_record/connection_handling.rb +96 -104
- data/lib/active_record/core.rb +251 -176
- data/lib/active_record/counter_cache.rb +68 -34
- data/lib/active_record/database_configurations/connection_url_resolver.rb +8 -3
- data/lib/active_record/database_configurations/database_config.rb +26 -5
- data/lib/active_record/database_configurations/hash_config.rb +52 -34
- data/lib/active_record/database_configurations/url_config.rb +37 -12
- data/lib/active_record/database_configurations.rb +87 -34
- data/lib/active_record/delegated_type.rb +39 -10
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +3 -1
- data/lib/active_record/dynamic_matchers.rb +2 -2
- data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +4 -1
- data/lib/active_record/encryption/config.rb +25 -1
- data/lib/active_record/encryption/configurable.rb +12 -19
- data/lib/active_record/encryption/context.rb +10 -3
- data/lib/active_record/encryption/contexts.rb +5 -1
- data/lib/active_record/encryption/derived_secret_key_provider.rb +8 -2
- data/lib/active_record/encryption/encryptable_record.rb +45 -21
- data/lib/active_record/encryption/encrypted_attribute_type.rb +47 -12
- data/lib/active_record/encryption/encryptor.rb +18 -3
- data/lib/active_record/encryption/extended_deterministic_queries.rb +66 -69
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +3 -3
- data/lib/active_record/encryption/key_generator.rb +12 -1
- data/lib/active_record/encryption/key_provider.rb +1 -1
- data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
- data/lib/active_record/encryption/message_serializer.rb +6 -0
- data/lib/active_record/encryption/null_encryptor.rb +4 -0
- data/lib/active_record/encryption/properties.rb +3 -3
- data/lib/active_record/encryption/read_only_null_encryptor.rb +4 -0
- data/lib/active_record/encryption/scheme.rb +22 -21
- data/lib/active_record/encryption.rb +3 -0
- data/lib/active_record/enum.rb +129 -28
- data/lib/active_record/errors.rb +151 -31
- data/lib/active_record/explain.rb +21 -12
- 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 +29 -8
- data/lib/active_record/fixtures.rb +167 -97
- data/lib/active_record/future_result.rb +47 -8
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +34 -18
- data/lib/active_record/insert_all.rb +72 -22
- data/lib/active_record/integration.rb +11 -8
- data/lib/active_record/internal_metadata.rb +124 -20
- data/lib/active_record/locking/optimistic.rb +8 -7
- data/lib/active_record/locking/pessimistic.rb +5 -2
- data/lib/active_record/log_subscriber.rb +18 -22
- data/lib/active_record/marshalling.rb +59 -0
- data/lib/active_record/message_pack.rb +124 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +4 -0
- data/lib/active_record/middleware/database_selector.rb +6 -8
- data/lib/active_record/middleware/shard_selector.rb +3 -1
- data/lib/active_record/migration/command_recorder.rb +106 -8
- data/lib/active_record/migration/compatibility.rb +147 -5
- 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/pending_migration_connection.rb +21 -0
- data/lib/active_record/migration.rb +234 -117
- data/lib/active_record/model_schema.rb +90 -102
- data/lib/active_record/nested_attributes.rb +48 -11
- data/lib/active_record/normalization.rb +163 -0
- data/lib/active_record/persistence.rb +168 -339
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +18 -25
- data/lib/active_record/query_logs.rb +92 -52
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +33 -8
- data/lib/active_record/railtie.rb +129 -85
- data/lib/active_record/railties/controller_runtime.rb +22 -7
- data/lib/active_record/railties/databases.rake +145 -154
- data/lib/active_record/railties/job_runtime.rb +23 -0
- data/lib/active_record/readonly_attributes.rb +32 -5
- data/lib/active_record/reflection.rb +267 -69
- data/lib/active_record/relation/batches/batch_enumerator.rb +20 -5
- data/lib/active_record/relation/batches.rb +198 -63
- data/lib/active_record/relation/calculations.rb +250 -93
- data/lib/active_record/relation/delegation.rb +30 -19
- data/lib/active_record/relation/finder_methods.rb +93 -18
- data/lib/active_record/relation/merger.rb +6 -6
- data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +18 -3
- 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 +28 -16
- data/lib/active_record/relation/query_attribute.rb +2 -1
- data/lib/active_record/relation/query_methods.rb +576 -107
- data/lib/active_record/relation/record_fetch_warning.rb +3 -0
- data/lib/active_record/relation/spawn_methods.rb +5 -4
- data/lib/active_record/relation/where_clause.rb +7 -19
- data/lib/active_record/relation.rb +580 -90
- data/lib/active_record/result.rb +49 -48
- data/lib/active_record/runtime_registry.rb +63 -1
- data/lib/active_record/sanitization.rb +70 -25
- data/lib/active_record/schema.rb +8 -7
- data/lib/active_record/schema_dumper.rb +63 -14
- data/lib/active_record/schema_migration.rb +75 -24
- data/lib/active_record/scoping/default.rb +15 -5
- data/lib/active_record/scoping/named.rb +3 -2
- data/lib/active_record/scoping.rb +2 -1
- data/lib/active_record/secure_password.rb +60 -0
- data/lib/active_record/secure_token.rb +21 -3
- data/lib/active_record/signed_id.rb +27 -6
- data/lib/active_record/statement_cache.rb +7 -7
- data/lib/active_record/store.rb +8 -8
- data/lib/active_record/suppressor.rb +3 -1
- data/lib/active_record/table_metadata.rb +1 -1
- data/lib/active_record/tasks/database_tasks.rb +190 -118
- data/lib/active_record/tasks/mysql_database_tasks.rb +15 -6
- data/lib/active_record/tasks/postgresql_database_tasks.rb +16 -13
- data/lib/active_record/tasks/sqlite_database_tasks.rb +16 -7
- data/lib/active_record/test_fixtures.rb +170 -155
- data/lib/active_record/testing/query_assertions.rb +121 -0
- data/lib/active_record/timestamp.rb +31 -17
- 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 +106 -24
- data/lib/active_record/translation.rb +0 -2
- data/lib/active_record/type/adapter_specific_registry.rb +1 -8
- data/lib/active_record/type/internal/timezone.rb +7 -2
- data/lib/active_record/type/serialized.rb +1 -3
- data/lib/active_record/type/time.rb +4 -0
- 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 +9 -3
- 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 +61 -11
- data/lib/active_record/validations.rb +12 -5
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +247 -33
- data/lib/arel/alias_predication.rb +1 -1
- 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/errors.rb +10 -0
- data/lib/arel/factory_methods.rb +4 -0
- data/lib/arel/nodes/binary.rb +6 -7
- data/lib/arel/nodes/bound_sql_literal.rb +65 -0
- data/lib/arel/nodes/cte.rb +36 -0
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/homogeneous_in.rb +1 -9
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/{and.rb → nary.rb} +5 -2
- data/lib/arel/nodes/node.rb +115 -5
- data/lib/arel/nodes/sql_literal.rb +13 -0
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes.rb +6 -2
- data/lib/arel/predications.rb +3 -1
- data/lib/arel/select_manager.rb +1 -1
- data/lib/arel/table.rb +9 -5
- data/lib/arel/tree_manager.rb +8 -3
- data/lib/arel/update_manager.rb +2 -1
- data/lib/arel/visitors/dot.rb +1 -0
- data/lib/arel/visitors/mysql.rb +17 -5
- data/lib/arel/visitors/postgresql.rb +1 -12
- data/lib/arel/visitors/sqlite.rb +25 -0
- data/lib/arel/visitors/to_sql.rb +112 -34
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel.rb +21 -3
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- 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
- metadata +59 -17
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
- data/lib/active_record/null_relation.rb +0 -63
@@ -57,280 +57,34 @@ module ActiveRecord
|
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
60
|
-
#
|
61
|
-
#
|
62
|
-
# Active Record callbacks or validations. Though passed values
|
63
|
-
# go through Active Record's type casting and serialization.
|
60
|
+
# Builds an object (or multiple objects) and returns either the built object or a list of built
|
61
|
+
# objects.
|
64
62
|
#
|
65
|
-
#
|
66
|
-
|
67
|
-
insert_all([ attributes ], returning: returning, unique_by: unique_by, record_timestamps: record_timestamps)
|
68
|
-
end
|
69
|
-
|
70
|
-
# Inserts multiple records into the database in a single SQL INSERT
|
71
|
-
# statement. It does not instantiate any models nor does it trigger
|
72
|
-
# Active Record callbacks or validations. Though passed values
|
73
|
-
# go through Active Record's type casting and serialization.
|
74
|
-
#
|
75
|
-
# The +attributes+ parameter is an Array of Hashes. Every Hash determines
|
76
|
-
# the attributes for a single row and must have the same keys.
|
77
|
-
#
|
78
|
-
# Rows are considered to be unique by every unique index on the table. Any
|
79
|
-
# duplicate rows are skipped.
|
80
|
-
# Override with <tt>:unique_by</tt> (see below).
|
81
|
-
#
|
82
|
-
# Returns an ActiveRecord::Result with its contents based on
|
83
|
-
# <tt>:returning</tt> (see below).
|
84
|
-
#
|
85
|
-
# ==== Options
|
86
|
-
#
|
87
|
-
# [:returning]
|
88
|
-
# (PostgreSQL only) An array of attributes to return for all successfully
|
89
|
-
# inserted records, which by default is the primary key.
|
90
|
-
# Pass <tt>returning: %w[ id name ]</tt> for both id and name
|
91
|
-
# or <tt>returning: false</tt> to omit the underlying <tt>RETURNING</tt> SQL
|
92
|
-
# clause entirely.
|
93
|
-
#
|
94
|
-
# You can also pass an SQL string if you need more control on the return values
|
95
|
-
# (for example, <tt>returning: "id, name as new_name"</tt>).
|
96
|
-
#
|
97
|
-
# [:unique_by]
|
98
|
-
# (PostgreSQL and SQLite only) By default rows are considered to be unique
|
99
|
-
# by every unique index on the table. Any duplicate rows are skipped.
|
100
|
-
#
|
101
|
-
# To skip rows according to just one unique index pass <tt>:unique_by</tt>.
|
102
|
-
#
|
103
|
-
# Consider a Book model where no duplicate ISBNs make sense, but if any
|
104
|
-
# row has an existing id, or is not unique by another unique index,
|
105
|
-
# <tt>ActiveRecord::RecordNotUnique</tt> is raised.
|
106
|
-
#
|
107
|
-
# Unique indexes can be identified by columns or name:
|
108
|
-
#
|
109
|
-
# unique_by: :isbn
|
110
|
-
# unique_by: %i[ author_id name ]
|
111
|
-
# unique_by: :index_books_on_isbn
|
112
|
-
#
|
113
|
-
# [:record_timestamps]
|
114
|
-
# By default, automatic setting of timestamp columns is controlled by
|
115
|
-
# the model's <tt>record_timestamps</tt> config, matching typical
|
116
|
-
# behavior.
|
117
|
-
#
|
118
|
-
# To override this and force automatic setting of timestamp columns one
|
119
|
-
# way or the other, pass <tt>:record_timestamps</tt>:
|
120
|
-
#
|
121
|
-
# record_timestamps: true # Always set timestamps automatically
|
122
|
-
# record_timestamps: false # Never set timestamps automatically
|
123
|
-
#
|
124
|
-
# Because it relies on the index information from the database
|
125
|
-
# <tt>:unique_by</tt> is recommended to be paired with
|
126
|
-
# Active Record's schema_cache.
|
127
|
-
#
|
128
|
-
# ==== Example
|
129
|
-
#
|
130
|
-
# # Insert records and skip inserting any duplicates.
|
131
|
-
# # Here "Eloquent Ruby" is skipped because its id is not unique.
|
132
|
-
#
|
133
|
-
# Book.insert_all([
|
134
|
-
# { id: 1, title: "Rework", author: "David" },
|
135
|
-
# { id: 1, title: "Eloquent Ruby", author: "Russ" }
|
136
|
-
# ])
|
137
|
-
#
|
138
|
-
# # insert_all works on chained scopes, and you can use create_with
|
139
|
-
# # to set default attributes for all inserted records.
|
140
|
-
#
|
141
|
-
# author.books.create_with(created_at: Time.now).insert_all([
|
142
|
-
# { id: 1, title: "Rework" },
|
143
|
-
# { id: 2, title: "Eloquent Ruby" }
|
144
|
-
# ])
|
145
|
-
def insert_all(attributes, returning: nil, unique_by: nil, record_timestamps: nil)
|
146
|
-
InsertAll.new(self, attributes, on_duplicate: :skip, returning: returning, unique_by: unique_by, record_timestamps: record_timestamps).execute
|
147
|
-
end
|
148
|
-
|
149
|
-
# Inserts a single record into the database in a single SQL INSERT
|
150
|
-
# statement. It does not instantiate any models nor does it trigger
|
151
|
-
# Active Record callbacks or validations. Though passed values
|
152
|
-
# go through Active Record's type casting and serialization.
|
153
|
-
#
|
154
|
-
# See #insert_all! for more.
|
155
|
-
def insert!(attributes, returning: nil, record_timestamps: nil)
|
156
|
-
insert_all!([ attributes ], returning: returning, record_timestamps: record_timestamps)
|
157
|
-
end
|
158
|
-
|
159
|
-
# Inserts multiple records into the database in a single SQL INSERT
|
160
|
-
# statement. It does not instantiate any models nor does it trigger
|
161
|
-
# Active Record callbacks or validations. Though passed values
|
162
|
-
# go through Active Record's type casting and serialization.
|
163
|
-
#
|
164
|
-
# The +attributes+ parameter is an Array of Hashes. Every Hash determines
|
165
|
-
# the attributes for a single row and must have the same keys.
|
166
|
-
#
|
167
|
-
# Raises <tt>ActiveRecord::RecordNotUnique</tt> if any rows violate a
|
168
|
-
# unique index on the table. In that case, no rows are inserted.
|
169
|
-
#
|
170
|
-
# To skip duplicate rows, see #insert_all. To replace them, see #upsert_all.
|
171
|
-
#
|
172
|
-
# Returns an ActiveRecord::Result with its contents based on
|
173
|
-
# <tt>:returning</tt> (see below).
|
174
|
-
#
|
175
|
-
# ==== Options
|
176
|
-
#
|
177
|
-
# [:returning]
|
178
|
-
# (PostgreSQL only) An array of attributes to return for all successfully
|
179
|
-
# inserted records, which by default is the primary key.
|
180
|
-
# Pass <tt>returning: %w[ id name ]</tt> for both id and name
|
181
|
-
# or <tt>returning: false</tt> to omit the underlying <tt>RETURNING</tt> SQL
|
182
|
-
# clause entirely.
|
183
|
-
#
|
184
|
-
# You can also pass an SQL string if you need more control on the return values
|
185
|
-
# (for example, <tt>returning: "id, name as new_name"</tt>).
|
186
|
-
#
|
187
|
-
# [:record_timestamps]
|
188
|
-
# By default, automatic setting of timestamp columns is controlled by
|
189
|
-
# the model's <tt>record_timestamps</tt> config, matching typical
|
190
|
-
# behavior.
|
191
|
-
#
|
192
|
-
# To override this and force automatic setting of timestamp columns one
|
193
|
-
# way or the other, pass <tt>:record_timestamps</tt>:
|
194
|
-
#
|
195
|
-
# record_timestamps: true # Always set timestamps automatically
|
196
|
-
# record_timestamps: false # Never set timestamps automatically
|
197
|
-
#
|
198
|
-
# ==== Examples
|
199
|
-
#
|
200
|
-
# # Insert multiple records
|
201
|
-
# Book.insert_all!([
|
202
|
-
# { title: "Rework", author: "David" },
|
203
|
-
# { title: "Eloquent Ruby", author: "Russ" }
|
204
|
-
# ])
|
205
|
-
#
|
206
|
-
# # Raises ActiveRecord::RecordNotUnique because "Eloquent Ruby"
|
207
|
-
# # does not have a unique id.
|
208
|
-
# Book.insert_all!([
|
209
|
-
# { id: 1, title: "Rework", author: "David" },
|
210
|
-
# { id: 1, title: "Eloquent Ruby", author: "Russ" }
|
211
|
-
# ])
|
212
|
-
def insert_all!(attributes, returning: nil, record_timestamps: nil)
|
213
|
-
InsertAll.new(self, attributes, on_duplicate: :raise, returning: returning, record_timestamps: record_timestamps).execute
|
214
|
-
end
|
215
|
-
|
216
|
-
# Updates or inserts (upserts) a single record into the database in a
|
217
|
-
# single SQL INSERT statement. It does not instantiate any models nor does
|
218
|
-
# it trigger Active Record callbacks or validations. Though passed values
|
219
|
-
# go through Active Record's type casting and serialization.
|
220
|
-
#
|
221
|
-
# See #upsert_all for documentation.
|
222
|
-
def upsert(attributes, on_duplicate: :update, returning: nil, unique_by: nil, record_timestamps: nil)
|
223
|
-
upsert_all([ attributes ], on_duplicate: on_duplicate, returning: returning, unique_by: unique_by, record_timestamps: record_timestamps)
|
224
|
-
end
|
225
|
-
|
226
|
-
# Updates or inserts (upserts) multiple records into the database in a
|
227
|
-
# single SQL INSERT statement. It does not instantiate any models nor does
|
228
|
-
# it trigger Active Record callbacks or validations. Though passed values
|
229
|
-
# go through Active Record's type casting and serialization.
|
230
|
-
#
|
231
|
-
# The +attributes+ parameter is an Array of Hashes. Every Hash determines
|
232
|
-
# the attributes for a single row and must have the same keys.
|
233
|
-
#
|
234
|
-
# Returns an ActiveRecord::Result with its contents based on
|
235
|
-
# <tt>:returning</tt> (see below).
|
236
|
-
#
|
237
|
-
# By default, +upsert_all+ will update all the columns that can be updated when
|
238
|
-
# there is a conflict. These are all the columns except primary keys, read-only
|
239
|
-
# columns, and columns covered by the optional +unique_by+.
|
240
|
-
#
|
241
|
-
# ==== Options
|
242
|
-
#
|
243
|
-
# [:returning]
|
244
|
-
# (PostgreSQL only) An array of attributes to return for all successfully
|
245
|
-
# inserted records, which by default is the primary key.
|
246
|
-
# Pass <tt>returning: %w[ id name ]</tt> for both id and name
|
247
|
-
# or <tt>returning: false</tt> to omit the underlying <tt>RETURNING</tt> SQL
|
248
|
-
# clause entirely.
|
249
|
-
#
|
250
|
-
# You can also pass an SQL string if you need more control on the return values
|
251
|
-
# (for example, <tt>returning: "id, name as new_name"</tt>).
|
252
|
-
#
|
253
|
-
# [:unique_by]
|
254
|
-
# (PostgreSQL and SQLite only) By default rows are considered to be unique
|
255
|
-
# by every unique index on the table. Any duplicate rows are skipped.
|
256
|
-
#
|
257
|
-
# To skip rows according to just one unique index pass <tt>:unique_by</tt>.
|
258
|
-
#
|
259
|
-
# Consider a Book model where no duplicate ISBNs make sense, but if any
|
260
|
-
# row has an existing id, or is not unique by another unique index,
|
261
|
-
# <tt>ActiveRecord::RecordNotUnique</tt> is raised.
|
262
|
-
#
|
263
|
-
# Unique indexes can be identified by columns or name:
|
264
|
-
#
|
265
|
-
# unique_by: :isbn
|
266
|
-
# unique_by: %i[ author_id name ]
|
267
|
-
# unique_by: :index_books_on_isbn
|
268
|
-
#
|
269
|
-
# Because it relies on the index information from the database
|
270
|
-
# <tt>:unique_by</tt> is recommended to be paired with
|
271
|
-
# Active Record's schema_cache.
|
272
|
-
#
|
273
|
-
# [:on_duplicate]
|
274
|
-
# Configure the SQL update sentence that will be used in case of conflict.
|
275
|
-
#
|
276
|
-
# NOTE: If you use this option you must provide all the columns you want to update
|
277
|
-
# by yourself.
|
278
|
-
#
|
279
|
-
# Example:
|
280
|
-
#
|
281
|
-
# Commodity.upsert_all(
|
282
|
-
# [
|
283
|
-
# { id: 2, name: "Copper", price: 4.84 },
|
284
|
-
# { id: 4, name: "Gold", price: 1380.87 },
|
285
|
-
# { id: 6, name: "Aluminium", price: 0.35 }
|
286
|
-
# ],
|
287
|
-
# on_duplicate: Arel.sql("price = GREATEST(commodities.price, EXCLUDED.price)")
|
288
|
-
# )
|
289
|
-
#
|
290
|
-
# See the related +:update_only+ option. Both options can't be used at the same time.
|
291
|
-
#
|
292
|
-
# [:update_only]
|
293
|
-
# Provide a list of column names that will be updated in case of conflict. If not provided,
|
294
|
-
# +upsert_all+ will update all the columns that can be updated. These are all the columns
|
295
|
-
# except primary keys, read-only columns, and columns covered by the optional +unique_by+
|
296
|
-
#
|
297
|
-
# Example:
|
298
|
-
#
|
299
|
-
# Commodity.upsert_all(
|
300
|
-
# [
|
301
|
-
# { id: 2, name: "Copper", price: 4.84 },
|
302
|
-
# { id: 4, name: "Gold", price: 1380.87 },
|
303
|
-
# { id: 6, name: "Aluminium", price: 0.35 }
|
304
|
-
# ],
|
305
|
-
# update_only: [:price] # Only prices will be updated
|
306
|
-
# )
|
307
|
-
#
|
308
|
-
# See the related +:on_duplicate+ option. Both options can't be used at the same time.
|
309
|
-
#
|
310
|
-
# [:record_timestamps]
|
311
|
-
# By default, automatic setting of timestamp columns is controlled by
|
312
|
-
# the model's <tt>record_timestamps</tt> config, matching typical
|
313
|
-
# behavior.
|
314
|
-
#
|
315
|
-
# To override this and force automatic setting of timestamp columns one
|
316
|
-
# way or the other, pass <tt>:record_timestamps</tt>:
|
317
|
-
#
|
318
|
-
# record_timestamps: true # Always set timestamps automatically
|
319
|
-
# record_timestamps: false # Never set timestamps automatically
|
63
|
+
# The +attributes+ parameter can be either a Hash or an Array of Hashes. These Hashes describe the
|
64
|
+
# attributes on the objects that are to be built.
|
320
65
|
#
|
321
66
|
# ==== Examples
|
67
|
+
# # Build a single new object
|
68
|
+
# User.build(first_name: 'Jamie')
|
322
69
|
#
|
323
|
-
# #
|
324
|
-
#
|
70
|
+
# # Build an Array of new objects
|
71
|
+
# User.build([{ first_name: 'Jamie' }, { first_name: 'Jeremy' }])
|
325
72
|
#
|
326
|
-
#
|
327
|
-
#
|
328
|
-
#
|
329
|
-
#
|
73
|
+
# # Build a single object and pass it into a block to set other attributes.
|
74
|
+
# User.build(first_name: 'Jamie') do |u|
|
75
|
+
# u.is_admin = false
|
76
|
+
# end
|
330
77
|
#
|
331
|
-
#
|
332
|
-
|
333
|
-
|
78
|
+
# # Building an Array of new objects using a block, where the block is executed for each object:
|
79
|
+
# User.build([{ first_name: 'Jamie' }, { first_name: 'Jeremy' }]) do |u|
|
80
|
+
# u.is_admin = false
|
81
|
+
# end
|
82
|
+
def build(attributes = nil, &block)
|
83
|
+
if attributes.is_a?(Array)
|
84
|
+
attributes.collect { |attr| build(attr, &block) }
|
85
|
+
else
|
86
|
+
new(attributes, &block)
|
87
|
+
end
|
334
88
|
end
|
335
89
|
|
336
90
|
# Given an attributes hash, +instantiate+ returns a new instance of
|
@@ -425,56 +179,63 @@ module ActiveRecord
|
|
425
179
|
end
|
426
180
|
end
|
427
181
|
|
428
|
-
#
|
429
|
-
#
|
430
|
-
# less efficient than #delete but allows cleanup methods and other actions to be run.
|
182
|
+
# Accepts a list of attribute names to be used in the WHERE clause
|
183
|
+
# of SELECT / UPDATE / DELETE queries and in the ORDER BY clause for +#first+ and +#last+ finder methods.
|
431
184
|
#
|
432
|
-
#
|
433
|
-
#
|
185
|
+
# class Developer < ActiveRecord::Base
|
186
|
+
# query_constraints :company_id, :id
|
187
|
+
# end
|
434
188
|
#
|
435
|
-
#
|
189
|
+
# developer = Developer.first
|
190
|
+
# # SELECT "developers".* FROM "developers" ORDER BY "developers"."company_id" ASC, "developers"."id" ASC LIMIT 1
|
191
|
+
# developer.inspect # => #<Developer id: 1, company_id: 1, ...>
|
436
192
|
#
|
437
|
-
#
|
193
|
+
# developer.update!(name: "Nikita")
|
194
|
+
# # UPDATE "developers" SET "name" = 'Nikita' WHERE "developers"."company_id" = 1 AND "developers"."id" = 1
|
438
195
|
#
|
439
|
-
#
|
196
|
+
# # It is possible to update an attribute used in the query_constraints clause:
|
197
|
+
# developer.update!(company_id: 2)
|
198
|
+
# # UPDATE "developers" SET "company_id" = 2 WHERE "developers"."company_id" = 1 AND "developers"."id" = 1
|
440
199
|
#
|
441
|
-
#
|
442
|
-
#
|
200
|
+
# developer.name = "Bob"
|
201
|
+
# developer.save!
|
202
|
+
# # UPDATE "developers" SET "name" = 'Bob' WHERE "developers"."company_id" = 1 AND "developers"."id" = 1
|
443
203
|
#
|
444
|
-
#
|
445
|
-
#
|
446
|
-
#
|
447
|
-
|
448
|
-
|
449
|
-
|
204
|
+
# developer.destroy!
|
205
|
+
# # DELETE FROM "developers" WHERE "developers"."company_id" = 1 AND "developers"."id" = 1
|
206
|
+
#
|
207
|
+
# developer.delete
|
208
|
+
# # DELETE FROM "developers" WHERE "developers"."company_id" = 1 AND "developers"."id" = 1
|
209
|
+
#
|
210
|
+
# developer.reload
|
211
|
+
# # SELECT "developers".* FROM "developers" WHERE "developers"."company_id" = 1 AND "developers"."id" = 1 LIMIT 1
|
212
|
+
def query_constraints(*columns_list)
|
213
|
+
raise ArgumentError, "You must specify at least one column to be used in querying" if columns_list.empty?
|
214
|
+
|
215
|
+
@query_constraints_list = columns_list.map(&:to_s)
|
216
|
+
@has_query_constraints = @query_constraints_list
|
217
|
+
end
|
218
|
+
|
219
|
+
def has_query_constraints? # :nodoc:
|
220
|
+
@has_query_constraints
|
221
|
+
end
|
222
|
+
|
223
|
+
def query_constraints_list # :nodoc:
|
224
|
+
@query_constraints_list ||= if base_class? || primary_key != base_class.primary_key
|
225
|
+
primary_key if primary_key.is_a?(Array)
|
450
226
|
else
|
451
|
-
|
227
|
+
base_class.query_constraints_list
|
452
228
|
end
|
453
229
|
end
|
454
230
|
|
455
|
-
#
|
456
|
-
#
|
457
|
-
#
|
458
|
-
|
459
|
-
|
460
|
-
# You can delete multiple rows at once by passing an Array of <tt>id</tt>s.
|
461
|
-
#
|
462
|
-
# Note: Although it is often much faster than the alternative, #destroy,
|
463
|
-
# skipping callbacks might bypass business logic in your application
|
464
|
-
# that ensures referential integrity or performs other essential jobs.
|
465
|
-
#
|
466
|
-
# ==== Examples
|
467
|
-
#
|
468
|
-
# # Delete a single row
|
469
|
-
# Todo.delete(1)
|
470
|
-
#
|
471
|
-
# # Delete multiple rows
|
472
|
-
# Todo.delete([2,3,4])
|
473
|
-
def delete(id_or_array)
|
474
|
-
delete_by(primary_key => id_or_array)
|
231
|
+
# Returns an array of column names to be used in queries. The source of column
|
232
|
+
# names is derived from +query_constraints_list+ or +primary_key+. This method
|
233
|
+
# is for internal use when the primary key is to be treated as an array.
|
234
|
+
def composite_query_constraints_list # :nodoc:
|
235
|
+
@composite_query_constraints_list ||= query_constraints_list || Array(primary_key)
|
475
236
|
end
|
476
237
|
|
477
|
-
def _insert_record(values) # :nodoc:
|
238
|
+
def _insert_record(connection, values, returning) # :nodoc:
|
478
239
|
primary_key = self.primary_key
|
479
240
|
primary_key_value = nil
|
480
241
|
|
@@ -487,13 +248,18 @@ module ActiveRecord
|
|
487
248
|
|
488
249
|
im = Arel::InsertManager.new(arel_table)
|
489
250
|
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
251
|
+
with_connection do |c|
|
252
|
+
if values.empty?
|
253
|
+
im.insert(connection.empty_insert_statement_value(primary_key))
|
254
|
+
else
|
255
|
+
im.insert(values.transform_keys { |name| arel_table[name] })
|
256
|
+
end
|
495
257
|
|
496
|
-
|
258
|
+
connection.insert(
|
259
|
+
im, "#{self} Create", primary_key || false, primary_key_value,
|
260
|
+
returning: returning
|
261
|
+
)
|
262
|
+
end
|
497
263
|
end
|
498
264
|
|
499
265
|
def _update_record(values, constraints) # :nodoc:
|
@@ -510,7 +276,9 @@ module ActiveRecord
|
|
510
276
|
um.set(values.transform_keys { |name| arel_table[name] })
|
511
277
|
um.wheres = constraints
|
512
278
|
|
513
|
-
|
279
|
+
with_connection do |c|
|
280
|
+
c.update(um, "#{self} Update")
|
281
|
+
end
|
514
282
|
end
|
515
283
|
|
516
284
|
def _delete_record(constraints) # :nodoc:
|
@@ -526,10 +294,20 @@ module ActiveRecord
|
|
526
294
|
dm = Arel::DeleteManager.new(arel_table)
|
527
295
|
dm.wheres = constraints
|
528
296
|
|
529
|
-
|
297
|
+
with_connection do |c|
|
298
|
+
c.delete(dm, "#{self} Destroy")
|
299
|
+
end
|
530
300
|
end
|
531
301
|
|
532
302
|
private
|
303
|
+
def inherited(subclass)
|
304
|
+
super
|
305
|
+
subclass.class_eval do
|
306
|
+
@_query_constraints_list = nil
|
307
|
+
@has_query_constraints = false
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
533
311
|
# Given a class, an attributes hash, +instantiate_instance_of+ returns a
|
534
312
|
# new instance of the class. Accepts only keys as strings.
|
535
313
|
def instantiate_instance_of(klass, attributes, column_types = {}, &block)
|
@@ -677,11 +455,7 @@ module ActiveRecord
|
|
677
455
|
def destroy
|
678
456
|
_raise_readonly_record_error if readonly?
|
679
457
|
destroy_associations
|
680
|
-
@_trigger_destroy_callback
|
681
|
-
destroy_row > 0
|
682
|
-
else
|
683
|
-
true
|
684
|
-
end
|
458
|
+
@_trigger_destroy_callback ||= persisted? && destroy_row > 0
|
685
459
|
@destroyed = true
|
686
460
|
@previously_new_record = false
|
687
461
|
freeze
|
@@ -709,11 +483,14 @@ module ActiveRecord
|
|
709
483
|
# Note: The new instance will share a link to the same attributes as the original class.
|
710
484
|
# Therefore the STI column value will still be the same.
|
711
485
|
# Any change to the attributes on either instance will affect both instances.
|
486
|
+
# This includes any attribute initialization done by the new instance.
|
487
|
+
#
|
712
488
|
# If you want to change the STI column as well, use #becomes! instead.
|
713
489
|
def becomes(klass)
|
714
490
|
became = klass.allocate
|
715
491
|
|
716
492
|
became.send(:initialize) do |becoming|
|
493
|
+
@attributes.reverse_merge!(becoming.instance_variable_get(:@attributes))
|
717
494
|
becoming.instance_variable_set(:@attributes, @attributes)
|
718
495
|
becoming.instance_variable_set(:@mutations_from_database, @mutations_from_database ||= nil)
|
719
496
|
becoming.instance_variable_set(:@new_record, new_record?)
|
@@ -748,7 +525,7 @@ module ActiveRecord
|
|
748
525
|
# * updated_at/updated_on column is updated if that column is available.
|
749
526
|
# * Updates all the attributes that are dirty in this object.
|
750
527
|
#
|
751
|
-
# This method raises an ActiveRecord::ActiveRecordError
|
528
|
+
# This method raises an ActiveRecord::ActiveRecordError if the
|
752
529
|
# attribute is marked as readonly.
|
753
530
|
#
|
754
531
|
# Also see #update_column.
|
@@ -760,6 +537,28 @@ module ActiveRecord
|
|
760
537
|
save(validate: false)
|
761
538
|
end
|
762
539
|
|
540
|
+
# Updates a single attribute and saves the record.
|
541
|
+
# This is especially useful for boolean flags on existing records. Also note that
|
542
|
+
#
|
543
|
+
# * Validation is skipped.
|
544
|
+
# * \Callbacks are invoked.
|
545
|
+
# * updated_at/updated_on column is updated if that column is available.
|
546
|
+
# * Updates all the attributes that are dirty in this object.
|
547
|
+
#
|
548
|
+
# This method raises an ActiveRecord::ActiveRecordError if the
|
549
|
+
# attribute is marked as readonly.
|
550
|
+
#
|
551
|
+
# If any of the <tt>before_*</tt> callbacks throws +:abort+ the action is cancelled
|
552
|
+
# and #update_attribute! raises ActiveRecord::RecordNotSaved. See
|
553
|
+
# ActiveRecord::Callbacks for further details.
|
554
|
+
def update_attribute!(name, value)
|
555
|
+
name = name.to_s
|
556
|
+
verify_readonly_attribute(name)
|
557
|
+
public_send("#{name}=", value)
|
558
|
+
|
559
|
+
save!(validate: false)
|
560
|
+
end
|
561
|
+
|
763
562
|
# Updates the attributes of the model from the passed-in hash and saves the
|
764
563
|
# record, all wrapped in a transaction. If the object is invalid, the saving
|
765
564
|
# will fail and false will be returned.
|
@@ -943,15 +742,16 @@ module ActiveRecord
|
|
943
742
|
# end
|
944
743
|
#
|
945
744
|
def reload(options = nil)
|
946
|
-
self.class.
|
745
|
+
self.class.connection_pool.clear_query_cache
|
947
746
|
|
948
747
|
fresh_object = if apply_scoping?(options)
|
949
|
-
_find_record(options)
|
748
|
+
_find_record((options || {}).merge(all_queries: true))
|
950
749
|
else
|
951
750
|
self.class.unscoped { _find_record(options) }
|
952
751
|
end
|
953
752
|
|
954
753
|
@association_cache = fresh_object.instance_variable_get(:@association_cache)
|
754
|
+
@association_cache.each_value { |association| association.owner = self }
|
955
755
|
@attributes = fresh_object.instance_variable_get(:@attributes)
|
956
756
|
@new_record = false
|
957
757
|
@previously_new_record = false
|
@@ -997,10 +797,12 @@ module ActiveRecord
|
|
997
797
|
_raise_readonly_record_error if readonly?
|
998
798
|
|
999
799
|
attribute_names = timestamp_attributes_for_update_in_model
|
1000
|
-
attribute_names
|
800
|
+
attribute_names = (attribute_names | names).map! do |name|
|
1001
801
|
name = name.to_s
|
1002
|
-
self.class.attribute_aliases[name] || name
|
1003
|
-
|
802
|
+
name = self.class.attribute_aliases[name] || name
|
803
|
+
verify_readonly_attribute(name)
|
804
|
+
name
|
805
|
+
end
|
1004
806
|
|
1005
807
|
unless attribute_names.empty?
|
1006
808
|
affected_rows = _touch_row(attribute_names, time)
|
@@ -1011,6 +813,12 @@ module ActiveRecord
|
|
1011
813
|
end
|
1012
814
|
|
1013
815
|
private
|
816
|
+
def init_internals
|
817
|
+
super
|
818
|
+
@_trigger_destroy_callback = @_trigger_update_callback = nil
|
819
|
+
@previously_new_record = false
|
820
|
+
end
|
821
|
+
|
1014
822
|
def strict_loaded_associations
|
1015
823
|
@association_cache.find_all do |_, assoc|
|
1016
824
|
assoc.owner.strict_loading? && !assoc.owner.strict_loading_n_plus_one_only?
|
@@ -1018,10 +826,23 @@ module ActiveRecord
|
|
1018
826
|
end
|
1019
827
|
|
1020
828
|
def _find_record(options)
|
829
|
+
all_queries = options ? options[:all_queries] : nil
|
830
|
+
base = self.class.all(all_queries: all_queries).preload(strict_loaded_associations)
|
831
|
+
|
1021
832
|
if options && options[:lock]
|
1022
|
-
|
833
|
+
base.lock(options[:lock]).find_by!(_in_memory_query_constraints_hash)
|
834
|
+
else
|
835
|
+
base.find_by!(_in_memory_query_constraints_hash)
|
836
|
+
end
|
837
|
+
end
|
838
|
+
|
839
|
+
def _in_memory_query_constraints_hash
|
840
|
+
if self.class.query_constraints_list.nil?
|
841
|
+
{ @primary_key => id }
|
1023
842
|
else
|
1024
|
-
self.class.
|
843
|
+
self.class.query_constraints_list.index_with do |column_name|
|
844
|
+
attribute(column_name)
|
845
|
+
end
|
1025
846
|
end
|
1026
847
|
end
|
1027
848
|
|
@@ -1031,7 +852,13 @@ module ActiveRecord
|
|
1031
852
|
end
|
1032
853
|
|
1033
854
|
def _query_constraints_hash
|
1034
|
-
|
855
|
+
if self.class.query_constraints_list.nil?
|
856
|
+
{ @primary_key => id_in_database }
|
857
|
+
else
|
858
|
+
self.class.query_constraints_list.index_with do |column_name|
|
859
|
+
attribute_in_database(column_name)
|
860
|
+
end
|
861
|
+
end
|
1035
862
|
end
|
1036
863
|
|
1037
864
|
# A hook to be overridden by association modules.
|
@@ -1095,11 +922,19 @@ module ActiveRecord
|
|
1095
922
|
def _create_record(attribute_names = self.attribute_names)
|
1096
923
|
attribute_names = attributes_for_create(attribute_names)
|
1097
924
|
|
1098
|
-
|
1099
|
-
|
1100
|
-
)
|
925
|
+
self.class.with_connection do |connection|
|
926
|
+
returning_columns = self.class._returning_columns_for_insert(connection)
|
1101
927
|
|
1102
|
-
|
928
|
+
returning_values = self.class._insert_record(
|
929
|
+
connection,
|
930
|
+
attributes_with_values(attribute_names),
|
931
|
+
returning_columns
|
932
|
+
)
|
933
|
+
|
934
|
+
returning_columns.zip(returning_values).each do |column, value|
|
935
|
+
_write_attribute(column, value) if !_read_attribute(column)
|
936
|
+
end if returning_values
|
937
|
+
end
|
1103
938
|
|
1104
939
|
@new_record = false
|
1105
940
|
@previously_new_record = true
|
@@ -1116,7 +951,7 @@ module ActiveRecord
|
|
1116
951
|
def _raise_record_not_destroyed
|
1117
952
|
@_association_destroy_exception ||= nil
|
1118
953
|
key = self.class.primary_key
|
1119
|
-
raise @_association_destroy_exception || RecordNotDestroyed.new("Failed to destroy #{self.class} with #{key}=#{
|
954
|
+
raise @_association_destroy_exception || RecordNotDestroyed.new("Failed to destroy #{self.class} with #{key}=#{id}", self)
|
1120
955
|
ensure
|
1121
956
|
@_association_destroy_exception = nil
|
1122
957
|
end
|
@@ -1131,11 +966,5 @@ module ActiveRecord
|
|
1131
966
|
persisted?, new_record?, or destroyed? before touching.
|
1132
967
|
MSG
|
1133
968
|
end
|
1134
|
-
|
1135
|
-
# The name of the method used to touch a +belongs_to+ association when the
|
1136
|
-
# +:touch+ option is used.
|
1137
|
-
def belongs_to_touch_method
|
1138
|
-
:touch
|
1139
|
-
end
|
1140
969
|
end
|
1141
970
|
end
|