activerecord 5.1.0 → 5.2.3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +596 -450
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -5
- data/examples/performance.rb +2 -0
- data/examples/simple.rb +2 -0
- data/lib/active_record.rb +11 -4
- data/lib/active_record/aggregations.rb +6 -5
- data/lib/active_record/association_relation.rb +7 -5
- data/lib/active_record/associations.rb +77 -85
- data/lib/active_record/associations/alias_tracker.rb +23 -32
- data/lib/active_record/associations/association.rb +49 -35
- data/lib/active_record/associations/association_scope.rb +55 -55
- data/lib/active_record/associations/belongs_to_association.rb +30 -11
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -8
- data/lib/active_record/associations/builder/association.rb +4 -7
- data/lib/active_record/associations/builder/belongs_to.rb +21 -8
- data/lib/active_record/associations/builder/collection_association.rb +1 -1
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -1
- data/lib/active_record/associations/builder/has_many.rb +2 -0
- data/lib/active_record/associations/builder/has_one.rb +2 -0
- data/lib/active_record/associations/builder/singular_association.rb +2 -0
- data/lib/active_record/associations/collection_association.rb +66 -53
- data/lib/active_record/associations/collection_proxy.rb +30 -73
- data/lib/active_record/associations/foreign_association.rb +2 -0
- data/lib/active_record/associations/has_many_association.rb +13 -2
- data/lib/active_record/associations/has_many_through_association.rb +37 -19
- data/lib/active_record/associations/has_one_association.rb +14 -1
- data/lib/active_record/associations/has_one_through_association.rb +13 -8
- data/lib/active_record/associations/join_dependency.rb +52 -96
- data/lib/active_record/associations/join_dependency/join_association.rb +22 -75
- data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
- data/lib/active_record/associations/join_dependency/join_part.rb +9 -9
- data/lib/active_record/associations/preloader.rb +17 -37
- data/lib/active_record/associations/preloader/association.rb +53 -92
- data/lib/active_record/associations/preloader/through_association.rb +72 -73
- data/lib/active_record/associations/singular_association.rb +14 -16
- data/lib/active_record/associations/through_association.rb +27 -12
- data/lib/active_record/attribute_assignment.rb +2 -5
- data/lib/active_record/attribute_decorators.rb +3 -2
- data/lib/active_record/attribute_methods.rb +65 -24
- data/lib/active_record/attribute_methods/before_type_cast.rb +2 -0
- data/lib/active_record/attribute_methods/dirty.rb +33 -216
- data/lib/active_record/attribute_methods/primary_key.rb +10 -13
- data/lib/active_record/attribute_methods/query.rb +2 -0
- data/lib/active_record/attribute_methods/read.rb +9 -3
- data/lib/active_record/attribute_methods/serialization.rb +23 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +6 -8
- data/lib/active_record/attribute_methods/write.rb +22 -19
- data/lib/active_record/attributes.rb +7 -6
- data/lib/active_record/autosave_association.rb +15 -13
- data/lib/active_record/base.rb +2 -0
- data/lib/active_record/callbacks.rb +12 -6
- data/lib/active_record/coders/json.rb +2 -0
- data/lib/active_record/coders/yaml_column.rb +2 -0
- data/lib/active_record/collection_cache_key.rb +15 -11
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +120 -39
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +7 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +192 -37
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +13 -2
- data/lib/active_record/connection_adapters/abstract/quoting.rb +15 -25
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +15 -6
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +65 -7
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +158 -87
- data/lib/active_record/connection_adapters/abstract/transaction.rb +66 -21
- data/lib/active_record/connection_adapters/abstract_adapter.rb +86 -98
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +126 -189
- data/lib/active_record/connection_adapters/column.rb +4 -2
- data/lib/active_record/connection_adapters/connection_specification.rb +17 -3
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +13 -2
- data/lib/active_record/connection_adapters/mysql/column.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +45 -15
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +9 -10
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +5 -3
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +7 -10
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +30 -23
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +106 -1
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -2
- data/lib/active_record/connection_adapters/postgresql/column.rb +30 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +6 -32
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +13 -1
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +8 -2
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +4 -2
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +22 -1
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +24 -11
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +20 -13
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +258 -129
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +75 -87
- data/lib/active_record/connection_adapters/schema_cache.rb +4 -2
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +24 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +6 -15
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +3 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +75 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +90 -96
- data/lib/active_record/connection_adapters/statement_pool.rb +2 -0
- data/lib/active_record/connection_handling.rb +4 -2
- data/lib/active_record/core.rb +41 -61
- data/lib/active_record/counter_cache.rb +20 -15
- data/lib/active_record/define_callbacks.rb +5 -3
- data/lib/active_record/dynamic_matchers.rb +9 -9
- data/lib/active_record/enum.rb +18 -13
- data/lib/active_record/errors.rb +60 -15
- data/lib/active_record/explain.rb +3 -1
- data/lib/active_record/explain_registry.rb +2 -0
- data/lib/active_record/explain_subscriber.rb +2 -0
- data/lib/active_record/fixture_set/file.rb +2 -0
- data/lib/active_record/fixtures.rb +67 -60
- data/lib/active_record/gem_version.rb +4 -2
- data/lib/active_record/inheritance.rb +49 -19
- data/lib/active_record/integration.rb +58 -19
- data/lib/active_record/internal_metadata.rb +2 -0
- data/lib/active_record/legacy_yaml_adapter.rb +3 -1
- data/lib/active_record/locking/optimistic.rb +30 -42
- data/lib/active_record/locking/pessimistic.rb +10 -7
- data/lib/active_record/log_subscriber.rb +46 -4
- data/lib/active_record/migration.rb +189 -139
- data/lib/active_record/migration/command_recorder.rb +11 -9
- data/lib/active_record/migration/compatibility.rb +81 -29
- data/lib/active_record/migration/join_table.rb +2 -0
- data/lib/active_record/model_schema.rb +74 -58
- data/lib/active_record/nested_attributes.rb +18 -6
- data/lib/active_record/no_touching.rb +3 -1
- data/lib/active_record/null_relation.rb +2 -0
- data/lib/active_record/persistence.rb +199 -54
- data/lib/active_record/query_cache.rb +8 -10
- data/lib/active_record/querying.rb +5 -3
- data/lib/active_record/railtie.rb +62 -6
- data/lib/active_record/railties/console_sandbox.rb +2 -0
- data/lib/active_record/railties/controller_runtime.rb +2 -0
- data/lib/active_record/railties/databases.rake +48 -38
- data/lib/active_record/readonly_attributes.rb +3 -2
- data/lib/active_record/reflection.rb +137 -207
- data/lib/active_record/relation.rb +132 -207
- data/lib/active_record/relation/batches.rb +32 -17
- data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
- data/lib/active_record/relation/calculations.rb +66 -25
- data/lib/active_record/relation/delegation.rb +45 -29
- data/lib/active_record/relation/finder_methods.rb +76 -85
- data/lib/active_record/relation/from_clause.rb +2 -8
- data/lib/active_record/relation/merger.rb +53 -23
- data/lib/active_record/relation/predicate_builder.rb +60 -79
- data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -7
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +12 -1
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +56 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +26 -9
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
- data/lib/active_record/relation/query_attribute.rb +28 -2
- data/lib/active_record/relation/query_methods.rb +135 -103
- data/lib/active_record/relation/record_fetch_warning.rb +2 -0
- data/lib/active_record/relation/spawn_methods.rb +4 -2
- data/lib/active_record/relation/where_clause.rb +65 -67
- data/lib/active_record/relation/where_clause_factory.rb +5 -48
- data/lib/active_record/result.rb +2 -0
- data/lib/active_record/runtime_registry.rb +2 -0
- data/lib/active_record/sanitization.rb +129 -121
- data/lib/active_record/schema.rb +4 -2
- data/lib/active_record/schema_dumper.rb +36 -26
- data/lib/active_record/schema_migration.rb +2 -0
- data/lib/active_record/scoping.rb +12 -10
- data/lib/active_record/scoping/default.rb +10 -7
- data/lib/active_record/scoping/named.rb +40 -12
- data/lib/active_record/secure_token.rb +2 -0
- data/lib/active_record/serialization.rb +2 -0
- data/lib/active_record/statement_cache.rb +22 -12
- data/lib/active_record/store.rb +3 -1
- data/lib/active_record/suppressor.rb +2 -0
- data/lib/active_record/table_metadata.rb +12 -3
- data/lib/active_record/tasks/database_tasks.rb +38 -26
- data/lib/active_record/tasks/mysql_database_tasks.rb +11 -50
- data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -3
- data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -3
- data/lib/active_record/timestamp.rb +13 -6
- data/lib/active_record/touch_later.rb +2 -0
- data/lib/active_record/transactions.rb +32 -27
- data/lib/active_record/translation.rb +2 -0
- data/lib/active_record/type.rb +4 -1
- data/lib/active_record/type/adapter_specific_registry.rb +2 -0
- data/lib/active_record/type/date.rb +2 -0
- data/lib/active_record/type/date_time.rb +2 -0
- data/lib/active_record/type/decimal_without_scale.rb +2 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +2 -0
- data/lib/active_record/type/internal/timezone.rb +2 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +6 -0
- data/lib/active_record/type/text.rb +2 -0
- data/lib/active_record/type/time.rb +2 -0
- data/lib/active_record/type/type_map.rb +2 -0
- data/lib/active_record/type/unsigned_integer.rb +2 -0
- data/lib/active_record/type_caster.rb +2 -0
- data/lib/active_record/type_caster/connection.rb +2 -0
- data/lib/active_record/type_caster/map.rb +3 -1
- data/lib/active_record/validations.rb +2 -0
- data/lib/active_record/validations/absence.rb +2 -0
- data/lib/active_record/validations/associated.rb +2 -0
- data/lib/active_record/validations/length.rb +2 -0
- data/lib/active_record/validations/presence.rb +2 -0
- data/lib/active_record/validations/uniqueness.rb +36 -6
- data/lib/active_record/version.rb +2 -0
- data/lib/rails/generators/active_record.rb +3 -1
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
- data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
- data/lib/rails/generators/active_record/migration.rb +2 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -1
- data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +0 -0
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +0 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +2 -23
- data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +0 -0
- data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
- metadata +24 -36
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -15
- data/lib/active_record/associations/preloader/collection_association.rb +0 -17
- data/lib/active_record/associations/preloader/has_many.rb +0 -15
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
- data/lib/active_record/associations/preloader/has_one.rb +0 -15
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -18
- data/lib/active_record/attribute.rb +0 -240
- data/lib/active_record/attribute/user_provided_default.rb +0 -30
- data/lib/active_record/attribute_mutation_tracker.rb +0 -113
- data/lib/active_record/attribute_set.rb +0 -113
- data/lib/active_record/attribute_set/builder.rb +0 -124
- data/lib/active_record/attribute_set/yaml_encoder.rb +0 -41
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -10
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -59
- data/lib/active_record/type/internal/abstract_json.rb +0 -33
data/lib/active_record/errors.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
# = Active Record Errors
|
3
5
|
#
|
@@ -105,7 +107,7 @@ module ActiveRecord
|
|
105
107
|
class WrappedDatabaseException < StatementInvalid
|
106
108
|
end
|
107
109
|
|
108
|
-
# Raised when a record cannot be inserted because it would violate a uniqueness constraint.
|
110
|
+
# Raised when a record cannot be inserted or updated because it would violate a uniqueness constraint.
|
109
111
|
class RecordNotUnique < WrappedDatabaseException
|
110
112
|
end
|
111
113
|
|
@@ -115,16 +117,27 @@ module ActiveRecord
|
|
115
117
|
|
116
118
|
# Raised when a foreign key constraint cannot be added because the column type does not match the referenced column type.
|
117
119
|
class MismatchedForeignKey < StatementInvalid
|
118
|
-
def initialize(
|
119
|
-
|
120
|
+
def initialize(
|
121
|
+
adapter = nil,
|
122
|
+
message: nil,
|
123
|
+
sql: nil,
|
124
|
+
binds: nil,
|
125
|
+
table: nil,
|
126
|
+
foreign_key: nil,
|
127
|
+
target_table: nil,
|
128
|
+
primary_key: nil,
|
129
|
+
primary_key_column: nil
|
130
|
+
)
|
120
131
|
if table
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
132
|
+
type = primary_key_column.bigint? ? :bigint : primary_key_column.type
|
133
|
+
msg = <<-EOM.squish
|
134
|
+
Column `#{foreign_key}` on table `#{table}` does not match column `#{primary_key}` on `#{target_table}`,
|
135
|
+
which has type `#{primary_key_column.sql_type}`.
|
136
|
+
To resolve this issue, change the type of the `#{foreign_key}` column on `#{table}` to be :#{type}.
|
137
|
+
(For example `t.#{type} :#{foreign_key}`).
|
125
138
|
EOM
|
126
139
|
else
|
127
|
-
msg = <<-EOM
|
140
|
+
msg = <<-EOM.squish
|
128
141
|
There is a mismatch between the foreign key and primary key column types.
|
129
142
|
Verify that the foreign key column type and the primary key of the associated table match types.
|
130
143
|
EOM
|
@@ -134,11 +147,6 @@ module ActiveRecord
|
|
134
147
|
end
|
135
148
|
super(msg)
|
136
149
|
end
|
137
|
-
|
138
|
-
private
|
139
|
-
def column_type(table, column)
|
140
|
-
@adapter.columns(table).detect { |c| c.name == column }.sql_type
|
141
|
-
end
|
142
150
|
end
|
143
151
|
|
144
152
|
# Raised when a record cannot be inserted or updated because it would violate a not null constraint.
|
@@ -167,7 +175,7 @@ module ActiveRecord
|
|
167
175
|
class NoDatabaseError < StatementInvalid
|
168
176
|
end
|
169
177
|
|
170
|
-
# Raised when
|
178
|
+
# Raised when PostgreSQL returns 'cached plan must not change result type' and
|
171
179
|
# we cannot retry gracefully (e.g. inside a transaction)
|
172
180
|
class PreparedStatementCacheExpired < StatementInvalid
|
173
181
|
end
|
@@ -313,7 +321,7 @@ module ActiveRecord
|
|
313
321
|
#
|
314
322
|
# See the following:
|
315
323
|
#
|
316
|
-
# *
|
324
|
+
# * https://www.postgresql.org/docs/current/static/transaction-iso.html
|
317
325
|
# * https://dev.mysql.com/doc/refman/5.7/en/error-messages-server.html#error_er_lock_deadlock
|
318
326
|
class TransactionRollbackError < StatementInvalid
|
319
327
|
end
|
@@ -332,4 +340,41 @@ module ActiveRecord
|
|
332
340
|
# +reverse_order+ to automatically reverse.
|
333
341
|
class IrreversibleOrderError < ActiveRecordError
|
334
342
|
end
|
343
|
+
|
344
|
+
# LockWaitTimeout will be raised when lock wait timeout exceeded.
|
345
|
+
class LockWaitTimeout < StatementInvalid
|
346
|
+
end
|
347
|
+
|
348
|
+
# StatementTimeout will be raised when statement timeout exceeded.
|
349
|
+
class StatementTimeout < StatementInvalid
|
350
|
+
end
|
351
|
+
|
352
|
+
# QueryCanceled will be raised when canceling statement due to user request.
|
353
|
+
class QueryCanceled < StatementInvalid
|
354
|
+
end
|
355
|
+
|
356
|
+
# UnknownAttributeReference is raised when an unknown and potentially unsafe
|
357
|
+
# value is passed to a query method when allow_unsafe_raw_sql is set to
|
358
|
+
# :disabled. For example, passing a non column name value to a relation's
|
359
|
+
# #order method might cause this exception.
|
360
|
+
#
|
361
|
+
# When working around this exception, caution should be taken to avoid SQL
|
362
|
+
# injection vulnerabilities when passing user-provided values to query
|
363
|
+
# methods. Known-safe values can be passed to query methods by wrapping them
|
364
|
+
# in Arel.sql.
|
365
|
+
#
|
366
|
+
# For example, with allow_unsafe_raw_sql set to :disabled, the following
|
367
|
+
# code would raise this exception:
|
368
|
+
#
|
369
|
+
# Post.order("length(title)").first
|
370
|
+
#
|
371
|
+
# The desired result can be accomplished by wrapping the known-safe string
|
372
|
+
# in Arel.sql:
|
373
|
+
#
|
374
|
+
# Post.order(Arel.sql("length(title)")).first
|
375
|
+
#
|
376
|
+
# Again, such a workaround should *not* be used when passing user-provided
|
377
|
+
# values, such as request parameters or model attributes to query methods.
|
378
|
+
class UnknownAttributeReference < ActiveRecordError
|
379
|
+
end
|
335
380
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_record/explain_registry"
|
2
4
|
|
3
5
|
module ActiveRecord
|
@@ -16,7 +18,7 @@ module ActiveRecord
|
|
16
18
|
# Returns a formatted string ready to be logged.
|
17
19
|
def exec_explain(queries) # :nodoc:
|
18
20
|
str = queries.map do |sql, binds|
|
19
|
-
msg = "EXPLAIN for: #{sql}"
|
21
|
+
msg = "EXPLAIN for: #{sql}".dup
|
20
22
|
unless binds.empty?
|
21
23
|
msg << " "
|
22
24
|
msg << binds.map { |attr| render_bind(attr) }.inspect
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "erb"
|
2
4
|
require "yaml"
|
3
5
|
require "zlib"
|
@@ -70,13 +72,32 @@ module ActiveRecord
|
|
70
72
|
# test. To ensure consistent data, the environment deletes the fixtures before running the load.
|
71
73
|
#
|
72
74
|
# In addition to being available in the database, the fixture's data may also be accessed by
|
73
|
-
# using a special dynamic method, which has the same name as the model
|
74
|
-
#
|
75
|
+
# using a special dynamic method, which has the same name as the model.
|
76
|
+
#
|
77
|
+
# Passing in a fixture name to this dynamic method returns the fixture matching this name:
|
75
78
|
#
|
76
|
-
# test "find" do
|
79
|
+
# test "find one" do
|
77
80
|
# assert_equal "Ruby on Rails", web_sites(:rubyonrails).name
|
78
81
|
# end
|
79
82
|
#
|
83
|
+
# Passing in multiple fixture names returns all fixtures matching these names:
|
84
|
+
#
|
85
|
+
# test "find all by name" do
|
86
|
+
# assert_equal 2, web_sites(:rubyonrails, :google).length
|
87
|
+
# end
|
88
|
+
#
|
89
|
+
# Passing in no arguments returns all fixtures:
|
90
|
+
#
|
91
|
+
# test "find all" do
|
92
|
+
# assert_equal 2, web_sites.length
|
93
|
+
# end
|
94
|
+
#
|
95
|
+
# Passing in any fixture name that does not exist will raise <tt>StandardError</tt>:
|
96
|
+
#
|
97
|
+
# test "find by name that does not exist" do
|
98
|
+
# assert_raise(StandardError) { web_sites(:reddit) }
|
99
|
+
# end
|
100
|
+
#
|
80
101
|
# Alternatively, you may enable auto-instantiation of the fixture data. For instance, take the
|
81
102
|
# following tests:
|
82
103
|
#
|
@@ -126,7 +147,7 @@ module ActiveRecord
|
|
126
147
|
# unwanted inter-test dependencies. Methods used by multiple fixtures should be defined in a module
|
127
148
|
# that is included in ActiveRecord::FixtureSet.context_class.
|
128
149
|
#
|
129
|
-
# - define a helper method in
|
150
|
+
# - define a helper method in <tt>test_helper.rb</tt>
|
130
151
|
# module FixtureFileHelpers
|
131
152
|
# def file_sha(path)
|
132
153
|
# Digest::SHA2.hexdigest(File.read(Rails.root.join('test/fixtures', path)))
|
@@ -148,13 +169,13 @@ module ActiveRecord
|
|
148
169
|
# self.use_transactional_tests = true
|
149
170
|
#
|
150
171
|
# test "godzilla" do
|
151
|
-
#
|
172
|
+
# assert_not_empty Foo.all
|
152
173
|
# Foo.destroy_all
|
153
|
-
#
|
174
|
+
# assert_empty Foo.all
|
154
175
|
# end
|
155
176
|
#
|
156
177
|
# test "godzilla aftermath" do
|
157
|
-
#
|
178
|
+
# assert_not_empty Foo.all
|
158
179
|
# end
|
159
180
|
# end
|
160
181
|
#
|
@@ -473,8 +494,7 @@ module ActiveRecord
|
|
473
494
|
end
|
474
495
|
end
|
475
496
|
|
476
|
-
cattr_accessor :all_loaded_fixtures
|
477
|
-
self.all_loaded_fixtures = {}
|
497
|
+
cattr_accessor :all_loaded_fixtures, default: {}
|
478
498
|
|
479
499
|
class ClassCache
|
480
500
|
def initialize(class_names, config)
|
@@ -520,49 +540,38 @@ module ActiveRecord
|
|
520
540
|
}
|
521
541
|
|
522
542
|
unless files_to_read.empty?
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
end
|
535
|
-
|
536
|
-
update_all_loaded_fixtures fixtures_map
|
537
|
-
|
538
|
-
connection.transaction(requires_new: true) do
|
539
|
-
deleted_tables = Hash.new { |h, k| h[k] = Set.new }
|
540
|
-
fixture_sets.each do |fs|
|
541
|
-
conn = fs.model_class.respond_to?(:connection) ? fs.model_class.connection : connection
|
542
|
-
table_rows = fs.table_rows
|
543
|
+
fixtures_map = {}
|
544
|
+
|
545
|
+
fixture_sets = files_to_read.map do |fs_name|
|
546
|
+
klass = class_names[fs_name]
|
547
|
+
conn = klass ? klass.connection : connection
|
548
|
+
fixtures_map[fs_name] = new( # ActiveRecord::FixtureSet.new
|
549
|
+
conn,
|
550
|
+
fs_name,
|
551
|
+
klass,
|
552
|
+
::File.join(fixtures_directory, fs_name))
|
553
|
+
end
|
543
554
|
|
544
|
-
|
545
|
-
|
546
|
-
conn.delete "DELETE FROM #{conn.quote_table_name(table)}", "Fixture Delete"
|
547
|
-
end
|
548
|
-
deleted_tables[conn] << table
|
549
|
-
end
|
555
|
+
update_all_loaded_fixtures fixtures_map
|
556
|
+
fixture_sets_by_connection = fixture_sets.group_by { |fs| fs.model_class ? fs.model_class.connection : connection }
|
550
557
|
|
551
|
-
|
552
|
-
|
553
|
-
conn.insert_fixture(row, fixture_set_name)
|
554
|
-
end
|
555
|
-
end
|
558
|
+
fixture_sets_by_connection.each do |conn, set|
|
559
|
+
table_rows_for_connection = Hash.new { |h, k| h[k] = [] }
|
556
560
|
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
end
|
561
|
+
set.each do |fs|
|
562
|
+
fs.table_rows.each do |table, rows|
|
563
|
+
table_rows_for_connection[table].unshift(*rows)
|
561
564
|
end
|
562
565
|
end
|
566
|
+
conn.insert_fixtures_set(table_rows_for_connection, table_rows_for_connection.keys)
|
563
567
|
|
564
|
-
|
568
|
+
# Cap primary key sequences to max(pk).
|
569
|
+
if conn.respond_to?(:reset_pk_sequence!)
|
570
|
+
set.each { |fs| conn.reset_pk_sequence!(fs.table_name) }
|
571
|
+
end
|
565
572
|
end
|
573
|
+
|
574
|
+
cache_fixtures(connection, fixtures_map)
|
566
575
|
end
|
567
576
|
cached_fixtures(connection, fixture_set_names)
|
568
577
|
end
|
@@ -859,20 +868,12 @@ module ActiveRecord
|
|
859
868
|
|
860
869
|
included do
|
861
870
|
class_attribute :fixture_path, instance_writer: false
|
862
|
-
class_attribute :fixture_table_names
|
863
|
-
class_attribute :fixture_class_names
|
864
|
-
class_attribute :use_transactional_tests
|
865
|
-
class_attribute :use_instantiated_fixtures # true, false, or :no_instances
|
866
|
-
class_attribute :pre_loaded_fixtures
|
867
|
-
class_attribute :config
|
868
|
-
|
869
|
-
self.fixture_table_names = []
|
870
|
-
self.use_instantiated_fixtures = false
|
871
|
-
self.pre_loaded_fixtures = false
|
872
|
-
self.config = ActiveRecord::Base
|
873
|
-
|
874
|
-
self.fixture_class_names = {}
|
875
|
-
self.use_transactional_tests = true
|
871
|
+
class_attribute :fixture_table_names, default: []
|
872
|
+
class_attribute :fixture_class_names, default: {}
|
873
|
+
class_attribute :use_transactional_tests, default: true
|
874
|
+
class_attribute :use_instantiated_fixtures, default: false # true, false, or :no_instances
|
875
|
+
class_attribute :pre_loaded_fixtures, default: false
|
876
|
+
class_attribute :config, default: ActiveRecord::Base
|
876
877
|
end
|
877
878
|
|
878
879
|
module ClassMethods
|
@@ -909,6 +910,8 @@ module ActiveRecord
|
|
909
910
|
|
910
911
|
define_method(accessor_name) do |*fixture_names|
|
911
912
|
force_reload = fixture_names.pop if fixture_names.last == true || fixture_names.last == :reload
|
913
|
+
return_single_record = fixture_names.size == 1
|
914
|
+
fixture_names = @loaded_fixtures[fs_name].fixtures.keys if fixture_names.empty?
|
912
915
|
|
913
916
|
@fixture_cache[fs_name] ||= {}
|
914
917
|
|
@@ -923,7 +926,7 @@ module ActiveRecord
|
|
923
926
|
end
|
924
927
|
end
|
925
928
|
|
926
|
-
|
929
|
+
return_single_record ? instances.first : instances
|
927
930
|
end
|
928
931
|
private accessor_name
|
929
932
|
end
|
@@ -1053,6 +1056,10 @@ class ActiveRecord::FixtureSet::RenderContext # :nodoc:
|
|
1053
1056
|
def get_binding
|
1054
1057
|
binding()
|
1055
1058
|
end
|
1059
|
+
|
1060
|
+
def binary(path)
|
1061
|
+
%(!!binary "#{Base64.strict_encode64(File.read(path))}")
|
1062
|
+
end
|
1056
1063
|
end
|
1057
1064
|
end
|
1058
1065
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
# Returns the version of the currently loaded Active Record as a <tt>Gem::Version</tt>
|
3
5
|
def self.gem_version
|
@@ -6,8 +8,8 @@ module ActiveRecord
|
|
6
8
|
|
7
9
|
module VERSION
|
8
10
|
MAJOR = 5
|
9
|
-
MINOR =
|
10
|
-
TINY =
|
11
|
+
MINOR = 2
|
12
|
+
TINY = 3
|
11
13
|
PRE = nil
|
12
14
|
|
13
15
|
STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/core_ext/hash/indifferent_access"
|
2
4
|
|
3
5
|
module ActiveRecord
|
@@ -30,7 +32,7 @@ module ActiveRecord
|
|
30
32
|
# for differentiating between them or reloading the right type with find.
|
31
33
|
#
|
32
34
|
# Note, all the attributes for all the cases are kept in the same table. Read more:
|
33
|
-
#
|
35
|
+
# https://www.martinfowler.com/eaaCatalog/singleTableInheritance.html
|
34
36
|
#
|
35
37
|
module Inheritance
|
36
38
|
extend ActiveSupport::Concern
|
@@ -38,22 +40,20 @@ module ActiveRecord
|
|
38
40
|
included do
|
39
41
|
# Determines whether to store the full constant name including namespace when using STI.
|
40
42
|
# This is true, by default.
|
41
|
-
class_attribute :store_full_sti_class, instance_writer: false
|
42
|
-
self.store_full_sti_class = true
|
43
|
+
class_attribute :store_full_sti_class, instance_writer: false, default: true
|
43
44
|
end
|
44
45
|
|
45
46
|
module ClassMethods
|
46
47
|
# Determines if one of the attributes passed in is the inheritance column,
|
47
48
|
# and if the inheritance column is attr accessible, it initializes an
|
48
49
|
# instance of the given subclass instead of the base class.
|
49
|
-
def new(
|
50
|
+
def new(attributes = nil, &block)
|
50
51
|
if abstract_class? || self == Base
|
51
52
|
raise NotImplementedError, "#{self} is an abstract class and cannot be instantiated."
|
52
53
|
end
|
53
54
|
|
54
|
-
attrs = args.first
|
55
55
|
if has_attribute?(inheritance_column)
|
56
|
-
subclass = subclass_from_attributes(
|
56
|
+
subclass = subclass_from_attributes(attributes)
|
57
57
|
|
58
58
|
if subclass.nil? && base_class == self
|
59
59
|
subclass = subclass_from_attributes(column_defaults)
|
@@ -61,7 +61,7 @@ module ActiveRecord
|
|
61
61
|
end
|
62
62
|
|
63
63
|
if subclass && subclass != self
|
64
|
-
subclass.new(
|
64
|
+
subclass.new(attributes, &block)
|
65
65
|
else
|
66
66
|
super
|
67
67
|
end
|
@@ -104,21 +104,47 @@ module ActiveRecord
|
|
104
104
|
end
|
105
105
|
end
|
106
106
|
|
107
|
-
# Set this to true if this is an abstract class (see
|
108
|
-
#
|
109
|
-
#
|
110
|
-
#
|
107
|
+
# Set this to +true+ if this is an abstract class (see
|
108
|
+
# <tt>abstract_class?</tt>).
|
109
|
+
# If you are using inheritance with Active Record and don't want a class
|
110
|
+
# to be considered as part of the STI hierarchy, you must set this to
|
111
|
+
# true.
|
112
|
+
# +ApplicationRecord+, for example, is generated as an abstract class.
|
113
|
+
#
|
114
|
+
# Consider the following default behaviour:
|
115
|
+
#
|
116
|
+
# Shape = Class.new(ActiveRecord::Base)
|
117
|
+
# Polygon = Class.new(Shape)
|
118
|
+
# Square = Class.new(Polygon)
|
119
|
+
#
|
120
|
+
# Shape.table_name # => "shapes"
|
121
|
+
# Polygon.table_name # => "shapes"
|
122
|
+
# Square.table_name # => "shapes"
|
123
|
+
# Shape.create! # => #<Shape id: 1, type: nil>
|
124
|
+
# Polygon.create! # => #<Polygon id: 2, type: "Polygon">
|
125
|
+
# Square.create! # => #<Square id: 3, type: "Square">
|
126
|
+
#
|
127
|
+
# However, when using <tt>abstract_class</tt>, +Shape+ is omitted from
|
128
|
+
# the hierarchy:
|
111
129
|
#
|
112
|
-
# class
|
130
|
+
# class Shape < ActiveRecord::Base
|
113
131
|
# self.abstract_class = true
|
114
132
|
# end
|
115
|
-
#
|
116
|
-
#
|
117
|
-
# end
|
118
|
-
#
|
133
|
+
# Polygon = Class.new(Shape)
|
134
|
+
# Square = Class.new(Polygon)
|
119
135
|
#
|
120
|
-
#
|
136
|
+
# Shape.table_name # => nil
|
137
|
+
# Polygon.table_name # => "polygons"
|
138
|
+
# Square.table_name # => "polygons"
|
139
|
+
# Shape.create! # => NotImplementedError: Shape is an abstract class and cannot be instantiated.
|
140
|
+
# Polygon.create! # => #<Polygon id: 1, type: nil>
|
141
|
+
# Square.create! # => #<Square id: 2, type: "Square">
|
121
142
|
#
|
143
|
+
# Note that in the above example, to disallow the creation of a plain
|
144
|
+
# +Polygon+, you should use <tt>validates :type, presence: true</tt>,
|
145
|
+
# instead of setting it as an abstract class. This way, +Polygon+ will
|
146
|
+
# stay in the hierarchy, and Active Record will continue to correctly
|
147
|
+
# derive the table name.
|
122
148
|
attr_accessor :abstract_class
|
123
149
|
|
124
150
|
# Returns whether this class is an abstract class or not.
|
@@ -130,6 +156,10 @@ module ActiveRecord
|
|
130
156
|
store_full_sti_class ? name : name.demodulize
|
131
157
|
end
|
132
158
|
|
159
|
+
def polymorphic_name
|
160
|
+
base_class.name
|
161
|
+
end
|
162
|
+
|
133
163
|
def inherited(subclass)
|
134
164
|
subclass.instance_variable_set(:@_type_candidates_cache, Concurrent::Map.new)
|
135
165
|
super
|
@@ -217,7 +247,7 @@ module ActiveRecord
|
|
217
247
|
def subclass_from_attributes(attrs)
|
218
248
|
attrs = attrs.to_h if attrs.respond_to?(:permitted?)
|
219
249
|
if attrs.is_a?(Hash)
|
220
|
-
subclass_name = attrs
|
250
|
+
subclass_name = attrs[inheritance_column] || attrs[inheritance_column.to_sym]
|
221
251
|
|
222
252
|
if subclass_name.present?
|
223
253
|
find_sti_class(subclass_name)
|
@@ -246,7 +276,7 @@ module ActiveRecord
|
|
246
276
|
def ensure_proper_type
|
247
277
|
klass = self.class
|
248
278
|
if klass.finder_needs_type_condition?
|
249
|
-
|
279
|
+
_write_attribute(klass.inheritance_column, klass.sti_name)
|
250
280
|
end
|
251
281
|
end
|
252
282
|
end
|