activerecord 6.0.1 → 6.1.7.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1363 -647
- data/MIT-LICENSE +1 -1
- data/README.rdoc +4 -4
- data/lib/active_record/aggregations.rb +5 -6
- data/lib/active_record/association_relation.rb +26 -15
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +55 -37
- data/lib/active_record/associations/association_scope.rb +19 -15
- data/lib/active_record/associations/belongs_to_association.rb +23 -10
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -3
- data/lib/active_record/associations/builder/association.rb +32 -5
- data/lib/active_record/associations/builder/belongs_to.rb +10 -7
- data/lib/active_record/associations/builder/collection_association.rb +5 -4
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +0 -3
- data/lib/active_record/associations/builder/has_many.rb +6 -2
- data/lib/active_record/associations/builder/has_one.rb +11 -14
- data/lib/active_record/associations/builder/singular_association.rb +1 -1
- data/lib/active_record/associations/collection_association.rb +38 -13
- data/lib/active_record/associations/collection_proxy.rb +14 -7
- data/lib/active_record/associations/foreign_association.rb +13 -0
- data/lib/active_record/associations/has_many_association.rb +24 -3
- data/lib/active_record/associations/has_many_through_association.rb +10 -4
- data/lib/active_record/associations/has_one_association.rb +15 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +39 -16
- data/lib/active_record/associations/join_dependency/join_part.rb +3 -3
- data/lib/active_record/associations/join_dependency.rb +73 -42
- data/lib/active_record/associations/preloader/association.rb +49 -25
- data/lib/active_record/associations/preloader/through_association.rb +2 -2
- data/lib/active_record/associations/preloader.rb +12 -7
- data/lib/active_record/associations/singular_association.rb +1 -1
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/associations.rb +119 -12
- data/lib/active_record/attribute_assignment.rb +10 -9
- data/lib/active_record/attribute_methods/before_type_cast.rb +13 -10
- data/lib/active_record/attribute_methods/dirty.rb +3 -13
- data/lib/active_record/attribute_methods/primary_key.rb +6 -4
- data/lib/active_record/attribute_methods/query.rb +3 -6
- data/lib/active_record/attribute_methods/read.rb +8 -12
- data/lib/active_record/attribute_methods/serialization.rb +11 -6
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -15
- data/lib/active_record/attribute_methods/write.rb +12 -21
- data/lib/active_record/attribute_methods.rb +64 -54
- data/lib/active_record/attributes.rb +33 -9
- data/lib/active_record/autosave_association.rb +56 -41
- data/lib/active_record/base.rb +2 -14
- data/lib/active_record/callbacks.rb +153 -24
- data/lib/active_record/coders/yaml_column.rb +24 -3
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +190 -136
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -44
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +83 -38
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +3 -9
- data/lib/active_record/connection_adapters/abstract/quoting.rb +44 -35
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +152 -116
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +145 -52
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +267 -105
- data/lib/active_record/connection_adapters/abstract/transaction.rb +94 -36
- data/lib/active_record/connection_adapters/abstract_adapter.rb +63 -77
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +136 -111
- data/lib/active_record/connection_adapters/column.rb +15 -1
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +30 -36
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
- data/lib/active_record/connection_adapters/mysql/quoting.rb +18 -3
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +32 -7
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +8 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +5 -2
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +20 -13
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +31 -13
- data/lib/active_record/connection_adapters/pool_config.rb +73 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +24 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +21 -56
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +10 -2
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -3
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -3
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +24 -6
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +11 -2
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +30 -4
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +7 -3
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +72 -54
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +80 -66
- data/lib/active_record/connection_adapters/schema_cache.rb +130 -15
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +8 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +38 -12
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +1 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +38 -5
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +57 -57
- data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
- data/lib/active_record/connection_adapters.rb +52 -0
- data/lib/active_record/connection_handling.rb +218 -87
- data/lib/active_record/core.rb +276 -68
- data/lib/active_record/counter_cache.rb +4 -1
- data/lib/active_record/database_configurations/connection_url_resolver.rb +99 -0
- data/lib/active_record/database_configurations/database_config.rb +52 -9
- data/lib/active_record/database_configurations/hash_config.rb +54 -8
- data/lib/active_record/database_configurations/url_config.rb +15 -41
- data/lib/active_record/database_configurations.rb +125 -85
- data/lib/active_record/delegated_type.rb +209 -0
- data/lib/active_record/destroy_association_async_job.rb +36 -0
- data/lib/active_record/dynamic_matchers.rb +2 -3
- data/lib/active_record/enum.rb +80 -38
- data/lib/active_record/errors.rb +47 -12
- data/lib/active_record/explain.rb +9 -5
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +10 -17
- data/lib/active_record/fixture_set/model_metadata.rb +1 -2
- data/lib/active_record/fixture_set/render_context.rb +1 -1
- data/lib/active_record/fixture_set/table_row.rb +2 -3
- data/lib/active_record/fixture_set/table_rows.rb +0 -1
- data/lib/active_record/fixtures.rb +58 -12
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +40 -21
- data/lib/active_record/insert_all.rb +42 -9
- data/lib/active_record/integration.rb +3 -5
- data/lib/active_record/internal_metadata.rb +18 -7
- data/lib/active_record/legacy_yaml_adapter.rb +7 -3
- data/lib/active_record/locking/optimistic.rb +33 -18
- data/lib/active_record/locking/pessimistic.rb +6 -2
- data/lib/active_record/log_subscriber.rb +28 -9
- data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +6 -2
- data/lib/active_record/middleware/database_selector.rb +4 -2
- data/lib/active_record/migration/command_recorder.rb +53 -45
- data/lib/active_record/migration/compatibility.rb +75 -21
- data/lib/active_record/migration/join_table.rb +0 -1
- data/lib/active_record/migration.rb +115 -85
- data/lib/active_record/model_schema.rb +117 -15
- data/lib/active_record/nested_attributes.rb +2 -5
- data/lib/active_record/no_touching.rb +1 -1
- data/lib/active_record/null_relation.rb +0 -1
- data/lib/active_record/persistence.rb +50 -46
- data/lib/active_record/query_cache.rb +15 -5
- data/lib/active_record/querying.rb +12 -7
- data/lib/active_record/railtie.rb +65 -45
- data/lib/active_record/railties/console_sandbox.rb +2 -4
- data/lib/active_record/railties/databases.rake +280 -99
- data/lib/active_record/readonly_attributes.rb +4 -0
- data/lib/active_record/reflection.rb +77 -63
- data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
- data/lib/active_record/relation/batches.rb +38 -32
- data/lib/active_record/relation/calculations.rb +106 -45
- data/lib/active_record/relation/delegation.rb +9 -7
- data/lib/active_record/relation/finder_methods.rb +45 -16
- data/lib/active_record/relation/from_clause.rb +5 -1
- data/lib/active_record/relation/merger.rb +27 -26
- data/lib/active_record/relation/predicate_builder/array_handler.rb +8 -9
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +4 -5
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -6
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/predicate_builder.rb +59 -40
- data/lib/active_record/relation/query_methods.rb +341 -188
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +8 -8
- data/lib/active_record/relation/where_clause.rb +111 -62
- data/lib/active_record/relation.rb +116 -83
- data/lib/active_record/result.rb +41 -34
- data/lib/active_record/runtime_registry.rb +2 -2
- data/lib/active_record/sanitization.rb +6 -17
- data/lib/active_record/schema_dumper.rb +34 -4
- data/lib/active_record/schema_migration.rb +2 -8
- data/lib/active_record/scoping/default.rb +1 -4
- data/lib/active_record/scoping/named.rb +7 -18
- data/lib/active_record/scoping.rb +0 -1
- data/lib/active_record/secure_token.rb +16 -8
- data/lib/active_record/serialization.rb +5 -3
- data/lib/active_record/signed_id.rb +116 -0
- data/lib/active_record/statement_cache.rb +20 -4
- data/lib/active_record/store.rb +9 -4
- data/lib/active_record/suppressor.rb +2 -2
- data/lib/active_record/table_metadata.rb +42 -36
- data/lib/active_record/tasks/database_tasks.rb +140 -113
- data/lib/active_record/tasks/mysql_database_tasks.rb +34 -36
- data/lib/active_record/tasks/postgresql_database_tasks.rb +24 -27
- data/lib/active_record/tasks/sqlite_database_tasks.rb +13 -10
- data/lib/active_record/test_databases.rb +5 -4
- data/lib/active_record/test_fixtures.rb +87 -20
- data/lib/active_record/timestamp.rb +4 -7
- data/lib/active_record/touch_later.rb +20 -21
- data/lib/active_record/transactions.rb +25 -72
- data/lib/active_record/type/adapter_specific_registry.rb +2 -5
- data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
- data/lib/active_record/type/serialized.rb +6 -3
- data/lib/active_record/type/time.rb +10 -0
- data/lib/active_record/type/type_map.rb +0 -1
- data/lib/active_record/type/unsigned_integer.rb +0 -1
- data/lib/active_record/type.rb +8 -2
- data/lib/active_record/type_caster/connection.rb +0 -1
- data/lib/active_record/type_caster/map.rb +8 -5
- data/lib/active_record/validations/associated.rb +1 -2
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/uniqueness.rb +24 -4
- data/lib/active_record/validations.rb +3 -3
- data/lib/active_record.rb +7 -13
- data/lib/arel/attributes/attribute.rb +4 -0
- data/lib/arel/collectors/bind.rb +5 -0
- data/lib/arel/collectors/composite.rb +8 -0
- data/lib/arel/collectors/sql_string.rb +7 -0
- data/lib/arel/collectors/substitute_binds.rb +7 -0
- data/lib/arel/nodes/binary.rb +82 -8
- data/lib/arel/nodes/bind_param.rb +8 -0
- data/lib/arel/nodes/casted.rb +21 -9
- data/lib/arel/nodes/equality.rb +6 -9
- data/lib/arel/nodes/grouping.rb +3 -0
- data/lib/arel/nodes/homogeneous_in.rb +76 -0
- data/lib/arel/nodes/in.rb +8 -1
- data/lib/arel/nodes/infix_operation.rb +13 -1
- data/lib/arel/nodes/join_source.rb +1 -1
- data/lib/arel/nodes/node.rb +7 -6
- data/lib/arel/nodes/ordering.rb +27 -0
- data/lib/arel/nodes/sql_literal.rb +3 -0
- data/lib/arel/nodes/table_alias.rb +7 -3
- data/lib/arel/nodes/unary.rb +0 -1
- data/lib/arel/nodes.rb +3 -1
- data/lib/arel/predications.rb +17 -24
- data/lib/arel/select_manager.rb +1 -2
- data/lib/arel/table.rb +13 -5
- data/lib/arel/visitors/dot.rb +14 -3
- data/lib/arel/visitors/mysql.rb +11 -1
- data/lib/arel/visitors/postgresql.rb +15 -5
- data/lib/arel/visitors/sqlite.rb +0 -1
- data/lib/arel/visitors/to_sql.rb +89 -79
- data/lib/arel/visitors/visitor.rb +0 -1
- data/lib/arel/visitors.rb +0 -7
- data/lib/arel.rb +5 -9
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +2 -0
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -4
- data/lib/rails/generators/active_record/migration.rb +6 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +38 -2
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- metadata +30 -29
- data/lib/active_record/attribute_decorators.rb +0 -90
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -297
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
- data/lib/active_record/define_callbacks.rb +0 -22
- data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
- data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
- data/lib/active_record/relation/where_clause_factory.rb +0 -33
- data/lib/arel/attributes.rb +0 -22
- data/lib/arel/visitors/depth_first.rb +0 -204
- data/lib/arel/visitors/ibm_db.rb +0 -34
- data/lib/arel/visitors/informix.rb +0 -62
- data/lib/arel/visitors/mssql.rb +0 -157
- data/lib/arel/visitors/oracle.rb +0 -159
- data/lib/arel/visitors/oracle12.rb +0 -66
- data/lib/arel/visitors/where_sql.rb +0 -23
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "
|
4
|
-
require "yaml"
|
3
|
+
require "active_support/configuration_file"
|
5
4
|
|
6
5
|
module ActiveRecord
|
7
6
|
class FixtureSet
|
@@ -29,6 +28,10 @@ module ActiveRecord
|
|
29
28
|
config_row["model_class"]
|
30
29
|
end
|
31
30
|
|
31
|
+
def ignored_fixtures
|
32
|
+
config_row["ignore"]
|
33
|
+
end
|
34
|
+
|
32
35
|
private
|
33
36
|
def rows
|
34
37
|
@rows ||= raw_rows.reject { |fixture_name, _| fixture_name == "_fixture" }
|
@@ -40,31 +43,21 @@ module ActiveRecord
|
|
40
43
|
if row
|
41
44
|
row.last
|
42
45
|
else
|
43
|
-
{ 'model_class': nil }
|
46
|
+
{ 'model_class': nil, 'ignore': nil }
|
44
47
|
end
|
45
48
|
end
|
46
49
|
end
|
47
50
|
|
48
51
|
def raw_rows
|
49
52
|
@raw_rows ||= begin
|
50
|
-
data =
|
53
|
+
data = ActiveSupport::ConfigurationFile.parse(@file, context:
|
54
|
+
ActiveRecord::FixtureSet::RenderContext.create_subclass.new.get_binding)
|
51
55
|
data ? validate(data).to_a : []
|
52
|
-
rescue
|
53
|
-
raise Fixture::FormatError,
|
56
|
+
rescue RuntimeError => error
|
57
|
+
raise Fixture::FormatError, error.message
|
54
58
|
end
|
55
59
|
end
|
56
60
|
|
57
|
-
def prepare_erb(content)
|
58
|
-
erb = ERB.new(content)
|
59
|
-
erb.filename = @file
|
60
|
-
erb
|
61
|
-
end
|
62
|
-
|
63
|
-
def render(content)
|
64
|
-
context = ActiveRecord::FixtureSet::RenderContext.create_subclass.new
|
65
|
-
prepare_erb(content).result(context.get_binding)
|
66
|
-
end
|
67
|
-
|
68
61
|
# Validate our unmarshalled data.
|
69
62
|
def validate(data)
|
70
63
|
unless Hash === data || YAML::Omap === data
|
@@ -21,8 +21,7 @@ module ActiveRecord
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def timestamp_column_names
|
24
|
-
@
|
25
|
-
%w(created_at created_on updated_at updated_on) & @model_class.column_names
|
24
|
+
@model_class.all_timestamp_attributes_in_model
|
26
25
|
end
|
27
26
|
|
28
27
|
def inheritance_column_name
|
@@ -48,7 +48,6 @@ module ActiveRecord
|
|
48
48
|
end
|
49
49
|
|
50
50
|
private
|
51
|
-
|
52
51
|
def model_metadata
|
53
52
|
@table_rows.model_metadata
|
54
53
|
end
|
@@ -113,12 +112,12 @@ module ActiveRecord
|
|
113
112
|
case association.macro
|
114
113
|
when :belongs_to
|
115
114
|
# Do not replace association name with association foreign key if they are named the same
|
116
|
-
fk_name =
|
115
|
+
fk_name = association.join_foreign_key
|
117
116
|
|
118
117
|
if association.name.to_s != fk_name && value = @row.delete(association.name.to_s)
|
119
118
|
if association.polymorphic? && value.sub!(/\s*\(([^\)]*)\)\s*$/, "")
|
120
119
|
# support polymorphic belongs_to as "label (Type)"
|
121
|
-
@row[association.
|
120
|
+
@row[association.join_foreign_type] = $1
|
122
121
|
end
|
123
122
|
|
124
123
|
fk_type = reflection_class.type_for_attribute(fk_name).type
|
@@ -10,7 +10,6 @@ require "active_record/fixture_set/file"
|
|
10
10
|
require "active_record/fixture_set/render_context"
|
11
11
|
require "active_record/fixture_set/table_rows"
|
12
12
|
require "active_record/test_fixtures"
|
13
|
-
require "active_record/errors"
|
14
13
|
|
15
14
|
module ActiveRecord
|
16
15
|
class FixtureClassNotFound < ActiveRecord::ActiveRecordError #:nodoc:
|
@@ -41,7 +40,7 @@ module ActiveRecord
|
|
41
40
|
# separated by a blank line for your viewing pleasure.
|
42
41
|
#
|
43
42
|
# Note: Fixtures are unordered. If you want ordered fixtures, use the omap YAML type.
|
44
|
-
# See
|
43
|
+
# See https://yaml.org/type/omap.html
|
45
44
|
# for the specification. You will need ordered fixtures when you have foreign key constraints
|
46
45
|
# on keys in the same table. This is commonly needed for tree structures. Example:
|
47
46
|
#
|
@@ -60,7 +59,7 @@ module ActiveRecord
|
|
60
59
|
# Since fixtures are a testing construct, we use them in our unit and functional tests. There
|
61
60
|
# are two ways to use the fixtures, but first let's take a look at a sample unit test:
|
62
61
|
#
|
63
|
-
# require
|
62
|
+
# require "test_helper"
|
64
63
|
#
|
65
64
|
# class WebSiteTest < ActiveSupport::TestCase
|
66
65
|
# test "web_site_count" do
|
@@ -182,7 +181,7 @@ module ActiveRecord
|
|
182
181
|
# end
|
183
182
|
# end
|
184
183
|
#
|
185
|
-
# If you preload your test database with all fixture data (probably by running
|
184
|
+
# If you preload your test database with all fixture data (probably by running <tt>bin/rails db:fixtures:load</tt>)
|
186
185
|
# and use transactional tests, then you may omit all fixtures declarations in your test cases since
|
187
186
|
# all the data's already there and every case rolls back its changes.
|
188
187
|
#
|
@@ -420,12 +419,35 @@ module ActiveRecord
|
|
420
419
|
#
|
421
420
|
# Any fixture labeled "DEFAULTS" is safely ignored.
|
422
421
|
#
|
422
|
+
# Besides using "DEFAULTS", you can also specify what fixtures will
|
423
|
+
# be ignored by setting "ignore" in "_fixture" section.
|
424
|
+
#
|
425
|
+
# # users.yml
|
426
|
+
# _fixture:
|
427
|
+
# ignore:
|
428
|
+
# - base
|
429
|
+
# # or use "ignore: base" when there is only one fixture needs to be ignored.
|
430
|
+
#
|
431
|
+
# base: &base
|
432
|
+
# admin: false
|
433
|
+
# introduction: "This is a default description"
|
434
|
+
#
|
435
|
+
# admin:
|
436
|
+
# <<: *base
|
437
|
+
# admin: true
|
438
|
+
#
|
439
|
+
# visitor:
|
440
|
+
# <<: *base
|
441
|
+
#
|
442
|
+
# In the above example, 'base' will be ignored when creating fixtures.
|
443
|
+
# This can be used for common attributes inheriting.
|
444
|
+
#
|
423
445
|
# == Configure the fixture model class
|
424
446
|
#
|
425
447
|
# It's possible to set the fixture's model class directly in the YAML file.
|
426
448
|
# This is helpful when fixtures are loaded outside tests and
|
427
449
|
# +set_fixture_class+ is not available (e.g.
|
428
|
-
# when running <tt>rails db:fixtures:load</tt>).
|
450
|
+
# when running <tt>bin/rails db:fixtures:load</tt>).
|
429
451
|
#
|
430
452
|
# _fixture:
|
431
453
|
# model_class: User
|
@@ -464,7 +486,6 @@ module ActiveRecord
|
|
464
486
|
end
|
465
487
|
|
466
488
|
private
|
467
|
-
|
468
489
|
def insert_class(class_names, name, klass)
|
469
490
|
# We only want to deal with AR objects.
|
470
491
|
if klass && klass < ActiveRecord::Base
|
@@ -564,13 +585,20 @@ module ActiveRecord
|
|
564
585
|
end
|
565
586
|
end
|
566
587
|
|
588
|
+
def signed_global_id(fixture_set_name, label, column_type: :integer, **options)
|
589
|
+
identifier = identify(label, column_type)
|
590
|
+
model_name = default_fixture_model_name(fixture_set_name)
|
591
|
+
uri = URI::GID.build([GlobalID.app, model_name, identifier, {}])
|
592
|
+
|
593
|
+
SignedGlobalID.new(uri, **options)
|
594
|
+
end
|
595
|
+
|
567
596
|
# Superclass for the evaluation contexts used by ERB fixtures.
|
568
597
|
def context_class
|
569
598
|
@context_class ||= Class.new
|
570
599
|
end
|
571
600
|
|
572
601
|
private
|
573
|
-
|
574
602
|
def read_and_insert(fixtures_directory, fixture_files, class_names, connection) # :nodoc:
|
575
603
|
fixtures_map = {}
|
576
604
|
fixture_sets = fixture_files.map do |fixture_set_name|
|
@@ -621,7 +649,7 @@ module ActiveRecord
|
|
621
649
|
end
|
622
650
|
end
|
623
651
|
|
624
|
-
attr_reader :table_name, :name, :fixtures, :model_class, :config
|
652
|
+
attr_reader :table_name, :name, :fixtures, :model_class, :ignored_fixtures, :config
|
625
653
|
|
626
654
|
def initialize(_, name, class_name, path, config = ActiveRecord::Base)
|
627
655
|
@name = name
|
@@ -654,8 +682,8 @@ module ActiveRecord
|
|
654
682
|
# Returns a hash of rows to be inserted. The key is the table, the value is
|
655
683
|
# a list of rows to insert to that table.
|
656
684
|
def table_rows
|
657
|
-
# allow
|
658
|
-
fixtures.
|
685
|
+
# allow specifying fixtures to be ignored by setting `ignore` in `_fixture` section
|
686
|
+
fixtures.except!(*ignored_fixtures)
|
659
687
|
|
660
688
|
TableRows.new(
|
661
689
|
table_name,
|
@@ -666,7 +694,6 @@ module ActiveRecord
|
|
666
694
|
end
|
667
695
|
|
668
696
|
private
|
669
|
-
|
670
697
|
def model_class=(class_name)
|
671
698
|
if class_name.is_a?(Class) # TODO: Should be an AR::Base type class, or any?
|
672
699
|
@model_class = class_name
|
@@ -675,6 +702,21 @@ module ActiveRecord
|
|
675
702
|
end
|
676
703
|
end
|
677
704
|
|
705
|
+
def ignored_fixtures=(base)
|
706
|
+
@ignored_fixtures =
|
707
|
+
case base
|
708
|
+
when Array
|
709
|
+
base
|
710
|
+
when String
|
711
|
+
[base]
|
712
|
+
else
|
713
|
+
[]
|
714
|
+
end
|
715
|
+
|
716
|
+
@ignored_fixtures << "DEFAULTS" unless @ignored_fixtures.include?("DEFAULTS")
|
717
|
+
@ignored_fixtures.compact
|
718
|
+
end
|
719
|
+
|
678
720
|
# Loads the fixtures from the YAML file at +path+.
|
679
721
|
# If the file sets the +model_class+ and current instance value is not set,
|
680
722
|
# it uses the file value.
|
@@ -686,6 +728,7 @@ module ActiveRecord
|
|
686
728
|
yaml_files.each_with_object({}) do |file, fixtures|
|
687
729
|
FixtureSet::File.open(file) do |fh|
|
688
730
|
self.model_class ||= fh.model_class if fh.model_class
|
731
|
+
self.ignored_fixtures ||= fh.ignored_fixtures
|
689
732
|
fh.each do |fixture_name, row|
|
690
733
|
fixtures[fixture_name] = ActiveRecord::Fixture.new(row, model_class)
|
691
734
|
end
|
@@ -730,9 +773,12 @@ module ActiveRecord
|
|
730
773
|
|
731
774
|
def find
|
732
775
|
raise FixtureClassNotFound, "No class attached to find." unless model_class
|
733
|
-
model_class.unscoped do
|
776
|
+
object = model_class.unscoped do
|
734
777
|
model_class.find(fixture[model_class.primary_key])
|
735
778
|
end
|
779
|
+
# Fixtures can't be eagerly loaded
|
780
|
+
object.instance_variable_set(:@strict_loading, false)
|
781
|
+
object
|
736
782
|
end
|
737
783
|
end
|
738
784
|
end
|
@@ -38,6 +38,8 @@ module ActiveRecord
|
|
38
38
|
extend ActiveSupport::Concern
|
39
39
|
|
40
40
|
included do
|
41
|
+
class_attribute :store_full_class_name, instance_writer: false, default: true
|
42
|
+
|
41
43
|
# Determines whether to store the full constant name including namespace when using STI.
|
42
44
|
# This is true, by default.
|
43
45
|
class_attribute :store_full_sti_class, instance_writer: false, default: true
|
@@ -52,7 +54,7 @@ module ActiveRecord
|
|
52
54
|
raise NotImplementedError, "#{self} is an abstract class and cannot be instantiated."
|
53
55
|
end
|
54
56
|
|
55
|
-
if
|
57
|
+
if _has_attribute?(inheritance_column)
|
56
58
|
subclass = subclass_from_attributes(attributes)
|
57
59
|
|
58
60
|
if subclass.nil? && scope_attributes = current_scope&.scope_for_create
|
@@ -162,12 +164,42 @@ module ActiveRecord
|
|
162
164
|
defined?(@abstract_class) && @abstract_class == true
|
163
165
|
end
|
164
166
|
|
167
|
+
# Returns the value to be stored in the inheritance column for STI.
|
165
168
|
def sti_name
|
166
|
-
store_full_sti_class ? name : name.demodulize
|
169
|
+
store_full_sti_class && store_full_class_name ? name : name.demodulize
|
167
170
|
end
|
168
171
|
|
172
|
+
# Returns the class for the provided +type_name+.
|
173
|
+
#
|
174
|
+
# It is used to find the class correspondent to the value stored in the inheritance column.
|
175
|
+
def sti_class_for(type_name)
|
176
|
+
if store_full_sti_class && store_full_class_name
|
177
|
+
ActiveSupport::Dependencies.constantize(type_name)
|
178
|
+
else
|
179
|
+
compute_type(type_name)
|
180
|
+
end
|
181
|
+
rescue NameError
|
182
|
+
raise SubclassNotFound,
|
183
|
+
"The single-table inheritance mechanism failed to locate the subclass: '#{type_name}'. " \
|
184
|
+
"This error is raised because the column '#{inheritance_column}' is reserved for storing the class in case of inheritance. " \
|
185
|
+
"Please rename this column if you didn't intend it to be used for storing the inheritance class " \
|
186
|
+
"or overwrite #{name}.inheritance_column to use another column for that information."
|
187
|
+
end
|
188
|
+
|
189
|
+
# Returns the value to be stored in the polymorphic type column for Polymorphic Associations.
|
169
190
|
def polymorphic_name
|
170
|
-
base_class.name
|
191
|
+
store_full_class_name ? base_class.name : base_class.name.demodulize
|
192
|
+
end
|
193
|
+
|
194
|
+
# Returns the class for the provided +name+.
|
195
|
+
#
|
196
|
+
# It is used to find the class correspondent to the value stored in the polymorphic type column.
|
197
|
+
def polymorphic_class_for(name)
|
198
|
+
if store_full_class_name
|
199
|
+
ActiveSupport::Dependencies.constantize(name)
|
200
|
+
else
|
201
|
+
compute_type(name)
|
202
|
+
end
|
171
203
|
end
|
172
204
|
|
173
205
|
def inherited(subclass)
|
@@ -176,7 +208,6 @@ module ActiveRecord
|
|
176
208
|
end
|
177
209
|
|
178
210
|
protected
|
179
|
-
|
180
211
|
# Returns the class type of the record using the current module as a prefix. So descendants of
|
181
212
|
# MyApp::Business::Account would appear as MyApp::Business::AccountSubclass.
|
182
213
|
def compute_type(type_name)
|
@@ -208,7 +239,6 @@ module ActiveRecord
|
|
208
239
|
end
|
209
240
|
|
210
241
|
private
|
211
|
-
|
212
242
|
# Called by +instantiate+ to decide which class to use for a new
|
213
243
|
# record instance. For single-table inheritance, we check the record
|
214
244
|
# for a +type+ column and return the corresponding class.
|
@@ -221,32 +251,22 @@ module ActiveRecord
|
|
221
251
|
end
|
222
252
|
|
223
253
|
def using_single_table_inheritance?(record)
|
224
|
-
record[inheritance_column].present? &&
|
254
|
+
record[inheritance_column].present? && _has_attribute?(inheritance_column)
|
225
255
|
end
|
226
256
|
|
227
257
|
def find_sti_class(type_name)
|
228
258
|
type_name = base_class.type_for_attribute(inheritance_column).cast(type_name)
|
229
|
-
subclass =
|
230
|
-
|
231
|
-
ActiveSupport::Dependencies.constantize(type_name)
|
232
|
-
else
|
233
|
-
compute_type(type_name)
|
234
|
-
end
|
235
|
-
rescue NameError
|
236
|
-
raise SubclassNotFound,
|
237
|
-
"The single-table inheritance mechanism failed to locate the subclass: '#{type_name}'. " \
|
238
|
-
"This error is raised because the column '#{inheritance_column}' is reserved for storing the class in case of inheritance. " \
|
239
|
-
"Please rename this column if you didn't intend it to be used for storing the inheritance class " \
|
240
|
-
"or overwrite #{name}.inheritance_column to use another column for that information."
|
241
|
-
end
|
259
|
+
subclass = sti_class_for(type_name)
|
260
|
+
|
242
261
|
unless subclass == self || descendants.include?(subclass)
|
243
262
|
raise SubclassNotFound, "Invalid single-table inheritance type: #{subclass.name} is not a subclass of #{name}"
|
244
263
|
end
|
264
|
+
|
245
265
|
subclass
|
246
266
|
end
|
247
267
|
|
248
268
|
def type_condition(table = arel_table)
|
249
|
-
sti_column =
|
269
|
+
sti_column = table[inheritance_column]
|
250
270
|
sti_names = ([self] + descendants).map(&:sti_name)
|
251
271
|
|
252
272
|
predicate_builder.build(sti_column, sti_names)
|
@@ -272,7 +292,6 @@ module ActiveRecord
|
|
272
292
|
end
|
273
293
|
|
274
294
|
private
|
275
|
-
|
276
295
|
def initialize_internals_callback
|
277
296
|
super
|
278
297
|
ensure_proper_type
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/core_ext/enumerable"
|
4
|
+
|
3
5
|
module ActiveRecord
|
4
6
|
class InsertAll # :nodoc:
|
5
7
|
attr_reader :model, :connection, :inserts, :keys
|
@@ -8,13 +10,19 @@ module ActiveRecord
|
|
8
10
|
def initialize(model, inserts, on_duplicate:, returning: nil, unique_by: nil)
|
9
11
|
raise ArgumentError, "Empty list of attributes passed" if inserts.blank?
|
10
12
|
|
11
|
-
@model, @connection, @inserts, @keys = model, model.connection, inserts, inserts.first.keys.map(&:to_s)
|
13
|
+
@model, @connection, @inserts, @keys = model, model.connection, inserts, inserts.first.keys.map(&:to_s)
|
12
14
|
@on_duplicate, @returning, @unique_by = on_duplicate, returning, unique_by
|
13
15
|
|
16
|
+
if model.scope_attributes?
|
17
|
+
@scope_attributes = model.scope_attributes
|
18
|
+
@keys |= @scope_attributes.keys
|
19
|
+
end
|
20
|
+
@keys = @keys.to_set
|
21
|
+
|
14
22
|
@returning = (connection.supports_insert_returning? ? primary_keys : false) if @returning.nil?
|
15
23
|
@returning = false if @returning == []
|
16
24
|
|
17
|
-
@unique_by = find_unique_index_for(unique_by)
|
25
|
+
@unique_by = find_unique_index_for(unique_by)
|
18
26
|
@on_duplicate = :skip if @on_duplicate == :update && updatable_columns.empty?
|
19
27
|
|
20
28
|
ensure_valid_options_for_connection!
|
@@ -32,7 +40,7 @@ module ActiveRecord
|
|
32
40
|
end
|
33
41
|
|
34
42
|
def primary_keys
|
35
|
-
Array(model.
|
43
|
+
Array(connection.schema_cache.primary_keys(model.table_name))
|
36
44
|
end
|
37
45
|
|
38
46
|
|
@@ -47,6 +55,8 @@ module ActiveRecord
|
|
47
55
|
def map_key_with_value
|
48
56
|
inserts.map do |attributes|
|
49
57
|
attributes = attributes.stringify_keys
|
58
|
+
attributes.merge!(scope_attributes) if scope_attributes
|
59
|
+
|
50
60
|
verify_attributes(attributes)
|
51
61
|
|
52
62
|
keys.map do |key|
|
@@ -56,13 +66,24 @@ module ActiveRecord
|
|
56
66
|
end
|
57
67
|
|
58
68
|
private
|
69
|
+
attr_reader :scope_attributes
|
70
|
+
|
59
71
|
def find_unique_index_for(unique_by)
|
60
|
-
|
72
|
+
if !connection.supports_insert_conflict_target?
|
73
|
+
return if unique_by.nil?
|
74
|
+
|
75
|
+
raise ArgumentError, "#{connection.class} does not support :unique_by"
|
76
|
+
end
|
77
|
+
|
78
|
+
name_or_columns = unique_by || model.primary_key
|
79
|
+
match = Array(name_or_columns).map(&:to_s)
|
61
80
|
|
62
81
|
if index = unique_indexes.find { |i| match.include?(i.name) || i.columns == match }
|
63
82
|
index
|
83
|
+
elsif match == primary_keys
|
84
|
+
unique_by.nil? ? nil : ActiveRecord::ConnectionAdapters::IndexDefinition.new(model.table_name, "#{model.table_name}_primary_key", true, match)
|
64
85
|
else
|
65
|
-
raise ArgumentError, "No unique index found for #{
|
86
|
+
raise ArgumentError, "No unique index found for #{name_or_columns}"
|
66
87
|
end
|
67
88
|
end
|
68
89
|
|
@@ -120,7 +141,7 @@ module ActiveRecord
|
|
120
141
|
end
|
121
142
|
|
122
143
|
def into
|
123
|
-
"INTO #{model.quoted_table_name}(#{columns_list})"
|
144
|
+
"INTO #{model.quoted_table_name} (#{columns_list})"
|
124
145
|
end
|
125
146
|
|
126
147
|
def values_list
|
@@ -130,7 +151,7 @@ module ActiveRecord
|
|
130
151
|
connection.with_yaml_fallback(types[key].serialize(value))
|
131
152
|
end
|
132
153
|
|
133
|
-
Arel::
|
154
|
+
connection.visitor.compile(Arel::Nodes::ValuesList.new(values_list))
|
134
155
|
end
|
135
156
|
|
136
157
|
def returning
|
@@ -151,9 +172,21 @@ module ActiveRecord
|
|
151
172
|
quote_columns(insert_all.updatable_columns)
|
152
173
|
end
|
153
174
|
|
175
|
+
def touch_model_timestamps_unless(&block)
|
176
|
+
model.send(:timestamp_attributes_for_update_in_model).map do |column_name|
|
177
|
+
if touch_timestamp_attribute?(column_name)
|
178
|
+
"#{column_name}=(CASE WHEN (#{updatable_columns.map(&block).join(" AND ")}) THEN #{model.quoted_table_name}.#{column_name} ELSE CURRENT_TIMESTAMP END),"
|
179
|
+
end
|
180
|
+
end.compact.join
|
181
|
+
end
|
182
|
+
|
154
183
|
private
|
155
184
|
attr_reader :connection, :insert_all
|
156
185
|
|
186
|
+
def touch_timestamp_attribute?(column_name)
|
187
|
+
update_duplicates? && !insert_all.updatable_columns.include?(column_name)
|
188
|
+
end
|
189
|
+
|
157
190
|
def columns_list
|
158
191
|
format_columns(insert_all.keys)
|
159
192
|
end
|
@@ -164,11 +197,11 @@ module ActiveRecord
|
|
164
197
|
unknown_column = (keys - columns.keys).first
|
165
198
|
raise UnknownAttributeError.new(model.new, unknown_column) if unknown_column
|
166
199
|
|
167
|
-
keys.
|
200
|
+
keys.index_with { |key| model.type_for_attribute(key) }
|
168
201
|
end
|
169
202
|
|
170
203
|
def format_columns(columns)
|
171
|
-
quote_columns(columns).join(",")
|
204
|
+
columns.respond_to?(:map) ? quote_columns(columns).join(",") : columns
|
172
205
|
end
|
173
206
|
|
174
207
|
def quote_columns(columns)
|
@@ -93,7 +93,7 @@ module ActiveRecord
|
|
93
93
|
# cache_version, but this method can be overwritten to return something else.
|
94
94
|
#
|
95
95
|
# Note, this method will return nil if ActiveRecord::Base.cache_versioning is set to
|
96
|
-
# +false
|
96
|
+
# +false+.
|
97
97
|
def cache_version
|
98
98
|
return unless cache_versioning
|
99
99
|
|
@@ -104,10 +104,8 @@ module ActiveRecord
|
|
104
104
|
elsif timestamp = updated_at
|
105
105
|
timestamp.utc.to_s(cache_timestamp_format)
|
106
106
|
end
|
107
|
-
|
108
|
-
|
109
|
-
raise ActiveModel::MissingAttributeError, "missing attribute: updated_at"
|
110
|
-
end
|
107
|
+
elsif self.class.has_attribute?("updated_at")
|
108
|
+
raise ActiveModel::MissingAttributeError, "missing attribute: updated_at"
|
111
109
|
end
|
112
110
|
end
|
113
111
|
|
@@ -6,8 +6,17 @@ require "active_record/scoping/named"
|
|
6
6
|
module ActiveRecord
|
7
7
|
# This class is used to create a table that keeps track of values and keys such
|
8
8
|
# as which environment migrations were run in.
|
9
|
+
#
|
10
|
+
# This is enabled by default. To disable this functionality set
|
11
|
+
# `use_metadata_table` to false in your database configuration.
|
9
12
|
class InternalMetadata < ActiveRecord::Base # :nodoc:
|
13
|
+
self.record_timestamps = true
|
14
|
+
|
10
15
|
class << self
|
16
|
+
def enabled?
|
17
|
+
ActiveRecord::Base.connection.use_metadata_table?
|
18
|
+
end
|
19
|
+
|
11
20
|
def _internal?
|
12
21
|
true
|
13
22
|
end
|
@@ -21,24 +30,24 @@ module ActiveRecord
|
|
21
30
|
end
|
22
31
|
|
23
32
|
def []=(key, value)
|
33
|
+
return unless enabled?
|
34
|
+
|
24
35
|
find_or_initialize_by(key: key).update!(value: value)
|
25
36
|
end
|
26
37
|
|
27
38
|
def [](key)
|
28
|
-
|
29
|
-
end
|
39
|
+
return unless enabled?
|
30
40
|
|
31
|
-
|
32
|
-
connection.table_exists?(table_name)
|
41
|
+
where(key: key).pluck(:value).first
|
33
42
|
end
|
34
43
|
|
35
44
|
# Creates an internal metadata table with columns +key+ and +value+
|
36
45
|
def create_table
|
37
|
-
unless
|
38
|
-
key_options = connection.internal_string_options_for_primary_key
|
46
|
+
return unless enabled?
|
39
47
|
|
48
|
+
unless connection.table_exists?(table_name)
|
40
49
|
connection.create_table(table_name, id: false) do |t|
|
41
|
-
t.string :key,
|
50
|
+
t.string :key, **connection.internal_string_options_for_primary_key
|
42
51
|
t.string :value
|
43
52
|
t.timestamps
|
44
53
|
end
|
@@ -46,6 +55,8 @@ module ActiveRecord
|
|
46
55
|
end
|
47
56
|
|
48
57
|
def drop_table
|
58
|
+
return unless enabled?
|
59
|
+
|
49
60
|
connection.drop_table table_name, if_exists: true
|
50
61
|
end
|
51
62
|
end
|
@@ -1,13 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
|
-
module LegacyYamlAdapter
|
4
|
+
module LegacyYamlAdapter # :nodoc:
|
5
5
|
def self.convert(klass, coder)
|
6
6
|
return coder unless coder.is_a?(Psych::Coder)
|
7
7
|
|
8
8
|
case coder["active_record_yaml_version"]
|
9
9
|
when 1, 2 then coder
|
10
10
|
else
|
11
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
12
|
+
YAML loading from legacy format older than Rails 5.0 is deprecated
|
13
|
+
and will be removed in Rails 7.0.
|
14
|
+
MSG
|
11
15
|
if coder["attributes"].is_a?(ActiveModel::AttributeSet)
|
12
16
|
Rails420.convert(klass, coder)
|
13
17
|
else
|
@@ -16,7 +20,7 @@ module ActiveRecord
|
|
16
20
|
end
|
17
21
|
end
|
18
22
|
|
19
|
-
module Rails420
|
23
|
+
module Rails420 # :nodoc:
|
20
24
|
def self.convert(klass, coder)
|
21
25
|
attribute_set = coder["attributes"]
|
22
26
|
|
@@ -32,7 +36,7 @@ module ActiveRecord
|
|
32
36
|
end
|
33
37
|
end
|
34
38
|
|
35
|
-
module Rails41
|
39
|
+
module Rails41 # :nodoc:
|
36
40
|
def self.convert(klass, coder)
|
37
41
|
attributes = klass.attributes_builder
|
38
42
|
.build_from_database(coder["attributes"])
|