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
@@ -1,7 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
class TableMetadata # :nodoc:
|
3
|
-
delegate :foreign_type, :foreign_key, to: :association, prefix: true
|
4
|
-
delegate :association_primary_key, to: :association
|
5
|
+
delegate :foreign_type, :foreign_key, :join_primary_key, :join_foreign_key, to: :association, prefix: true
|
5
6
|
|
6
7
|
def initialize(klass, arel_table, association = nil)
|
7
8
|
@klass = klass
|
@@ -29,7 +30,7 @@ module ActiveRecord
|
|
29
30
|
|
30
31
|
def type(column_name)
|
31
32
|
if klass
|
32
|
-
klass.type_for_attribute(column_name
|
33
|
+
klass.type_for_attribute(column_name)
|
33
34
|
else
|
34
35
|
Type.default_value
|
35
36
|
end
|
@@ -64,6 +65,14 @@ module ActiveRecord
|
|
64
65
|
association && association.polymorphic?
|
65
66
|
end
|
66
67
|
|
68
|
+
def aggregated_with?(aggregation_name)
|
69
|
+
klass && reflect_on_aggregation(aggregation_name)
|
70
|
+
end
|
71
|
+
|
72
|
+
def reflect_on_aggregation(aggregation_name)
|
73
|
+
klass.reflect_on_aggregation(aggregation_name)
|
74
|
+
end
|
75
|
+
|
67
76
|
# TODO Change this to private once we've dropped Ruby 2.2 support.
|
68
77
|
# Workaround for Ruby 2.2 "private attribute?" warning.
|
69
78
|
protected
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module Tasks # :nodoc:
|
3
5
|
class DatabaseAlreadyExists < StandardError; end # :nodoc:
|
@@ -52,10 +54,10 @@ module ActiveRecord
|
|
52
54
|
|
53
55
|
def check_protected_environments!
|
54
56
|
unless ENV["DISABLE_DATABASE_ENVIRONMENT_CHECK"]
|
55
|
-
current = ActiveRecord::
|
56
|
-
stored = ActiveRecord::
|
57
|
+
current = ActiveRecord::Base.connection.migration_context.current_environment
|
58
|
+
stored = ActiveRecord::Base.connection.migration_context.last_stored_environment
|
57
59
|
|
58
|
-
if ActiveRecord::
|
60
|
+
if ActiveRecord::Base.connection.migration_context.protected_environment?
|
59
61
|
raise ActiveRecord::ProtectedEnvironmentError.new(stored)
|
60
62
|
end
|
61
63
|
|
@@ -71,9 +73,9 @@ module ActiveRecord
|
|
71
73
|
@tasks[pattern] = task
|
72
74
|
end
|
73
75
|
|
74
|
-
register_task(/mysql/, ActiveRecord::Tasks::MySQLDatabaseTasks)
|
75
|
-
register_task(/postgresql/, ActiveRecord::Tasks::PostgreSQLDatabaseTasks)
|
76
|
-
register_task(/sqlite/, ActiveRecord::Tasks::SQLiteDatabaseTasks)
|
76
|
+
register_task(/mysql/, "ActiveRecord::Tasks::MySQLDatabaseTasks")
|
77
|
+
register_task(/postgresql/, "ActiveRecord::Tasks::PostgreSQLDatabaseTasks")
|
78
|
+
register_task(/sqlite/, "ActiveRecord::Tasks::SQLiteDatabaseTasks")
|
77
79
|
|
78
80
|
def db_dir
|
79
81
|
@db_dir ||= Rails.application.config.paths["db"].first
|
@@ -120,7 +122,7 @@ module ActiveRecord
|
|
120
122
|
$stderr.puts "Database '#{configuration['database']}' already exists"
|
121
123
|
rescue Exception => error
|
122
124
|
$stderr.puts error
|
123
|
-
$stderr.puts "Couldn't create database
|
125
|
+
$stderr.puts "Couldn't create '#{configuration['database']}' database. Please check your configuration."
|
124
126
|
raise
|
125
127
|
end
|
126
128
|
|
@@ -162,13 +164,12 @@ module ActiveRecord
|
|
162
164
|
end
|
163
165
|
|
164
166
|
def migrate
|
165
|
-
|
167
|
+
check_target_version
|
166
168
|
|
167
|
-
verbose = ENV["VERBOSE"] ? ENV["VERBOSE"]
|
168
|
-
version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
|
169
|
+
verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] != "false" : true
|
169
170
|
scope = ENV["SCOPE"]
|
170
171
|
verbose_was, Migration.verbose = Migration.verbose, verbose
|
171
|
-
|
172
|
+
Base.connection.migration_context.migrate(target_version) do |migration|
|
172
173
|
scope.blank? || scope == migration.scope
|
173
174
|
end
|
174
175
|
ActiveRecord::Base.clear_cache!
|
@@ -176,6 +177,16 @@ module ActiveRecord
|
|
176
177
|
Migration.verbose = verbose_was
|
177
178
|
end
|
178
179
|
|
180
|
+
def check_target_version
|
181
|
+
if target_version && !(Migration::MigrationFilenameRegexp.match?(ENV["VERSION"]) || /\A\d+\z/.match?(ENV["VERSION"]))
|
182
|
+
raise "Invalid format of target version: `VERSION=#{ENV['VERSION']}`"
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def target_version
|
187
|
+
ENV["VERSION"].to_i if ENV["VERSION"] && !ENV["VERSION"].empty?
|
188
|
+
end
|
189
|
+
|
179
190
|
def charset_current(environment = env)
|
180
191
|
charset ActiveRecord::Base.configurations[environment]
|
181
192
|
end
|
@@ -223,22 +234,22 @@ module ActiveRecord
|
|
223
234
|
class_for_adapter(configuration["adapter"]).new(*arguments).structure_load(filename, structure_load_flags)
|
224
235
|
end
|
225
236
|
|
226
|
-
def load_schema(configuration, format = ActiveRecord::Base.schema_format, file = nil) # :nodoc:
|
237
|
+
def load_schema(configuration, format = ActiveRecord::Base.schema_format, file = nil, environment = env) # :nodoc:
|
227
238
|
file ||= schema_file(format)
|
228
239
|
|
240
|
+
check_schema_file(file)
|
241
|
+
ActiveRecord::Base.establish_connection(configuration)
|
242
|
+
|
229
243
|
case format
|
230
244
|
when :ruby
|
231
|
-
check_schema_file(file)
|
232
|
-
ActiveRecord::Base.establish_connection(configuration)
|
233
245
|
load(file)
|
234
246
|
when :sql
|
235
|
-
check_schema_file(file)
|
236
247
|
structure_load(configuration, file)
|
237
248
|
else
|
238
249
|
raise ArgumentError, "unknown format #{format.inspect}"
|
239
250
|
end
|
240
251
|
ActiveRecord::InternalMetadata.create_table
|
241
|
-
ActiveRecord::InternalMetadata[:environment] =
|
252
|
+
ActiveRecord::InternalMetadata[:environment] = environment
|
242
253
|
end
|
243
254
|
|
244
255
|
def schema_file(format = ActiveRecord::Base.schema_format)
|
@@ -251,16 +262,16 @@ module ActiveRecord
|
|
251
262
|
end
|
252
263
|
|
253
264
|
def load_schema_current(format = ActiveRecord::Base.schema_format, file = nil, environment = env)
|
254
|
-
each_current_configuration(environment) { |configuration|
|
255
|
-
load_schema configuration, format, file
|
265
|
+
each_current_configuration(environment) { |configuration, configuration_environment|
|
266
|
+
load_schema configuration, format, file, configuration_environment
|
256
267
|
}
|
257
268
|
ActiveRecord::Base.establish_connection(environment.to_sym)
|
258
269
|
end
|
259
270
|
|
260
271
|
def check_schema_file(filename)
|
261
272
|
unless File.exist?(filename)
|
262
|
-
message = %{#{filename} doesn't exist yet. Run `rails db:migrate` to create it, then try again.}
|
263
|
-
message << %{ If you do not intend to use a database, you should instead alter #{Rails.root}/config/application.rb to limit the frameworks that will be loaded.} if defined?(::Rails)
|
273
|
+
message = %{#{filename} doesn't exist yet. Run `rails db:migrate` to create it, then try again.}.dup
|
274
|
+
message << %{ If you do not intend to use a database, you should instead alter #{Rails.root}/config/application.rb to limit the frameworks that will be loaded.} if defined?(::Rails.root)
|
264
275
|
Kernel.abort message
|
265
276
|
end
|
266
277
|
end
|
@@ -288,20 +299,21 @@ module ActiveRecord
|
|
288
299
|
private
|
289
300
|
|
290
301
|
def class_for_adapter(adapter)
|
291
|
-
|
292
|
-
unless
|
302
|
+
_key, task = @tasks.each_pair.detect { |pattern, _task| adapter[pattern] }
|
303
|
+
unless task
|
293
304
|
raise DatabaseNotSupported, "Rake tasks not supported by '#{adapter}' adapter"
|
294
305
|
end
|
295
|
-
|
306
|
+
task.is_a?(String) ? task.constantize : task
|
296
307
|
end
|
297
308
|
|
298
309
|
def each_current_configuration(environment)
|
299
310
|
environments = [environment]
|
300
311
|
environments << "test" if environment == "development"
|
301
312
|
|
302
|
-
|
303
|
-
|
304
|
-
|
313
|
+
ActiveRecord::Base.configurations.slice(*environments).each do |configuration_environment, configuration|
|
314
|
+
next unless configuration["database"]
|
315
|
+
|
316
|
+
yield configuration, configuration_environment
|
305
317
|
end
|
306
318
|
end
|
307
319
|
|
@@ -1,8 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module Tasks # :nodoc:
|
3
5
|
class MySQLDatabaseTasks # :nodoc:
|
4
|
-
ACCESS_DENIED_ERROR = 1045
|
5
|
-
|
6
6
|
delegate :connection, :establish_connection, to: ActiveRecord::Base
|
7
7
|
|
8
8
|
def initialize(configuration)
|
@@ -19,20 +19,6 @@ module ActiveRecord
|
|
19
19
|
else
|
20
20
|
raise
|
21
21
|
end
|
22
|
-
rescue error_class => error
|
23
|
-
if error.respond_to?(:errno) && error.errno == ACCESS_DENIED_ERROR
|
24
|
-
$stdout.print error.message
|
25
|
-
establish_connection root_configuration_without_database
|
26
|
-
connection.create_database configuration["database"], creation_options
|
27
|
-
if configuration["username"] != "root"
|
28
|
-
connection.execute grant_statement.gsub(/\s+/, " ").strip
|
29
|
-
end
|
30
|
-
establish_connection configuration
|
31
|
-
else
|
32
|
-
$stderr.puts error.inspect
|
33
|
-
$stderr.puts "Couldn't create database for #{configuration.inspect}, #{creation_options.inspect}"
|
34
|
-
$stderr.puts "(If you set the charset manually, make sure you have a matching collation)" if configuration["encoding"]
|
35
|
-
end
|
36
22
|
end
|
37
23
|
|
38
24
|
def drop
|
@@ -59,8 +45,14 @@ module ActiveRecord
|
|
59
45
|
args.concat(["--no-data"])
|
60
46
|
args.concat(["--routines"])
|
61
47
|
args.concat(["--skip-comments"])
|
62
|
-
|
48
|
+
|
49
|
+
ignore_tables = ActiveRecord::SchemaDumper.ignore_tables
|
50
|
+
if ignore_tables.any?
|
51
|
+
args += ignore_tables.map { |table| "--ignore-table=#{configuration['database']}.#{table}" }
|
52
|
+
end
|
53
|
+
|
63
54
|
args.concat(["#{configuration['database']}"])
|
55
|
+
args.unshift(*extra_flags) if extra_flags
|
64
56
|
|
65
57
|
run_cmd("mysqldump", args, "dumping")
|
66
58
|
end
|
@@ -69,7 +61,7 @@ module ActiveRecord
|
|
69
61
|
args = prepare_command_options
|
70
62
|
args.concat(["--execute", %{SET FOREIGN_KEY_CHECKS = 0; SOURCE #{filename}; SET FOREIGN_KEY_CHECKS = 1}])
|
71
63
|
args.concat(["--database", "#{configuration['database']}"])
|
72
|
-
args.
|
64
|
+
args.unshift(*extra_flags) if extra_flags
|
73
65
|
|
74
66
|
run_cmd("mysql", args, "loading")
|
75
67
|
end
|
@@ -91,37 +83,6 @@ module ActiveRecord
|
|
91
83
|
end
|
92
84
|
end
|
93
85
|
|
94
|
-
def error_class
|
95
|
-
if configuration["adapter"].include?("jdbc")
|
96
|
-
require "active_record/railties/jdbcmysql_error"
|
97
|
-
ArJdbcMySQL::Error
|
98
|
-
elsif defined?(Mysql2)
|
99
|
-
Mysql2::Error
|
100
|
-
else
|
101
|
-
StandardError
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
def grant_statement
|
106
|
-
<<-SQL
|
107
|
-
GRANT ALL PRIVILEGES ON `#{configuration['database']}`.*
|
108
|
-
TO '#{configuration['username']}'@'localhost'
|
109
|
-
IDENTIFIED BY '#{configuration['password']}' WITH GRANT OPTION;
|
110
|
-
SQL
|
111
|
-
end
|
112
|
-
|
113
|
-
def root_configuration_without_database
|
114
|
-
configuration_without_database.merge(
|
115
|
-
"username" => "root",
|
116
|
-
"password" => root_password
|
117
|
-
)
|
118
|
-
end
|
119
|
-
|
120
|
-
def root_password
|
121
|
-
$stdout.print "Please provide the root password for your MySQL installation\n>"
|
122
|
-
$stdin.gets.strip
|
123
|
-
end
|
124
|
-
|
125
86
|
def prepare_command_options
|
126
87
|
args = {
|
127
88
|
"host" => "--host",
|
@@ -145,7 +106,7 @@ IDENTIFIED BY '#{configuration['password']}' WITH GRANT OPTION;
|
|
145
106
|
end
|
146
107
|
|
147
108
|
def run_cmd_error(cmd, args, action)
|
148
|
-
msg = "failed to execute: `#{cmd}`\n"
|
109
|
+
msg = "failed to execute: `#{cmd}`\n".dup
|
149
110
|
msg << "Please check the output above for any errors and make sure that `#{cmd}` is installed in your PATH and has proper permissions.\n\n"
|
150
111
|
msg
|
151
112
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "tempfile"
|
2
4
|
|
3
5
|
module ActiveRecord
|
@@ -20,7 +22,7 @@ module ActiveRecord
|
|
20
22
|
configuration.merge("encoding" => encoding)
|
21
23
|
establish_connection configuration
|
22
24
|
rescue ActiveRecord::StatementInvalid => error
|
23
|
-
if
|
25
|
+
if error.cause.is_a?(PG::DuplicateDatabase)
|
24
26
|
raise DatabaseAlreadyExists
|
25
27
|
else
|
26
28
|
raise
|
@@ -66,6 +68,12 @@ module ActiveRecord
|
|
66
68
|
"--schema=#{part.strip}"
|
67
69
|
end
|
68
70
|
end
|
71
|
+
|
72
|
+
ignore_tables = ActiveRecord::SchemaDumper.ignore_tables
|
73
|
+
if ignore_tables.any?
|
74
|
+
args += ignore_tables.flat_map { |table| ["-T", table] }
|
75
|
+
end
|
76
|
+
|
69
77
|
args << configuration["database"]
|
70
78
|
run_cmd("pg_dump", args, "dumping")
|
71
79
|
remove_sql_header_comments(filename)
|
@@ -109,7 +117,7 @@ module ActiveRecord
|
|
109
117
|
end
|
110
118
|
|
111
119
|
def run_cmd_error(cmd, args, action)
|
112
|
-
msg = "failed to execute:\n"
|
120
|
+
msg = "failed to execute:\n".dup
|
113
121
|
msg << "#{cmd} #{args.join(' ')}\n\n"
|
114
122
|
msg << "Please check the output above for any errors and make sure that `#{cmd}` is installed in your PATH and has proper permissions.\n\n"
|
115
123
|
msg
|
@@ -128,7 +136,7 @@ module ActiveRecord
|
|
128
136
|
ensure
|
129
137
|
tempfile.close
|
130
138
|
end
|
131
|
-
FileUtils.
|
139
|
+
FileUtils.cp(tempfile.path, filename)
|
132
140
|
end
|
133
141
|
end
|
134
142
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module Tasks # :nodoc:
|
3
5
|
class SQLiteDatabaseTasks # :nodoc:
|
@@ -36,9 +38,18 @@ module ActiveRecord
|
|
36
38
|
end
|
37
39
|
|
38
40
|
def structure_dump(filename, extra_flags)
|
39
|
-
|
40
|
-
|
41
|
-
|
41
|
+
args = []
|
42
|
+
args.concat(Array(extra_flags)) if extra_flags
|
43
|
+
args << configuration["database"]
|
44
|
+
|
45
|
+
ignore_tables = ActiveRecord::SchemaDumper.ignore_tables
|
46
|
+
if ignore_tables.any?
|
47
|
+
condition = ignore_tables.map { |table| connection.quote(table) }.join(", ")
|
48
|
+
args << "SELECT sql FROM sqlite_master WHERE tbl_name NOT IN (#{condition}) ORDER BY tbl_name, type DESC, name"
|
49
|
+
else
|
50
|
+
args << ".schema"
|
51
|
+
end
|
52
|
+
run_cmd("sqlite3", args, filename)
|
42
53
|
end
|
43
54
|
|
44
55
|
def structure_load(filename, extra_flags)
|
@@ -56,6 +67,17 @@ module ActiveRecord
|
|
56
67
|
def root
|
57
68
|
@root
|
58
69
|
end
|
70
|
+
|
71
|
+
def run_cmd(cmd, args, out)
|
72
|
+
fail run_cmd_error(cmd, args) unless Kernel.system(cmd, *args, out: out)
|
73
|
+
end
|
74
|
+
|
75
|
+
def run_cmd_error(cmd, args)
|
76
|
+
msg = "failed to execute:\n".dup
|
77
|
+
msg << "#{cmd} #{args.join(' ')}\n\n"
|
78
|
+
msg << "Please check the output above for any errors and make sure that `#{cmd}` is installed in your PATH and has proper permissions.\n\n"
|
79
|
+
msg
|
80
|
+
end
|
59
81
|
end
|
60
82
|
end
|
61
83
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module ActiveRecord
|
3
4
|
# = Active Record \Timestamp
|
4
5
|
#
|
@@ -43,8 +44,7 @@ module ActiveRecord
|
|
43
44
|
extend ActiveSupport::Concern
|
44
45
|
|
45
46
|
included do
|
46
|
-
class_attribute :record_timestamps
|
47
|
-
self.record_timestamps = true
|
47
|
+
class_attribute :record_timestamps, default: true
|
48
48
|
end
|
49
49
|
|
50
50
|
def initialize_dup(other) # :nodoc:
|
@@ -52,7 +52,14 @@ module ActiveRecord
|
|
52
52
|
clear_timestamp_attributes
|
53
53
|
end
|
54
54
|
|
55
|
-
|
55
|
+
module ClassMethods # :nodoc:
|
56
|
+
def touch_attributes_with_time(*names, time: nil)
|
57
|
+
attribute_names = timestamp_attributes_for_update_in_model
|
58
|
+
attribute_names |= names.map(&:to_s)
|
59
|
+
time ||= current_time_from_proper_timezone
|
60
|
+
attribute_names.each_with_object({}) { |attr_name, result| result[attr_name] = time }
|
61
|
+
end
|
62
|
+
|
56
63
|
private
|
57
64
|
def timestamp_attributes_for_create_in_model
|
58
65
|
timestamp_attributes_for_create.select { |c| column_names.include?(c) }
|
@@ -87,7 +94,7 @@ module ActiveRecord
|
|
87
94
|
|
88
95
|
all_timestamp_attributes_in_model.each do |column|
|
89
96
|
if !attribute_present?(column)
|
90
|
-
|
97
|
+
_write_attribute(column, current_time)
|
91
98
|
end
|
92
99
|
end
|
93
100
|
end
|
@@ -101,7 +108,7 @@ module ActiveRecord
|
|
101
108
|
|
102
109
|
timestamp_attributes_for_update_in_model.each do |column|
|
103
110
|
next if will_save_change_to_attribute?(column)
|
104
|
-
|
111
|
+
_write_attribute(column, current_time)
|
105
112
|
end
|
106
113
|
end
|
107
114
|
super(*args)
|
@@ -127,7 +134,7 @@ module ActiveRecord
|
|
127
134
|
self.class.send(:current_time_from_proper_timezone)
|
128
135
|
end
|
129
136
|
|
130
|
-
def max_updated_column_timestamp(timestamp_names =
|
137
|
+
def max_updated_column_timestamp(timestamp_names = timestamp_attributes_for_update_in_model)
|
131
138
|
timestamp_names
|
132
139
|
.map { |attr| self[attr] }
|
133
140
|
.compact
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
# See ActiveRecord::Transactions::ClassMethods for documentation.
|
3
5
|
module Transactions
|
@@ -168,7 +170,7 @@ module ActiveRecord
|
|
168
170
|
# writing, the only database that we're aware of that supports true nested
|
169
171
|
# transactions, is MS-SQL. Because of this, Active Record emulates nested
|
170
172
|
# transactions by using savepoints on MySQL and PostgreSQL. See
|
171
|
-
#
|
173
|
+
# https://dev.mysql.com/doc/refman/5.7/en/savepoint.html
|
172
174
|
# for more information about savepoints.
|
173
175
|
#
|
174
176
|
# === \Callbacks
|
@@ -188,7 +190,7 @@ module ActiveRecord
|
|
188
190
|
#
|
189
191
|
# === Caveats
|
190
192
|
#
|
191
|
-
# If you're on MySQL, then do not use Data Definition Language(DDL) operations in nested
|
193
|
+
# If you're on MySQL, then do not use Data Definition Language (DDL) operations in nested
|
192
194
|
# transactions blocks that are emulated with savepoints. That is, do not execute statements
|
193
195
|
# like 'CREATE TABLE' inside such blocks. This is because MySQL automatically
|
194
196
|
# releases all savepoints upon executing a DDL operation. When +transaction+
|
@@ -283,7 +285,7 @@ module ActiveRecord
|
|
283
285
|
fire_on = Array(options[:on])
|
284
286
|
assert_valid_transaction_action(fire_on)
|
285
287
|
options[:if] = Array(options[:if])
|
286
|
-
options[:if].unshift(
|
288
|
+
options[:if].unshift(-> { transaction_include_any_action?(fire_on) })
|
287
289
|
end
|
288
290
|
end
|
289
291
|
|
@@ -338,11 +340,13 @@ module ActiveRecord
|
|
338
340
|
# Ensure that it is not called if the object was never persisted (failed create),
|
339
341
|
# but call it after the commit of a destroyed object.
|
340
342
|
def committed!(should_run_callbacks: true) #:nodoc:
|
341
|
-
if should_run_callbacks && destroyed? || persisted?
|
343
|
+
if should_run_callbacks && (destroyed? || persisted?)
|
344
|
+
@_committed_already_called = true
|
342
345
|
_run_commit_without_transaction_enrollment_callbacks
|
343
346
|
_run_commit_callbacks
|
344
347
|
end
|
345
348
|
ensure
|
349
|
+
@_committed_already_called = false
|
346
350
|
force_clear_transaction_record_state
|
347
351
|
end
|
348
352
|
|
@@ -380,13 +384,7 @@ module ActiveRecord
|
|
380
384
|
status = nil
|
381
385
|
self.class.transaction do
|
382
386
|
add_to_transaction
|
383
|
-
|
384
|
-
status = yield
|
385
|
-
rescue ActiveRecord::Rollback
|
386
|
-
clear_transaction_record_state
|
387
|
-
status = nil
|
388
|
-
end
|
389
|
-
|
387
|
+
status = yield
|
390
388
|
raise ActiveRecord::Rollback unless status
|
391
389
|
end
|
392
390
|
status
|
@@ -396,17 +394,29 @@ module ActiveRecord
|
|
396
394
|
end
|
397
395
|
end
|
398
396
|
|
397
|
+
protected
|
398
|
+
attr_reader :_committed_already_called, :_trigger_update_callback, :_trigger_destroy_callback
|
399
|
+
|
399
400
|
private
|
400
401
|
|
401
402
|
# Save the new record state and id of a record so it can be restored later if a transaction fails.
|
402
403
|
def remember_transaction_record_state
|
403
|
-
@_start_transaction_state[:id] = id
|
404
404
|
@_start_transaction_state.reverse_merge!(
|
405
|
+
id: id,
|
405
406
|
new_record: @new_record,
|
406
407
|
destroyed: @destroyed,
|
407
408
|
frozen?: frozen?,
|
408
409
|
)
|
409
410
|
@_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) + 1
|
411
|
+
remember_new_record_before_last_commit
|
412
|
+
end
|
413
|
+
|
414
|
+
def remember_new_record_before_last_commit
|
415
|
+
if _committed_already_called
|
416
|
+
@_new_record_before_last_commit = false
|
417
|
+
else
|
418
|
+
@_new_record_before_last_commit = @_start_transaction_state[:new_record]
|
419
|
+
end
|
410
420
|
end
|
411
421
|
|
412
422
|
# Clear the new record state and id of a record.
|
@@ -430,30 +440,24 @@ module ActiveRecord
|
|
430
440
|
@new_record = restore_state[:new_record]
|
431
441
|
@destroyed = restore_state[:destroyed]
|
432
442
|
pk = self.class.primary_key
|
433
|
-
if pk &&
|
434
|
-
|
443
|
+
if pk && _read_attribute(pk) != restore_state[:id]
|
444
|
+
_write_attribute(pk, restore_state[:id])
|
435
445
|
end
|
436
446
|
freeze if restore_state[:frozen?]
|
437
447
|
end
|
438
448
|
end
|
439
449
|
end
|
440
450
|
|
441
|
-
# Determine if a record was created or destroyed in a transaction. State should be one of :new_record or :destroyed.
|
442
|
-
def transaction_record_state(state)
|
443
|
-
@_start_transaction_state[state]
|
444
|
-
end
|
445
|
-
|
446
451
|
# Determine if a transaction included an action for :create, :update, or :destroy. Used in filtering callbacks.
|
447
452
|
def transaction_include_any_action?(actions)
|
448
453
|
actions.any? do |action|
|
449
454
|
case action
|
450
455
|
when :create
|
451
|
-
|
452
|
-
when :destroy
|
453
|
-
defined?(@_trigger_destroy_callback) && @_trigger_destroy_callback
|
456
|
+
persisted? && @_new_record_before_last_commit
|
454
457
|
when :update
|
455
|
-
!(
|
456
|
-
|
458
|
+
!(@_new_record_before_last_commit || destroyed?) && _trigger_update_callback
|
459
|
+
when :destroy
|
460
|
+
_trigger_destroy_callback
|
457
461
|
end
|
458
462
|
end
|
459
463
|
end
|
@@ -470,7 +474,7 @@ module ActiveRecord
|
|
470
474
|
# if it's associated with a transaction, then the state of the Active Record
|
471
475
|
# object will be updated to reflect the current state of the transaction.
|
472
476
|
#
|
473
|
-
# The
|
477
|
+
# The <tt>@transaction_state</tt> variable stores the states of the associated
|
474
478
|
# transaction. This relies on the fact that a transaction can only be in
|
475
479
|
# one rollback or commit (otherwise a list of states would be required).
|
476
480
|
# Each Active Record object inside of a transaction carries that transaction's
|
@@ -489,8 +493,9 @@ module ActiveRecord
|
|
489
493
|
|
490
494
|
def update_attributes_from_transaction_state(transaction_state)
|
491
495
|
if transaction_state && transaction_state.finalized?
|
492
|
-
restore_transaction_record_state if transaction_state.rolledback?
|
493
|
-
|
496
|
+
restore_transaction_record_state(transaction_state.fully_rolledback?) if transaction_state.rolledback?
|
497
|
+
force_clear_transaction_record_state if transaction_state.fully_committed?
|
498
|
+
clear_transaction_record_state if transaction_state.fully_completed?
|
494
499
|
end
|
495
500
|
end
|
496
501
|
end
|