activerecord 6.1.7 → 7.1.5
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 +2030 -1020
- data/MIT-LICENSE +1 -1
- data/README.rdoc +18 -18
- data/lib/active_record/aggregations.rb +17 -14
- data/lib/active_record/association_relation.rb +1 -11
- data/lib/active_record/associations/association.rb +51 -19
- data/lib/active_record/associations/association_scope.rb +17 -12
- data/lib/active_record/associations/belongs_to_association.rb +28 -9
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +10 -2
- data/lib/active_record/associations/builder/association.rb +11 -5
- data/lib/active_record/associations/builder/belongs_to.rb +40 -14
- data/lib/active_record/associations/builder/collection_association.rb +10 -3
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -5
- data/lib/active_record/associations/builder/has_many.rb +3 -2
- data/lib/active_record/associations/builder/has_one.rb +2 -1
- data/lib/active_record/associations/builder/singular_association.rb +6 -2
- data/lib/active_record/associations/collection_association.rb +39 -35
- data/lib/active_record/associations/collection_proxy.rb +30 -15
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/foreign_association.rb +10 -3
- data/lib/active_record/associations/has_many_association.rb +28 -18
- 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 +3 -2
- data/lib/active_record/associations/join_dependency.rb +28 -20
- data/lib/active_record/associations/preloader/association.rb +210 -52
- data/lib/active_record/associations/preloader/batch.rb +48 -0
- data/lib/active_record/associations/preloader/branch.rb +147 -0
- data/lib/active_record/associations/preloader/through_association.rb +50 -14
- data/lib/active_record/associations/preloader.rb +50 -121
- data/lib/active_record/associations/singular_association.rb +9 -3
- data/lib/active_record/associations/through_association.rb +25 -14
- data/lib/active_record/associations.rb +446 -306
- data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
- data/lib/active_record/attribute_assignment.rb +1 -3
- data/lib/active_record/attribute_methods/before_type_cast.rb +24 -2
- data/lib/active_record/attribute_methods/dirty.rb +73 -22
- data/lib/active_record/attribute_methods/primary_key.rb +78 -26
- data/lib/active_record/attribute_methods/query.rb +31 -19
- data/lib/active_record/attribute_methods/read.rb +27 -12
- data/lib/active_record/attribute_methods/serialization.rb +194 -37
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +8 -3
- data/lib/active_record/attribute_methods/write.rb +12 -15
- data/lib/active_record/attribute_methods.rb +161 -40
- data/lib/active_record/attributes.rb +27 -38
- data/lib/active_record/autosave_association.rb +65 -31
- data/lib/active_record/base.rb +25 -2
- 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 +367 -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 +78 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +113 -597
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -17
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +172 -50
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +78 -27
- data/lib/active_record/connection_adapters/abstract/quoting.rb +87 -73
- 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 +367 -141
- data/lib/active_record/connection_adapters/abstract/transaction.rb +281 -59
- data/lib/active_record/connection_adapters/abstract_adapter.rb +631 -150
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +317 -164
- 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 +25 -134
- data/lib/active_record/connection_adapters/mysql/quoting.rb +56 -25
- 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 +39 -14
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +151 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +112 -55
- data/lib/active_record/connection_adapters/pool_config.rb +20 -11
- 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 +89 -52
- 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/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.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +89 -56
- 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 +153 -3
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +397 -75
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +508 -246
- data/lib/active_record/connection_adapters/schema_cache.rb +319 -90
- data/lib/active_record/connection_adapters/sqlite3/column.rb +49 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +72 -53
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +37 -21
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +7 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +43 -22
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +296 -104
- 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 +258 -0
- data/lib/active_record/connection_adapters.rb +9 -6
- data/lib/active_record/connection_handling.rb +108 -137
- data/lib/active_record/core.rb +242 -233
- data/lib/active_record/counter_cache.rb +52 -27
- data/lib/active_record/database_configurations/connection_url_resolver.rb +3 -2
- data/lib/active_record/database_configurations/database_config.rb +21 -12
- data/lib/active_record/database_configurations/hash_config.rb +88 -16
- data/lib/active_record/database_configurations/url_config.rb +18 -12
- data/lib/active_record/database_configurations.rb +95 -59
- data/lib/active_record/delegated_type.rb +66 -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 +1 -1
- 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 +155 -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 +155 -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_serializer.rb +92 -0
- data/lib/active_record/encryption/null_encryptor.rb +21 -0
- data/lib/active_record/encryption/properties.rb +76 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
- data/lib/active_record/encryption/scheme.rb +100 -0
- data/lib/active_record/encryption.rb +58 -0
- data/lib/active_record/enum.rb +154 -63
- data/lib/active_record/errors.rb +172 -15
- data/lib/active_record/explain.rb +23 -3
- 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 +147 -86
- data/lib/active_record/future_result.rb +174 -0
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +81 -29
- data/lib/active_record/insert_all.rb +135 -22
- data/lib/active_record/integration.rb +11 -10
- data/lib/active_record/internal_metadata.rb +119 -33
- data/lib/active_record/legacy_yaml_adapter.rb +2 -39
- data/lib/active_record/locking/optimistic.rb +37 -22
- data/lib/active_record/locking/pessimistic.rb +15 -6
- data/lib/active_record/log_subscriber.rb +52 -19
- 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 +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 +112 -14
- data/lib/active_record/migration/compatibility.rb +233 -46
- data/lib/active_record/migration/default_strategy.rb +23 -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 +361 -173
- data/lib/active_record/model_schema.rb +125 -101
- data/lib/active_record/nested_attributes.rb +50 -20
- data/lib/active_record/no_touching.rb +3 -3
- data/lib/active_record/normalization.rb +167 -0
- data/lib/active_record/persistence.rb +409 -88
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +4 -22
- data/lib/active_record/query_logs.rb +174 -0
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +29 -6
- data/lib/active_record/railtie.rb +220 -44
- data/lib/active_record/railties/controller_runtime.rb +15 -10
- data/lib/active_record/railties/databases.rake +188 -252
- 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 +248 -81
- data/lib/active_record/relation/batches/batch_enumerator.rb +23 -7
- data/lib/active_record/relation/batches.rb +192 -63
- data/lib/active_record/relation/calculations.rb +246 -90
- data/lib/active_record/relation/delegation.rb +28 -14
- data/lib/active_record/relation/finder_methods.rb +108 -51
- data/lib/active_record/relation/merger.rb +22 -13
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +31 -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 +27 -20
- data/lib/active_record/relation/query_attribute.rb +30 -12
- data/lib/active_record/relation/query_methods.rb +670 -129
- data/lib/active_record/relation/record_fetch_warning.rb +7 -9
- data/lib/active_record/relation/spawn_methods.rb +20 -3
- data/lib/active_record/relation/where_clause.rb +10 -19
- data/lib/active_record/relation.rb +287 -120
- data/lib/active_record/result.rb +37 -11
- data/lib/active_record/runtime_registry.rb +32 -13
- data/lib/active_record/sanitization.rb +65 -20
- data/lib/active_record/schema.rb +36 -22
- data/lib/active_record/schema_dumper.rb +73 -24
- data/lib/active_record/schema_migration.rb +68 -33
- 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 +10 -8
- data/lib/active_record/store.rb +10 -10
- data/lib/active_record/suppressor.rb +13 -15
- data/lib/active_record/table_metadata.rb +16 -3
- data/lib/active_record/tasks/database_tasks.rb +251 -140
- 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 +15 -7
- data/lib/active_record/test_databases.rb +1 -1
- data/lib/active_record/test_fixtures.rb +117 -96
- data/lib/active_record/timestamp.rb +32 -19
- data/lib/active_record/token_for.rb +113 -0
- data/lib/active_record/touch_later.rb +11 -6
- data/lib/active_record/transactions.rb +48 -27
- data/lib/active_record/translation.rb +3 -3
- 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 -5
- 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/validations/absence.rb +1 -1
- data/lib/active_record/validations/associated.rb +4 -4
- 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 +51 -6
- data/lib/active_record/validations.rb +8 -4
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +335 -32
- data/lib/arel/attributes/attribute.rb +0 -8
- 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/and.rb +4 -0
- data/lib/arel/nodes/binary.rb +6 -1
- data/lib/arel/nodes/bound_sql_literal.rb +61 -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/node.rb +111 -2
- 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 +6 -0
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes/update_statement.rb +8 -3
- data/lib/arel/nodes.rb +5 -0
- data/lib/arel/predications.rb +13 -3
- data/lib/arel/select_manager.rb +10 -4
- data/lib/arel/table.rb +9 -6
- data/lib/arel/tree_manager.rb +5 -13
- data/lib/arel/update_manager.rb +18 -4
- data/lib/arel/visitors/dot.rb +80 -90
- data/lib/arel/visitors/mysql.rb +16 -3
- data/lib/arel/visitors/postgresql.rb +0 -10
- data/lib/arel/visitors/to_sql.rb +141 -20
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel.rb +18 -3
- 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.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 +96 -16
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
- data/lib/active_record/null_relation.rb +0 -67
@@ -6,6 +6,13 @@ module ActiveRecord
|
|
6
6
|
module ModelSchema
|
7
7
|
extend ActiveSupport::Concern
|
8
8
|
|
9
|
+
##
|
10
|
+
# :method: id_value
|
11
|
+
# :call-seq: id_value
|
12
|
+
#
|
13
|
+
# Returns the underlying column value for a column named "id". Useful when defining
|
14
|
+
# a composite primary key including an "id" column so that the value is readable.
|
15
|
+
|
9
16
|
##
|
10
17
|
# :singleton-method: primary_key_prefix_type
|
11
18
|
# :call-seq: primary_key_prefix_type
|
@@ -126,9 +133,29 @@ module ActiveRecord
|
|
126
133
|
# +:immutable_string+. This setting does not affect the behavior of
|
127
134
|
# <tt>attribute :foo, :string</tt>. Defaults to false.
|
128
135
|
|
129
|
-
|
130
|
-
|
136
|
+
##
|
137
|
+
# :singleton-method: inheritance_column
|
138
|
+
# :call-seq: inheritance_column
|
139
|
+
#
|
140
|
+
# The name of the table column which stores the class name on single-table
|
141
|
+
# inheritance situations.
|
142
|
+
#
|
143
|
+
# The default inheritance column name is +type+, which means it's a
|
144
|
+
# reserved word inside Active Record. To be able to use single-table
|
145
|
+
# inheritance with another column name, or to use the column +type+ in
|
146
|
+
# your own model for something else, you can set +inheritance_column+:
|
147
|
+
#
|
148
|
+
# self.inheritance_column = 'zoink'
|
149
|
+
|
150
|
+
##
|
151
|
+
# :singleton-method: inheritance_column=
|
152
|
+
# :call-seq: inheritance_column=(column)
|
153
|
+
#
|
154
|
+
# Defines the name of the table column which will store the class name on single-table
|
155
|
+
# inheritance situations.
|
131
156
|
|
157
|
+
included do
|
158
|
+
class_attribute :primary_key_prefix_type, instance_writer: false
|
132
159
|
class_attribute :table_name_prefix, instance_writer: false, default: ""
|
133
160
|
class_attribute :table_name_suffix, instance_writer: false, default: ""
|
134
161
|
class_attribute :schema_migrations_table_name, instance_accessor: false, default: "schema_migrations"
|
@@ -137,8 +164,15 @@ module ActiveRecord
|
|
137
164
|
class_attribute :implicit_order_column, instance_accessor: false
|
138
165
|
class_attribute :immutable_strings_by_default, instance_accessor: false
|
139
166
|
|
167
|
+
class_attribute :inheritance_column, instance_accessor: false, default: "type"
|
168
|
+
singleton_class.class_eval do
|
169
|
+
alias_method :_inheritance_column=, :inheritance_column=
|
170
|
+
private :_inheritance_column=
|
171
|
+
alias_method :inheritance_column=, :real_inheritance_column=
|
172
|
+
end
|
173
|
+
|
140
174
|
self.protected_environments = ["production"]
|
141
|
-
|
175
|
+
|
142
176
|
self.ignored_columns = [].freeze
|
143
177
|
|
144
178
|
delegate :type_for_attribute, :column_for_attribute, to: :class
|
@@ -153,8 +187,9 @@ module ActiveRecord
|
|
153
187
|
# artists, records => artists_records
|
154
188
|
# records, artists => artists_records
|
155
189
|
# music_artists, music_records => music_artists_records
|
190
|
+
# music.artists, music.records => music.artists_records
|
156
191
|
def self.derive_join_table_name(first_table, second_table) # :nodoc:
|
157
|
-
[first_table.to_s, second_table.to_s].sort.join("\0").gsub(/^(.*_)(.+)\0\1(.+)/, '\1\2_\3').tr("\0", "_")
|
192
|
+
[first_table.to_s, second_table.to_s].sort.join("\0").gsub(/^(.*[_.])(.+)\0\1(.+)/, '\1\2_\3').tr("\0", "_")
|
158
193
|
end
|
159
194
|
|
160
195
|
module ClassMethods
|
@@ -197,6 +232,21 @@ module ActiveRecord
|
|
197
232
|
# the table name guess for an Invoice class becomes "myapp_invoices".
|
198
233
|
# Invoice::Lineitem becomes "myapp_invoice_lineitems".
|
199
234
|
#
|
235
|
+
# Active Model Naming's +model_name+ is the base name used to guess the
|
236
|
+
# table name. In case a custom Active Model Name is defined, it will be
|
237
|
+
# used for the table name as well:
|
238
|
+
#
|
239
|
+
# class PostRecord < ActiveRecord::Base
|
240
|
+
# class << self
|
241
|
+
# def model_name
|
242
|
+
# ActiveModel::Name.new(self, nil, "Post")
|
243
|
+
# end
|
244
|
+
# end
|
245
|
+
# end
|
246
|
+
#
|
247
|
+
# PostRecord.table_name
|
248
|
+
# # => "posts"
|
249
|
+
#
|
200
250
|
# You can also set your own table name explicitly:
|
201
251
|
#
|
202
252
|
# class Mouse < ActiveRecord::Base
|
@@ -233,9 +283,11 @@ module ActiveRecord
|
|
233
283
|
end
|
234
284
|
|
235
285
|
# Computes the table name, (re)sets it internally, and returns it.
|
236
|
-
def reset_table_name
|
237
|
-
self.table_name = if
|
238
|
-
|
286
|
+
def reset_table_name # :nodoc:
|
287
|
+
self.table_name = if self == Base
|
288
|
+
nil
|
289
|
+
elsif abstract_class?
|
290
|
+
superclass.table_name
|
239
291
|
elsif superclass.abstract_class?
|
240
292
|
superclass.table_name || compute_table_name
|
241
293
|
else
|
@@ -243,11 +295,11 @@ module ActiveRecord
|
|
243
295
|
end
|
244
296
|
end
|
245
297
|
|
246
|
-
def full_table_name_prefix
|
298
|
+
def full_table_name_prefix # :nodoc:
|
247
299
|
(module_parents.detect { |p| p.respond_to?(:table_name_prefix) } || self).table_name_prefix
|
248
300
|
end
|
249
301
|
|
250
|
-
def full_table_name_suffix
|
302
|
+
def full_table_name_suffix # :nodoc:
|
251
303
|
(module_parents.detect { |p| p.respond_to?(:table_name_suffix) } || self).table_name_suffix
|
252
304
|
end
|
253
305
|
|
@@ -266,33 +318,14 @@ module ActiveRecord
|
|
266
318
|
@protected_environments = environments.map(&:to_s)
|
267
319
|
end
|
268
320
|
|
269
|
-
|
270
|
-
|
271
|
-
#
|
272
|
-
# The default inheritance column name is +type+, which means it's a
|
273
|
-
# reserved word inside Active Record. To be able to use single-table
|
274
|
-
# inheritance with another column name, or to use the column +type+ in
|
275
|
-
# your own model for something else, you can set +inheritance_column+:
|
276
|
-
#
|
277
|
-
# self.inheritance_column = 'zoink'
|
278
|
-
def inheritance_column
|
279
|
-
(@inheritance_column ||= nil) || superclass.inheritance_column
|
280
|
-
end
|
281
|
-
|
282
|
-
# Sets the value of inheritance_column
|
283
|
-
def inheritance_column=(value)
|
284
|
-
@inheritance_column = value.to_s
|
285
|
-
@explicit_inheritance_column = true
|
321
|
+
def real_inheritance_column=(value) # :nodoc:
|
322
|
+
self._inheritance_column = value.to_s
|
286
323
|
end
|
287
324
|
|
288
325
|
# The list of columns names the model should ignore. Ignored columns won't have attribute
|
289
326
|
# accessors defined, and won't be referenced in SQL queries.
|
290
327
|
def ignored_columns
|
291
|
-
|
292
|
-
@ignored_columns
|
293
|
-
else
|
294
|
-
superclass.ignored_columns
|
295
|
-
end
|
328
|
+
@ignored_columns || superclass.ignored_columns
|
296
329
|
end
|
297
330
|
|
298
331
|
# Sets the columns names the model should ignore. Ignored columns won't have attribute
|
@@ -313,7 +346,7 @@ module ActiveRecord
|
|
313
346
|
# # name :string, limit: 255
|
314
347
|
# # category :string, limit: 255
|
315
348
|
#
|
316
|
-
# self.ignored_columns
|
349
|
+
# self.ignored_columns += [:category]
|
317
350
|
# end
|
318
351
|
#
|
319
352
|
# The schema still contains "category", but now the model omits it, so any meta-driven code or
|
@@ -339,7 +372,7 @@ module ActiveRecord
|
|
339
372
|
end
|
340
373
|
end
|
341
374
|
|
342
|
-
def reset_sequence_name
|
375
|
+
def reset_sequence_name # :nodoc:
|
343
376
|
@explicit_sequence_name = false
|
344
377
|
@sequence_name = connection.default_sequence_name(table_name, primary_key)
|
345
378
|
end
|
@@ -398,6 +431,16 @@ module ActiveRecord
|
|
398
431
|
@columns ||= columns_hash.values.freeze
|
399
432
|
end
|
400
433
|
|
434
|
+
def _returning_columns_for_insert # :nodoc:
|
435
|
+
@_returning_columns_for_insert ||= begin
|
436
|
+
auto_populated_columns = columns.filter_map do |c|
|
437
|
+
c.name if connection.return_value_after_insert?(c)
|
438
|
+
end
|
439
|
+
|
440
|
+
auto_populated_columns.empty? ? Array(primary_key) : auto_populated_columns
|
441
|
+
end
|
442
|
+
end
|
443
|
+
|
401
444
|
def attribute_types # :nodoc:
|
402
445
|
load_schema
|
403
446
|
@attribute_types ||= Hash.new(Type.default_value)
|
@@ -430,7 +473,7 @@ module ActiveRecord
|
|
430
473
|
end
|
431
474
|
|
432
475
|
# Returns the column object for the named attribute.
|
433
|
-
# Returns an
|
476
|
+
# Returns an ActiveRecord::ConnectionAdapters::NullColumn if the
|
434
477
|
# named attribute does not exist.
|
435
478
|
#
|
436
479
|
# class Person < ActiveRecord::Base
|
@@ -486,9 +529,9 @@ module ActiveRecord
|
|
486
529
|
#
|
487
530
|
# The most common usage pattern for this method is probably in a migration,
|
488
531
|
# when just after creating a table you want to populate it with some default
|
489
|
-
# values,
|
532
|
+
# values, e.g.:
|
490
533
|
#
|
491
|
-
# class CreateJobLevels < ActiveRecord::Migration[
|
534
|
+
# class CreateJobLevels < ActiveRecord::Migration[7.1]
|
492
535
|
# def up
|
493
536
|
# create_table :job_levels do |t|
|
494
537
|
# t.integer :id
|
@@ -516,35 +559,61 @@ module ActiveRecord
|
|
516
559
|
initialize_find_by_cache
|
517
560
|
end
|
518
561
|
|
562
|
+
def load_schema # :nodoc:
|
563
|
+
return if schema_loaded?
|
564
|
+
@load_schema_monitor.synchronize do
|
565
|
+
return if @columns_hash
|
566
|
+
|
567
|
+
load_schema!
|
568
|
+
|
569
|
+
@schema_loaded = true
|
570
|
+
rescue
|
571
|
+
reload_schema_from_cache # If the schema loading failed half way through, we must reset the state.
|
572
|
+
raise
|
573
|
+
end
|
574
|
+
end
|
575
|
+
|
519
576
|
protected
|
520
577
|
def initialize_load_schema_monitor
|
521
578
|
@load_schema_monitor = Monitor.new
|
522
579
|
end
|
523
580
|
|
581
|
+
def reload_schema_from_cache(recursive = true)
|
582
|
+
@_returning_columns_for_insert = nil
|
583
|
+
@arel_table = nil
|
584
|
+
@column_names = nil
|
585
|
+
@symbol_column_to_string_name_hash = nil
|
586
|
+
@attribute_types = nil
|
587
|
+
@content_columns = nil
|
588
|
+
@default_attributes = nil
|
589
|
+
@column_defaults = nil
|
590
|
+
@attributes_builder = nil
|
591
|
+
@columns = nil
|
592
|
+
@columns_hash = nil
|
593
|
+
@schema_loaded = false
|
594
|
+
@attribute_names = nil
|
595
|
+
@yaml_encoder = nil
|
596
|
+
if recursive
|
597
|
+
subclasses.each do |descendant|
|
598
|
+
descendant.send(:reload_schema_from_cache)
|
599
|
+
end
|
600
|
+
end
|
601
|
+
end
|
602
|
+
|
524
603
|
private
|
525
604
|
def inherited(child_class)
|
526
605
|
super
|
527
606
|
child_class.initialize_load_schema_monitor
|
607
|
+
child_class.reload_schema_from_cache(false)
|
608
|
+
child_class.class_eval do
|
609
|
+
@ignored_columns = nil
|
610
|
+
end
|
528
611
|
end
|
529
612
|
|
530
613
|
def schema_loaded?
|
531
614
|
defined?(@schema_loaded) && @schema_loaded
|
532
615
|
end
|
533
616
|
|
534
|
-
def load_schema
|
535
|
-
return if schema_loaded?
|
536
|
-
@load_schema_monitor.synchronize do
|
537
|
-
return if defined?(@columns_hash) && @columns_hash
|
538
|
-
|
539
|
-
load_schema!
|
540
|
-
|
541
|
-
@schema_loaded = true
|
542
|
-
rescue
|
543
|
-
reload_schema_from_cache # If the schema loading failed half way through, we must reset the state.
|
544
|
-
raise
|
545
|
-
end
|
546
|
-
end
|
547
|
-
|
548
617
|
def load_schema!
|
549
618
|
unless table_name
|
550
619
|
raise ActiveRecord::TableNotSpecified, "#{self} has no table configured. Set one with #{self}.table_name="
|
@@ -556,39 +625,20 @@ module ActiveRecord
|
|
556
625
|
@columns_hash.each do |name, column|
|
557
626
|
type = connection.lookup_cast_type_from_column(column)
|
558
627
|
type = _convert_type_from_options(type)
|
559
|
-
warn_if_deprecated_type(column)
|
560
628
|
define_attribute(
|
561
629
|
name,
|
562
630
|
type,
|
563
631
|
default: column.default,
|
564
632
|
user_provided_default: false
|
565
633
|
)
|
634
|
+
alias_attribute :id_value, :id if name == "id"
|
566
635
|
end
|
567
|
-
|
568
|
-
|
569
|
-
def reload_schema_from_cache
|
570
|
-
@arel_table = nil
|
571
|
-
@column_names = nil
|
572
|
-
@symbol_column_to_string_name_hash = nil
|
573
|
-
@attribute_types = nil
|
574
|
-
@content_columns = nil
|
575
|
-
@default_attributes = nil
|
576
|
-
@column_defaults = nil
|
577
|
-
@inheritance_column = nil unless defined?(@explicit_inheritance_column) && @explicit_inheritance_column
|
578
|
-
@attributes_builder = nil
|
579
|
-
@columns = nil
|
580
|
-
@columns_hash = nil
|
581
|
-
@schema_loaded = false
|
582
|
-
@attribute_names = nil
|
583
|
-
@yaml_encoder = nil
|
584
|
-
direct_descendants.each do |descendant|
|
585
|
-
descendant.send(:reload_schema_from_cache)
|
586
|
-
end
|
636
|
+
_default_attributes # Precompute to cache DB-dependent attribute types
|
587
637
|
end
|
588
638
|
|
589
639
|
# Guesses the table name, but does not decorate it with prefix and suffix information.
|
590
|
-
def undecorated_table_name(
|
591
|
-
table_name =
|
640
|
+
def undecorated_table_name(model_name)
|
641
|
+
table_name = model_name.to_s.demodulize.underscore
|
592
642
|
pluralize_table_names ? table_name.pluralize : table_name
|
593
643
|
end
|
594
644
|
|
@@ -602,9 +652,9 @@ module ActiveRecord
|
|
602
652
|
contained += "_"
|
603
653
|
end
|
604
654
|
|
605
|
-
"#{full_table_name_prefix}#{contained}#{undecorated_table_name(
|
655
|
+
"#{full_table_name_prefix}#{contained}#{undecorated_table_name(model_name)}#{full_table_name_suffix}"
|
606
656
|
else
|
607
|
-
# STI subclasses always use their superclass' table.
|
657
|
+
# STI subclasses always use their superclass's table.
|
608
658
|
base_class.table_name
|
609
659
|
end
|
610
660
|
end
|
@@ -616,32 +666,6 @@ module ActiveRecord
|
|
616
666
|
type
|
617
667
|
end
|
618
668
|
end
|
619
|
-
|
620
|
-
def warn_if_deprecated_type(column)
|
621
|
-
return if attributes_to_define_after_schema_loads.key?(column.name)
|
622
|
-
return unless column.respond_to?(:oid)
|
623
|
-
|
624
|
-
if column.array?
|
625
|
-
array_arguments = ", array: true"
|
626
|
-
else
|
627
|
-
array_arguments = ""
|
628
|
-
end
|
629
|
-
|
630
|
-
if column.sql_type.start_with?("interval")
|
631
|
-
precision_arguments = column.precision.presence && ", precision: #{column.precision}"
|
632
|
-
ActiveSupport::Deprecation.warn(<<~WARNING)
|
633
|
-
The behavior of the `:interval` type will be changing in Rails 7.0
|
634
|
-
to return an `ActiveSupport::Duration` object. If you'd like to keep
|
635
|
-
the old behavior, you can add this line to #{self.name} model:
|
636
|
-
|
637
|
-
attribute :#{column.name}, :string#{precision_arguments}#{array_arguments}
|
638
|
-
|
639
|
-
If you'd like the new behavior today, you can add this line:
|
640
|
-
|
641
|
-
attribute :#{column.name}, :interval#{precision_arguments}#{array_arguments}
|
642
|
-
WARNING
|
643
|
-
end
|
644
|
-
end
|
645
669
|
end
|
646
670
|
end
|
647
671
|
end
|
@@ -5,7 +5,7 @@ require "active_support/core_ext/module/redefine_method"
|
|
5
5
|
require "active_support/core_ext/hash/indifferent_access"
|
6
6
|
|
7
7
|
module ActiveRecord
|
8
|
-
module NestedAttributes
|
8
|
+
module NestedAttributes # :nodoc:
|
9
9
|
class TooManyRecords < ActiveRecordError
|
10
10
|
end
|
11
11
|
|
@@ -15,7 +15,7 @@ module ActiveRecord
|
|
15
15
|
class_attribute :nested_attributes_options, instance_writer: false, default: {}
|
16
16
|
end
|
17
17
|
|
18
|
-
# = Active Record Nested Attributes
|
18
|
+
# = Active Record Nested \Attributes
|
19
19
|
#
|
20
20
|
# Nested attributes allow you to save attributes on associated records
|
21
21
|
# through the parent. By default nested attribute updating is turned off
|
@@ -180,7 +180,7 @@ module ActiveRecord
|
|
180
180
|
# member.posts.second.title # => '[UPDATED] other post'
|
181
181
|
#
|
182
182
|
# However, the above applies if the parent model is being updated as well.
|
183
|
-
# For example,
|
183
|
+
# For example, if you wanted to create a +member+ named _joe_ and wanted to
|
184
184
|
# update the +posts+ at the same time, that would give an
|
185
185
|
# ActiveRecord::RecordNotFound error.
|
186
186
|
#
|
@@ -245,18 +245,19 @@ module ActiveRecord
|
|
245
245
|
#
|
246
246
|
# === Validating the presence of a parent model
|
247
247
|
#
|
248
|
-
#
|
249
|
-
#
|
250
|
-
#
|
248
|
+
# The +belongs_to+ association validates the presence of the parent model
|
249
|
+
# by default. You can disable this behavior by specifying <code>optional: true</code>.
|
250
|
+
# This can be used, for example, when conditionally validating the presence
|
251
|
+
# of the parent model:
|
251
252
|
#
|
252
|
-
# class
|
253
|
-
# has_many :
|
254
|
-
# accepts_nested_attributes_for :
|
253
|
+
# class Veterinarian < ActiveRecord::Base
|
254
|
+
# has_many :patients, inverse_of: :veterinarian
|
255
|
+
# accepts_nested_attributes_for :patients
|
255
256
|
# end
|
256
257
|
#
|
257
|
-
# class
|
258
|
-
# belongs_to :
|
259
|
-
#
|
258
|
+
# class Patient < ActiveRecord::Base
|
259
|
+
# belongs_to :veterinarian, inverse_of: :patients, optional: true
|
260
|
+
# validates :veterinarian, presence: true, unless: -> { awaiting_intake }
|
260
261
|
# end
|
261
262
|
#
|
262
263
|
# Note that if you do not specify the +:inverse_of+ option, then
|
@@ -279,6 +280,24 @@ module ActiveRecord
|
|
279
280
|
# member = Member.new
|
280
281
|
# member.avatar_attributes = {icon: 'sad'}
|
281
282
|
# member.avatar.width # => 200
|
283
|
+
#
|
284
|
+
# === Creating forms with nested attributes
|
285
|
+
#
|
286
|
+
# Use ActionView::Helpers::FormHelper#fields_for to create form elements for
|
287
|
+
# nested attributes.
|
288
|
+
#
|
289
|
+
# Integration test params should reflect the structure of the form. For
|
290
|
+
# example:
|
291
|
+
#
|
292
|
+
# post members_path, params: {
|
293
|
+
# member: {
|
294
|
+
# name: 'joe',
|
295
|
+
# posts_attributes: {
|
296
|
+
# '0' => { title: 'Foo' },
|
297
|
+
# '1' => { title: 'Bar' }
|
298
|
+
# }
|
299
|
+
# }
|
300
|
+
# }
|
282
301
|
module ClassMethods
|
283
302
|
REJECT_ALL_BLANK_PROC = proc { |attributes| attributes.all? { |key, value| key == "_destroy" || value.blank? } }
|
284
303
|
|
@@ -288,7 +307,7 @@ module ActiveRecord
|
|
288
307
|
# [:allow_destroy]
|
289
308
|
# If true, destroys any members from the attributes hash with a
|
290
309
|
# <tt>_destroy</tt> key and a value that evaluates to +true+
|
291
|
-
# (e.g. 1, '1', true, or 'true'). This option is
|
310
|
+
# (e.g. 1, '1', true, or 'true'). This option is false by default.
|
292
311
|
# [:reject_if]
|
293
312
|
# Allows you to specify a Proc or a Symbol pointing to a method
|
294
313
|
# that checks whether a record should be built for a certain attribute
|
@@ -313,11 +332,11 @@ module ActiveRecord
|
|
313
332
|
# nested attributes are going to be used when an associated record already
|
314
333
|
# exists. In general, an existing record may either be updated with the
|
315
334
|
# new set of attribute values or be replaced by a wholly new record
|
316
|
-
# containing those values. By default the +:update_only+ option is
|
335
|
+
# containing those values. By default the +:update_only+ option is false
|
317
336
|
# and the nested attributes are used to update the existing record only
|
318
337
|
# if they include the record's <tt>:id</tt> value. Otherwise a new
|
319
338
|
# record will be instantiated and used to replace the existing one.
|
320
|
-
# However if the +:update_only+ option is
|
339
|
+
# However if the +:update_only+ option is true, the nested attributes
|
321
340
|
# are used to update the record's attributes always, regardless of
|
322
341
|
# whether the <tt>:id</tt> is present. The option is ignored for collection
|
323
342
|
# associations.
|
@@ -374,11 +393,11 @@ module ActiveRecord
|
|
374
393
|
end
|
375
394
|
end
|
376
395
|
|
377
|
-
# Returns ActiveRecord::AutosaveAssociation
|
396
|
+
# Returns ActiveRecord::AutosaveAssociation#marked_for_destruction? It's
|
378
397
|
# used in conjunction with fields_for to build a form element for the
|
379
398
|
# destruction of this association.
|
380
399
|
#
|
381
|
-
# See ActionView::Helpers::FormHelper
|
400
|
+
# See ActionView::Helpers::FormHelper#fields_for for more info.
|
382
401
|
def _destroy
|
383
402
|
marked_for_destruction?
|
384
403
|
end
|
@@ -486,7 +505,7 @@ module ActiveRecord
|
|
486
505
|
existing_records = if association.loaded?
|
487
506
|
association.target
|
488
507
|
else
|
489
|
-
attribute_ids = attributes_collection.
|
508
|
+
attribute_ids = attributes_collection.filter_map { |a| a["id"] || a[:id] }
|
490
509
|
attribute_ids.empty? ? [] : association.scope.where(association.klass.primary_key => attribute_ids)
|
491
510
|
end
|
492
511
|
|
@@ -500,12 +519,12 @@ module ActiveRecord
|
|
500
519
|
unless reject_new_record?(association_name, attributes)
|
501
520
|
association.reader.build(attributes.except(*UNASSIGNABLE_KEYS))
|
502
521
|
end
|
503
|
-
elsif existing_record = existing_records
|
522
|
+
elsif existing_record = find_record_by_id(existing_records, attributes["id"])
|
504
523
|
unless call_reject_if(association_name, attributes)
|
505
524
|
# Make sure we are operating on the actual object which is in the association's
|
506
525
|
# proxy_target array (either by finding it, or adding it if not found)
|
507
526
|
# Take into account that the proxy_target may have changed due to callbacks
|
508
|
-
target_record = association.target
|
527
|
+
target_record = find_record_by_id(association.target, attributes["id"])
|
509
528
|
if target_record
|
510
529
|
existing_record = target_record
|
511
530
|
else
|
@@ -593,5 +612,16 @@ module ActiveRecord
|
|
593
612
|
raise RecordNotFound.new("Couldn't find #{model} with ID=#{record_id} for #{self.class.name} with ID=#{id}",
|
594
613
|
model, "id", record_id)
|
595
614
|
end
|
615
|
+
|
616
|
+
def find_record_by_id(records, id)
|
617
|
+
return if records.empty?
|
618
|
+
|
619
|
+
if records.first.class.composite_primary_key?
|
620
|
+
id = Array(id).map(&:to_s)
|
621
|
+
records.find { |record| Array(record.id).map(&:to_s) == id }
|
622
|
+
else
|
623
|
+
records.find { |record| record.id.to_s == id.to_s }
|
624
|
+
end
|
625
|
+
end
|
596
626
|
end
|
597
627
|
end
|
@@ -26,20 +26,20 @@ module ActiveRecord
|
|
26
26
|
end
|
27
27
|
|
28
28
|
class << self
|
29
|
-
def apply_to(klass)
|
29
|
+
def apply_to(klass) # :nodoc:
|
30
30
|
klasses.push(klass)
|
31
31
|
yield
|
32
32
|
ensure
|
33
33
|
klasses.pop
|
34
34
|
end
|
35
35
|
|
36
|
-
def applied_to?(klass)
|
36
|
+
def applied_to?(klass) # :nodoc:
|
37
37
|
klasses.any? { |k| k >= klass }
|
38
38
|
end
|
39
39
|
|
40
40
|
private
|
41
41
|
def klasses
|
42
|
-
|
42
|
+
ActiveSupport::IsolatedExecutionState[:active_record_no_touching_classes] ||= []
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|