activerecord 5.2.8.1 → 6.0.0.beta1
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 +4 -4
- data/CHANGELOG.md +299 -816
- data/MIT-LICENSE +3 -1
- data/README.rdoc +1 -1
- data/examples/performance.rb +1 -1
- data/lib/active_record/aggregations.rb +4 -2
- data/lib/active_record/associations/association.rb +35 -19
- data/lib/active_record/associations/association_scope.rb +4 -6
- data/lib/active_record/associations/belongs_to_association.rb +36 -42
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +0 -4
- data/lib/active_record/associations/builder/belongs_to.rb +14 -50
- data/lib/active_record/associations/builder/collection_association.rb +3 -3
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -38
- data/lib/active_record/associations/collection_association.rb +11 -25
- data/lib/active_record/associations/collection_proxy.rb +32 -6
- data/lib/active_record/associations/foreign_association.rb +7 -0
- data/lib/active_record/associations/has_many_association.rb +1 -1
- data/lib/active_record/associations/has_many_through_association.rb +25 -18
- data/lib/active_record/associations/has_one_association.rb +28 -30
- data/lib/active_record/associations/has_one_through_association.rb +5 -5
- data/lib/active_record/associations/join_dependency/join_association.rb +11 -26
- data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
- data/lib/active_record/associations/join_dependency.rb +15 -20
- data/lib/active_record/associations/preloader/association.rb +1 -2
- data/lib/active_record/associations/preloader.rb +32 -29
- data/lib/active_record/associations/singular_association.rb +2 -16
- data/lib/active_record/associations.rb +16 -12
- data/lib/active_record/attribute_assignment.rb +7 -10
- data/lib/active_record/attribute_methods/dirty.rb +64 -26
- data/lib/active_record/attribute_methods/primary_key.rb +8 -7
- data/lib/active_record/attribute_methods/read.rb +16 -48
- data/lib/active_record/attribute_methods/serialization.rb +1 -1
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +1 -1
- data/lib/active_record/attribute_methods/write.rb +15 -16
- data/lib/active_record/attribute_methods.rb +34 -56
- data/lib/active_record/autosave_association.rb +7 -21
- data/lib/active_record/base.rb +2 -2
- data/lib/active_record/callbacks.rb +3 -17
- data/lib/active_record/coders/yaml_column.rb +1 -13
- data/lib/active_record/collection_cache_key.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +13 -36
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +25 -84
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +17 -14
- data/lib/active_record/connection_adapters/abstract/quoting.rb +5 -11
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +15 -11
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +30 -13
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +0 -2
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +41 -27
- data/lib/active_record/connection_adapters/abstract/transaction.rb +81 -52
- data/lib/active_record/connection_adapters/abstract_adapter.rb +95 -31
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +65 -90
- data/lib/active_record/connection_adapters/connection_specification.rb +52 -42
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +5 -9
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +29 -7
- data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +3 -4
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +65 -10
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -4
- data/lib/active_record/connection_adapters/postgresql/column.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +16 -1
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +11 -36
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +9 -2
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +38 -20
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +75 -56
- data/lib/active_record/connection_adapters/schema_cache.rb +5 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +5 -5
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +14 -9
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +95 -62
- data/lib/active_record/connection_handling.rb +132 -26
- data/lib/active_record/core.rb +75 -52
- data/lib/active_record/counter_cache.rb +4 -29
- data/lib/active_record/database_configurations/database_config.rb +37 -0
- data/lib/active_record/database_configurations/hash_config.rb +50 -0
- data/lib/active_record/database_configurations/url_config.rb +74 -0
- data/lib/active_record/database_configurations.rb +184 -0
- data/lib/active_record/enum.rb +22 -7
- data/lib/active_record/errors.rb +24 -21
- data/lib/active_record/explain.rb +1 -1
- data/lib/active_record/fixture_set/model_metadata.rb +33 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +153 -0
- data/lib/active_record/fixture_set/table_rows.rb +47 -0
- data/lib/active_record/fixtures.rb +140 -472
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +12 -2
- data/lib/active_record/integration.rb +56 -16
- data/lib/active_record/internal_metadata.rb +5 -1
- data/lib/active_record/locking/optimistic.rb +2 -2
- data/lib/active_record/locking/pessimistic.rb +3 -3
- data/lib/active_record/log_subscriber.rb +7 -26
- data/lib/active_record/migration/command_recorder.rb +35 -5
- data/lib/active_record/migration/compatibility.rb +34 -16
- data/lib/active_record/migration.rb +38 -37
- data/lib/active_record/model_schema.rb +30 -9
- data/lib/active_record/nested_attributes.rb +2 -2
- data/lib/active_record/no_touching.rb +7 -0
- data/lib/active_record/persistence.rb +18 -7
- data/lib/active_record/query_cache.rb +11 -4
- data/lib/active_record/querying.rb +19 -11
- data/lib/active_record/railtie.rb +71 -60
- data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
- data/lib/active_record/railties/controller_runtime.rb +30 -35
- data/lib/active_record/railties/databases.rake +94 -43
- data/lib/active_record/reflection.rb +60 -44
- data/lib/active_record/relation/batches.rb +13 -10
- data/lib/active_record/relation/calculations.rb +38 -28
- data/lib/active_record/relation/delegation.rb +4 -13
- data/lib/active_record/relation/finder_methods.rb +12 -25
- data/lib/active_record/relation/merger.rb +2 -6
- data/lib/active_record/relation/predicate_builder/array_handler.rb +5 -4
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +1 -4
- data/lib/active_record/relation/predicate_builder/base_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -4
- data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
- data/lib/active_record/relation/predicate_builder.rb +4 -6
- data/lib/active_record/relation/query_attribute.rb +15 -12
- data/lib/active_record/relation/query_methods.rb +29 -52
- data/lib/active_record/relation/where_clause.rb +4 -0
- data/lib/active_record/relation/where_clause_factory.rb +1 -2
- data/lib/active_record/relation.rb +150 -69
- data/lib/active_record/result.rb +30 -11
- data/lib/active_record/sanitization.rb +2 -39
- data/lib/active_record/schema.rb +1 -10
- data/lib/active_record/schema_dumper.rb +12 -6
- data/lib/active_record/schema_migration.rb +4 -0
- data/lib/active_record/scoping/default.rb +10 -3
- data/lib/active_record/scoping/named.rb +10 -14
- data/lib/active_record/scoping.rb +9 -8
- data/lib/active_record/statement_cache.rb +32 -5
- data/lib/active_record/store.rb +39 -8
- data/lib/active_record/table_metadata.rb +1 -4
- data/lib/active_record/tasks/database_tasks.rb +89 -23
- data/lib/active_record/tasks/mysql_database_tasks.rb +2 -4
- data/lib/active_record/tasks/postgresql_database_tasks.rb +5 -7
- data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -8
- data/lib/active_record/test_databases.rb +38 -0
- data/lib/active_record/test_fixtures.rb +224 -0
- data/lib/active_record/timestamp.rb +4 -6
- data/lib/active_record/transactions.rb +3 -22
- data/lib/active_record/translation.rb +1 -1
- data/lib/active_record/type/adapter_specific_registry.rb +1 -8
- data/lib/active_record/type.rb +3 -4
- data/lib/active_record/type_caster/connection.rb +1 -6
- data/lib/active_record/type_caster/map.rb +1 -4
- data/lib/active_record/validations/uniqueness.rb +13 -25
- data/lib/active_record.rb +2 -1
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +37 -0
- data/lib/arel/attributes.rb +22 -0
- data/lib/arel/collectors/bind.rb +24 -0
- data/lib/arel/collectors/composite.rb +31 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +20 -0
- data/lib/arel/collectors/substitute_binds.rb +28 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/insert_manager.rb +49 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +52 -0
- data/lib/arel/nodes/bind_param.rb +36 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +50 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +45 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +18 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +8 -0
- data/lib/arel/nodes/in.rb +8 -0
- data/lib/arel/nodes/infix_operation.rb +80 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +50 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +63 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +16 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +27 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +44 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +41 -0
- data/lib/arel/nodes/values.rb +16 -0
- data/lib/arel/nodes/values_list.rb +24 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/nodes.rb +67 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +257 -0
- data/lib/arel/select_manager.rb +271 -0
- data/lib/arel/table.rb +110 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors/depth_first.rb +199 -0
- data/lib/arel/visitors/dot.rb +292 -0
- data/lib/arel/visitors/ibm_db.rb +21 -0
- data/lib/arel/visitors/informix.rb +56 -0
- data/lib/arel/visitors/mssql.rb +143 -0
- data/lib/arel/visitors/mysql.rb +83 -0
- data/lib/arel/visitors/oracle.rb +159 -0
- data/lib/arel/visitors/oracle12.rb +67 -0
- data/lib/arel/visitors/postgresql.rb +116 -0
- data/lib/arel/visitors/sqlite.rb +39 -0
- data/lib/arel/visitors/to_sql.rb +913 -0
- data/lib/arel/visitors/visitor.rb +42 -0
- data/lib/arel/visitors/where_sql.rb +23 -0
- data/lib/arel/visitors.rb +20 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +44 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +2 -5
- data/lib/rails/generators/active_record/migration.rb +14 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +1 -0
- metadata +107 -29
@@ -55,7 +55,11 @@ module ActiveRecord
|
|
55
55
|
if has_attribute?(inheritance_column)
|
56
56
|
subclass = subclass_from_attributes(attributes)
|
57
57
|
|
58
|
-
if subclass.nil? &&
|
58
|
+
if subclass.nil? && scope_attributes = current_scope&.scope_for_create
|
59
|
+
subclass = subclass_from_attributes(scope_attributes)
|
60
|
+
end
|
61
|
+
|
62
|
+
if subclass.nil? && base_class?
|
59
63
|
subclass = subclass_from_attributes(column_defaults)
|
60
64
|
end
|
61
65
|
end
|
@@ -104,6 +108,12 @@ module ActiveRecord
|
|
104
108
|
end
|
105
109
|
end
|
106
110
|
|
111
|
+
# Returns whether the class is a base class.
|
112
|
+
# See #base_class for more information.
|
113
|
+
def base_class?
|
114
|
+
base_class == self
|
115
|
+
end
|
116
|
+
|
107
117
|
# Set this to +true+ if this is an abstract class (see
|
108
118
|
# <tt>abstract_class?</tt>).
|
109
119
|
# If you are using inheritance with Active Record and don't want a class
|
@@ -170,7 +180,7 @@ module ActiveRecord
|
|
170
180
|
# Returns the class type of the record using the current module as a prefix. So descendants of
|
171
181
|
# MyApp::Business::Account would appear as MyApp::Business::AccountSubclass.
|
172
182
|
def compute_type(type_name)
|
173
|
-
if type_name.start_with?("::"
|
183
|
+
if type_name.start_with?("::")
|
174
184
|
# If the type is prefixed with a scope operator then we assume that
|
175
185
|
# the type_name is an absolute reference.
|
176
186
|
ActiveSupport::Dependencies.constantize(type_name)
|
@@ -20,7 +20,7 @@ module ActiveRecord
|
|
20
20
|
# Indicates whether to use a stable #cache_key method that is accompanied
|
21
21
|
# by a changing version in the #cache_version method.
|
22
22
|
#
|
23
|
-
# This is +
|
23
|
+
# This is +true+, by default on Rails 5.2 and above.
|
24
24
|
class_attribute :cache_versioning, instance_writer: false, default: false
|
25
25
|
end
|
26
26
|
|
@@ -60,24 +60,15 @@ module ActiveRecord
|
|
60
60
|
# the cache key will also include a version.
|
61
61
|
#
|
62
62
|
# Product.cache_versioning = false
|
63
|
-
#
|
64
|
-
def cache_key
|
63
|
+
# Product.find(5).cache_key # => "products/5-20071224150000" (updated_at available)
|
64
|
+
def cache_key
|
65
65
|
if new_record?
|
66
66
|
"#{model_name.cache_key}/new"
|
67
67
|
else
|
68
|
-
if cache_version
|
68
|
+
if cache_version
|
69
69
|
"#{model_name.cache_key}/#{id}"
|
70
70
|
else
|
71
|
-
timestamp =
|
72
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
73
|
-
Specifying a timestamp name for #cache_key has been deprecated in favor of
|
74
|
-
the explicit #cache_version method that can be overwritten.
|
75
|
-
MSG
|
76
|
-
|
77
|
-
max_updated_column_timestamp(timestamp_names)
|
78
|
-
else
|
79
|
-
max_updated_column_timestamp
|
80
|
-
end
|
71
|
+
timestamp = max_updated_column_timestamp
|
81
72
|
|
82
73
|
if timestamp
|
83
74
|
timestamp = timestamp.utc.to_s(cache_timestamp_format)
|
@@ -96,8 +87,19 @@ module ActiveRecord
|
|
96
87
|
# Note, this method will return nil if ActiveRecord::Base.cache_versioning is set to
|
97
88
|
# +false+ (which it is by default until Rails 6.0).
|
98
89
|
def cache_version
|
99
|
-
|
100
|
-
|
90
|
+
return unless cache_versioning
|
91
|
+
|
92
|
+
if has_attribute?("updated_at")
|
93
|
+
timestamp = updated_at_before_type_cast
|
94
|
+
if can_use_fast_cache_version?(timestamp)
|
95
|
+
raw_timestamp_to_cache_version(timestamp)
|
96
|
+
elsif timestamp = updated_at
|
97
|
+
timestamp.utc.to_s(cache_timestamp_format)
|
98
|
+
end
|
99
|
+
else
|
100
|
+
if self.class.has_attribute?("updated_at")
|
101
|
+
raise ActiveModel::MissingAttributeError, "missing attribute: updated_at"
|
102
|
+
end
|
101
103
|
end
|
102
104
|
end
|
103
105
|
|
@@ -151,5 +153,43 @@ module ActiveRecord
|
|
151
153
|
end
|
152
154
|
end
|
153
155
|
end
|
156
|
+
|
157
|
+
private
|
158
|
+
# Detects if the value before type cast
|
159
|
+
# can be used to generate a cache_version.
|
160
|
+
#
|
161
|
+
# The fast cache version only works with a
|
162
|
+
# string value directly from the database.
|
163
|
+
#
|
164
|
+
# We also must check if the timestamp format has been changed
|
165
|
+
# or if the timezone is not set to UTC then
|
166
|
+
# we cannot apply our transformations correctly.
|
167
|
+
def can_use_fast_cache_version?(timestamp)
|
168
|
+
timestamp.is_a?(String) &&
|
169
|
+
cache_timestamp_format == :usec &&
|
170
|
+
default_timezone == :utc &&
|
171
|
+
!updated_at_came_from_user?
|
172
|
+
end
|
173
|
+
|
174
|
+
# Converts a raw database string to `:usec`
|
175
|
+
# format.
|
176
|
+
#
|
177
|
+
# Example:
|
178
|
+
#
|
179
|
+
# timestamp = "2018-10-15 20:02:15.266505"
|
180
|
+
# raw_timestamp_to_cache_version(timestamp)
|
181
|
+
# # => "20181015200215266505"
|
182
|
+
#
|
183
|
+
# Postgres truncates trailing zeros,
|
184
|
+
# https://github.com/postgres/postgres/commit/3e1beda2cde3495f41290e1ece5d544525810214
|
185
|
+
# to account for this we pad the output with zeros
|
186
|
+
def raw_timestamp_to_cache_version(timestamp)
|
187
|
+
key = timestamp.delete("- :.")
|
188
|
+
if key.length < 20
|
189
|
+
key.ljust(20, "0")
|
190
|
+
else
|
191
|
+
key
|
192
|
+
end
|
193
|
+
end
|
154
194
|
end
|
155
195
|
end
|
@@ -8,6 +8,10 @@ module ActiveRecord
|
|
8
8
|
# as which environment migrations were run in.
|
9
9
|
class InternalMetadata < ActiveRecord::Base # :nodoc:
|
10
10
|
class << self
|
11
|
+
def _internal?
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
11
15
|
def primary_key
|
12
16
|
"key"
|
13
17
|
end
|
@@ -17,7 +21,7 @@ module ActiveRecord
|
|
17
21
|
end
|
18
22
|
|
19
23
|
def []=(key, value)
|
20
|
-
find_or_initialize_by(key: key).
|
24
|
+
find_or_initialize_by(key: key).update!(value: value)
|
21
25
|
end
|
22
26
|
|
23
27
|
def [](key)
|
@@ -61,7 +61,7 @@ module ActiveRecord
|
|
61
61
|
end
|
62
62
|
|
63
63
|
private
|
64
|
-
def _create_record(attribute_names = self.attribute_names
|
64
|
+
def _create_record(attribute_names = self.attribute_names)
|
65
65
|
if locking_enabled?
|
66
66
|
# We always want to persist the locking version, even if we don't detect
|
67
67
|
# a change from the default, since the database might have no default
|
@@ -165,7 +165,7 @@ module ActiveRecord
|
|
165
165
|
def inherited(subclass)
|
166
166
|
subclass.class_eval do
|
167
167
|
is_lock_column = ->(name, _) { lock_optimistically && name == locking_column }
|
168
|
-
decorate_matching_attribute_types(is_lock_column,
|
168
|
+
decorate_matching_attribute_types(is_lock_column, "_optimistic_locking") do |type|
|
169
169
|
LockingType.new(type)
|
170
170
|
end
|
171
171
|
end
|
@@ -14,9 +14,9 @@ module ActiveRecord
|
|
14
14
|
# of your own such as 'LOCK IN SHARE MODE' or 'FOR UPDATE NOWAIT'. Example:
|
15
15
|
#
|
16
16
|
# Account.transaction do
|
17
|
-
# # select * from accounts where name = 'shugo' limit 1 for update
|
18
|
-
# shugo = Account.
|
19
|
-
# yuko = Account.
|
17
|
+
# # select * from accounts where name = 'shugo' limit 1 for update nowait
|
18
|
+
# shugo = Account.lock("FOR UPDATE NOWAIT").find_by(name: "shugo")
|
19
|
+
# yuko = Account.lock("FOR UPDATE NOWAIT").find_by(name: "yuko")
|
20
20
|
# shugo.balance -= 100
|
21
21
|
# shugo.save!
|
22
22
|
# yuko.balance += 100
|
@@ -4,6 +4,8 @@ module ActiveRecord
|
|
4
4
|
class LogSubscriber < ActiveSupport::LogSubscriber
|
5
5
|
IGNORE_PAYLOAD_NAMES = ["SCHEMA", "EXPLAIN"]
|
6
6
|
|
7
|
+
class_attribute :backtrace_cleaner, default: ActiveSupport::BacktraceCleaner.new
|
8
|
+
|
7
9
|
def self.runtime=(value)
|
8
10
|
ActiveRecord::RuntimeRegistry.sql_runtime = value
|
9
11
|
end
|
@@ -100,36 +102,15 @@ module ActiveRecord
|
|
100
102
|
end
|
101
103
|
|
102
104
|
def log_query_source
|
103
|
-
|
104
|
-
|
105
|
-
if source_line
|
106
|
-
if defined?(::Rails.root)
|
107
|
-
app_root = "#{::Rails.root.to_s}/".freeze
|
108
|
-
source_line = source_line.sub(app_root, "")
|
109
|
-
end
|
110
|
-
|
111
|
-
logger.debug(" ↳ #{ source_line }:#{ line_number }")
|
112
|
-
end
|
113
|
-
end
|
105
|
+
source = extract_query_source_location(caller)
|
114
106
|
|
115
|
-
|
116
|
-
|
117
|
-
frame.absolute_path && !ignored_callstack(frame.absolute_path)
|
107
|
+
if source
|
108
|
+
logger.debug(" ↳ #{source}")
|
118
109
|
end
|
119
|
-
|
120
|
-
offending_line = line || callstack.first
|
121
|
-
|
122
|
-
[
|
123
|
-
offending_line.path,
|
124
|
-
offending_line.lineno
|
125
|
-
]
|
126
110
|
end
|
127
111
|
|
128
|
-
|
129
|
-
|
130
|
-
def ignored_callstack(path)
|
131
|
-
path.start_with?(RAILS_GEM_ROOT) ||
|
132
|
-
path.start_with?(RbConfig::CONFIG["rubylibdir"])
|
112
|
+
def extract_query_source_location(locations)
|
113
|
+
backtrace_cleaner.clean(locations).first
|
133
114
|
end
|
134
115
|
end
|
135
116
|
end
|
@@ -85,7 +85,7 @@ module ActiveRecord
|
|
85
85
|
# invert the +command+.
|
86
86
|
def inverse_of(command, args, &block)
|
87
87
|
method = :"invert_#{command}"
|
88
|
-
raise IrreversibleMigration,
|
88
|
+
raise IrreversibleMigration, <<~MSG unless respond_to?(method, true)
|
89
89
|
This migration uses #{command}, which is not automatically reversible.
|
90
90
|
To make the migration reversible you can either:
|
91
91
|
1. Define #up and #down methods in place of the #change method.
|
@@ -108,11 +108,17 @@ module ActiveRecord
|
|
108
108
|
yield delegate.update_table_definition(table_name, self)
|
109
109
|
end
|
110
110
|
|
111
|
+
def replay(migration)
|
112
|
+
commands.each do |cmd, args, block|
|
113
|
+
migration.send(cmd, *args, &block)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
111
117
|
private
|
112
118
|
|
113
119
|
module StraightReversions # :nodoc:
|
114
120
|
private
|
115
|
-
{
|
121
|
+
{
|
116
122
|
execute_block: :execute_block,
|
117
123
|
create_table: :drop_table,
|
118
124
|
create_join_table: :drop_join_table,
|
@@ -133,6 +139,17 @@ module ActiveRecord
|
|
133
139
|
|
134
140
|
include StraightReversions
|
135
141
|
|
142
|
+
def invert_transaction(args)
|
143
|
+
sub_recorder = CommandRecorder.new(delegate)
|
144
|
+
sub_recorder.revert { yield }
|
145
|
+
|
146
|
+
invertions_proc = proc {
|
147
|
+
sub_recorder.replay(self)
|
148
|
+
}
|
149
|
+
|
150
|
+
[:transaction, args, invertions_proc]
|
151
|
+
end
|
152
|
+
|
136
153
|
def invert_drop_table(args, &block)
|
137
154
|
if args.size == 1 && block == nil
|
138
155
|
raise ActiveRecord::IrreversibleMigration, "To avoid mistakes, drop_table is only reversible if given options or a block (can be empty)."
|
@@ -214,11 +231,24 @@ module ActiveRecord
|
|
214
231
|
end
|
215
232
|
|
216
233
|
def invert_remove_foreign_key(args)
|
217
|
-
from_table,
|
218
|
-
|
234
|
+
from_table, options_or_to_table, options_or_nil = args
|
235
|
+
|
236
|
+
to_table = if options_or_to_table.is_a?(Hash)
|
237
|
+
options_or_to_table[:to_table]
|
238
|
+
else
|
239
|
+
options_or_to_table
|
240
|
+
end
|
241
|
+
|
242
|
+
remove_options = if options_or_to_table.is_a?(Hash)
|
243
|
+
options_or_to_table.except(:to_table)
|
244
|
+
else
|
245
|
+
options_or_nil
|
246
|
+
end
|
247
|
+
|
248
|
+
raise ActiveRecord::IrreversibleMigration, "remove_foreign_key is only reversible if given a second table" if to_table.nil?
|
219
249
|
|
220
250
|
reversed_args = [from_table, to_table]
|
221
|
-
reversed_args << remove_options if remove_options
|
251
|
+
reversed_args << remove_options if remove_options.present?
|
222
252
|
|
223
253
|
[:add_foreign_key, reversed_args]
|
224
254
|
end
|
@@ -13,22 +13,42 @@ module ActiveRecord
|
|
13
13
|
const_get(name)
|
14
14
|
end
|
15
15
|
|
16
|
-
|
16
|
+
V6_0 = Current
|
17
|
+
|
18
|
+
class V5_2 < V6_0
|
19
|
+
module CommandRecorder
|
20
|
+
def invert_transaction(args, &block)
|
21
|
+
[:transaction, args, block]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def command_recorder
|
28
|
+
recorder = super
|
29
|
+
class << recorder
|
30
|
+
prepend CommandRecorder
|
31
|
+
end
|
32
|
+
recorder
|
33
|
+
end
|
34
|
+
end
|
17
35
|
|
18
36
|
class V5_1 < V5_2
|
19
37
|
def change_column(table_name, column_name, type, options = {})
|
20
|
-
if
|
21
|
-
|
22
|
-
connection.
|
23
|
-
|
24
|
-
|
38
|
+
if adapter_name == "PostgreSQL"
|
39
|
+
clear_cache!
|
40
|
+
sql = connection.send(:change_column_sql, table_name, column_name, type, options)
|
41
|
+
execute "ALTER TABLE #{quote_table_name(table_name)} #{sql}"
|
42
|
+
change_column_default(table_name, column_name, options[:default]) if options.key?(:default)
|
43
|
+
change_column_null(table_name, column_name, options[:null], options[:default]) if options.key?(:null)
|
44
|
+
change_column_comment(table_name, column_name, options[:comment]) if options.key?(:comment)
|
25
45
|
else
|
26
46
|
super
|
27
47
|
end
|
28
48
|
end
|
29
49
|
|
30
50
|
def create_table(table_name, options = {})
|
31
|
-
if
|
51
|
+
if adapter_name == "Mysql2"
|
32
52
|
super(table_name, options: "ENGINE=InnoDB", **options)
|
33
53
|
else
|
34
54
|
super
|
@@ -50,13 +70,13 @@ module ActiveRecord
|
|
50
70
|
end
|
51
71
|
|
52
72
|
def create_table(table_name, options = {})
|
53
|
-
if
|
73
|
+
if adapter_name == "PostgreSQL"
|
54
74
|
if options[:id] == :uuid && !options.key?(:default)
|
55
75
|
options[:default] = "uuid_generate_v4()"
|
56
76
|
end
|
57
77
|
end
|
58
78
|
|
59
|
-
unless
|
79
|
+
unless adapter_name == "Mysql2" && options[:id] == :bigint
|
60
80
|
if [:integer, :bigint].include?(options[:id]) && !options.key?(:default)
|
61
81
|
options[:default] = nil
|
62
82
|
end
|
@@ -173,7 +193,7 @@ module ActiveRecord
|
|
173
193
|
if options[:name].present?
|
174
194
|
options[:name].to_s
|
175
195
|
else
|
176
|
-
|
196
|
+
index_name(table_name, column: column_names)
|
177
197
|
end
|
178
198
|
super
|
179
199
|
end
|
@@ -193,17 +213,15 @@ module ActiveRecord
|
|
193
213
|
end
|
194
214
|
|
195
215
|
def index_name_for_remove(table_name, options = {})
|
196
|
-
index_name =
|
216
|
+
index_name = index_name(table_name, options)
|
197
217
|
|
198
|
-
unless
|
218
|
+
unless index_name_exists?(table_name, index_name)
|
199
219
|
if options.is_a?(Hash) && options.has_key?(:name)
|
200
220
|
options_without_column = options.dup
|
201
221
|
options_without_column.delete :column
|
202
|
-
index_name_without_column =
|
222
|
+
index_name_without_column = index_name(table_name, options_without_column)
|
203
223
|
|
204
|
-
if
|
205
|
-
return index_name_without_column
|
206
|
-
end
|
224
|
+
return index_name_without_column if index_name_exists?(table_name, index_name_without_column)
|
207
225
|
end
|
208
226
|
|
209
227
|
raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' does not exist"
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "benchmark"
|
3
4
|
require "set"
|
4
5
|
require "zlib"
|
5
6
|
require "active_support/core_ext/module/attribute_accessors"
|
@@ -22,7 +23,7 @@ module ActiveRecord
|
|
22
23
|
# t.string :zipcode
|
23
24
|
# end
|
24
25
|
#
|
25
|
-
# execute
|
26
|
+
# execute <<~SQL
|
26
27
|
# ALTER TABLE distributors
|
27
28
|
# ADD CONSTRAINT zipchk
|
28
29
|
# CHECK (char_length(zipcode) = 5) NO INHERIT;
|
@@ -40,7 +41,7 @@ module ActiveRecord
|
|
40
41
|
# t.string :zipcode
|
41
42
|
# end
|
42
43
|
#
|
43
|
-
# execute
|
44
|
+
# execute <<~SQL
|
44
45
|
# ALTER TABLE distributors
|
45
46
|
# ADD CONSTRAINT zipchk
|
46
47
|
# CHECK (char_length(zipcode) = 5) NO INHERIT;
|
@@ -48,7 +49,7 @@ module ActiveRecord
|
|
48
49
|
# end
|
49
50
|
#
|
50
51
|
# def down
|
51
|
-
# execute
|
52
|
+
# execute <<~SQL
|
52
53
|
# ALTER TABLE distributors
|
53
54
|
# DROP CONSTRAINT zipchk
|
54
55
|
# SQL
|
@@ -67,7 +68,7 @@ module ActiveRecord
|
|
67
68
|
#
|
68
69
|
# reversible do |dir|
|
69
70
|
# dir.up do
|
70
|
-
# execute
|
71
|
+
# execute <<~SQL
|
71
72
|
# ALTER TABLE distributors
|
72
73
|
# ADD CONSTRAINT zipchk
|
73
74
|
# CHECK (char_length(zipcode) = 5) NO INHERIT;
|
@@ -75,7 +76,7 @@ module ActiveRecord
|
|
75
76
|
# end
|
76
77
|
#
|
77
78
|
# dir.down do
|
78
|
-
# execute
|
79
|
+
# execute <<~SQL
|
79
80
|
# ALTER TABLE distributors
|
80
81
|
# DROP CONSTRAINT zipchk
|
81
82
|
# SQL
|
@@ -129,9 +130,9 @@ module ActiveRecord
|
|
129
130
|
class PendingMigrationError < MigrationError#:nodoc:
|
130
131
|
def initialize(message = nil)
|
131
132
|
if !message && defined?(Rails.env)
|
132
|
-
super("Migrations are pending. To resolve this issue, run:\n\n
|
133
|
+
super("Migrations are pending. To resolve this issue, run:\n\n rails db:migrate RAILS_ENV=#{::Rails.env}")
|
133
134
|
elsif !message
|
134
|
-
super("Migrations are pending. To resolve this issue, run:\n\n
|
135
|
+
super("Migrations are pending. To resolve this issue, run:\n\n rails db:migrate")
|
135
136
|
else
|
136
137
|
super
|
137
138
|
end
|
@@ -139,8 +140,8 @@ module ActiveRecord
|
|
139
140
|
end
|
140
141
|
|
141
142
|
class ConcurrentMigrationError < MigrationError #:nodoc:
|
142
|
-
DEFAULT_MESSAGE = "Cannot run migrations because another migration process is currently running."
|
143
|
-
RELEASE_LOCK_FAILED_MESSAGE = "Failed to release advisory lock"
|
143
|
+
DEFAULT_MESSAGE = "Cannot run migrations because another migration process is currently running."
|
144
|
+
RELEASE_LOCK_FAILED_MESSAGE = "Failed to release advisory lock"
|
144
145
|
|
145
146
|
def initialize(message = DEFAULT_MESSAGE)
|
146
147
|
super
|
@@ -149,7 +150,7 @@ module ActiveRecord
|
|
149
150
|
|
150
151
|
class NoEnvironmentInSchemaError < MigrationError #:nodoc:
|
151
152
|
def initialize
|
152
|
-
msg = "Environment data not found in the schema. To resolve this issue, run: \n\n
|
153
|
+
msg = "Environment data not found in the schema. To resolve this issue, run: \n\n rails db:environment:set"
|
153
154
|
if defined?(Rails.env)
|
154
155
|
super("#{msg} RAILS_ENV=#{::Rails.env}")
|
155
156
|
else
|
@@ -160,7 +161,7 @@ module ActiveRecord
|
|
160
161
|
|
161
162
|
class ProtectedEnvironmentError < ActiveRecordError #:nodoc:
|
162
163
|
def initialize(env = "production")
|
163
|
-
msg = "You are attempting to run a destructive action against your '#{env}' database.\n"
|
164
|
+
msg = +"You are attempting to run a destructive action against your '#{env}' database.\n"
|
164
165
|
msg << "If you are sure you want to continue, run the same command with the environment variable:\n"
|
165
166
|
msg << "DISABLE_DATABASE_ENVIRONMENT_CHECK=1"
|
166
167
|
super(msg)
|
@@ -169,10 +170,10 @@ module ActiveRecord
|
|
169
170
|
|
170
171
|
class EnvironmentMismatchError < ActiveRecordError
|
171
172
|
def initialize(current: nil, stored: nil)
|
172
|
-
msg =
|
173
|
+
msg = +"You are attempting to modify a database that was last run in `#{ stored }` environment.\n"
|
173
174
|
msg << "You are running in `#{ current }` environment. "
|
174
175
|
msg << "If you are sure you want to continue, first set the environment using:\n\n"
|
175
|
-
msg << "
|
176
|
+
msg << " rails db:environment:set"
|
176
177
|
if defined?(Rails.env)
|
177
178
|
super("#{msg} RAILS_ENV=#{::Rails.env}\n\n")
|
178
179
|
else
|
@@ -351,7 +352,7 @@ module ActiveRecord
|
|
351
352
|
# <tt>rails db:migrate</tt>. This will update the database by running all of the
|
352
353
|
# pending migrations, creating the <tt>schema_migrations</tt> table
|
353
354
|
# (see "About the schema_migrations table" section below) if missing. It will also
|
354
|
-
# invoke the db:schema:dump
|
355
|
+
# invoke the db:schema:dump command, which will update your db/schema.rb file
|
355
356
|
# to match the structure of your database.
|
356
357
|
#
|
357
358
|
# To roll the database back to a previous migration version, use
|
@@ -677,15 +678,13 @@ module ActiveRecord
|
|
677
678
|
if connection.respond_to? :revert
|
678
679
|
connection.revert { yield }
|
679
680
|
else
|
680
|
-
recorder =
|
681
|
+
recorder = command_recorder
|
681
682
|
@connection = recorder
|
682
683
|
suppress_messages do
|
683
684
|
connection.revert { yield }
|
684
685
|
end
|
685
686
|
@connection = recorder.delegate
|
686
|
-
recorder.
|
687
|
-
send(cmd, *args, &block)
|
688
|
-
end
|
687
|
+
recorder.replay(self)
|
689
688
|
end
|
690
689
|
end
|
691
690
|
end
|
@@ -830,10 +829,14 @@ module ActiveRecord
|
|
830
829
|
write "== %s %s" % [text, "=" * length]
|
831
830
|
end
|
832
831
|
|
832
|
+
# Takes a message argument and outputs it as is.
|
833
|
+
# A second boolean argument can be passed to specify whether to indent or not.
|
833
834
|
def say(message, subitem = false)
|
834
835
|
write "#{subitem ? " ->" : "--"} #{message}"
|
835
836
|
end
|
836
837
|
|
838
|
+
# Outputs text along with how long it took to run its block.
|
839
|
+
# If the block returns an integer it assumes it is the number of rows affected.
|
837
840
|
def say_with_time(message)
|
838
841
|
say(message)
|
839
842
|
result = nil
|
@@ -843,6 +846,7 @@ module ActiveRecord
|
|
843
846
|
result
|
844
847
|
end
|
845
848
|
|
849
|
+
# Takes a block as an argument and suppresses any output generated by the block.
|
846
850
|
def suppress_messages
|
847
851
|
save, self.verbose = verbose, false
|
848
852
|
yield
|
@@ -885,7 +889,7 @@ module ActiveRecord
|
|
885
889
|
source_migrations.each do |migration|
|
886
890
|
source = File.binread(migration.filename)
|
887
891
|
inserted_comment = "# This migration comes from #{scope} (originally #{migration.version})\n"
|
888
|
-
magic_comments = ""
|
892
|
+
magic_comments = +""
|
889
893
|
loop do
|
890
894
|
# If we have a magic comment in the original migration,
|
891
895
|
# insert our comment after the first newline(end of the magic comment line)
|
@@ -956,6 +960,10 @@ module ActiveRecord
|
|
956
960
|
yield
|
957
961
|
end
|
958
962
|
end
|
963
|
+
|
964
|
+
def command_recorder
|
965
|
+
CommandRecorder.new(connection)
|
966
|
+
end
|
959
967
|
end
|
960
968
|
|
961
969
|
# MigrationProxy is used to defer loading of the actual migration classes
|
@@ -1079,10 +1087,6 @@ module ActiveRecord
|
|
1079
1087
|
migrations.last || NullMigration.new
|
1080
1088
|
end
|
1081
1089
|
|
1082
|
-
def parse_migration_filename(filename) # :nodoc:
|
1083
|
-
File.basename(filename).scan(Migration::MigrationFilenameRegexp).first
|
1084
|
-
end
|
1085
|
-
|
1086
1090
|
def migrations
|
1087
1091
|
migrations = migration_files.map do |file|
|
1088
1092
|
version, name, scope = parse_migration_filename(file)
|
@@ -1114,11 +1118,6 @@ module ActiveRecord
|
|
1114
1118
|
(db_list + file_list).sort_by { |_, version, _| version }
|
1115
1119
|
end
|
1116
1120
|
|
1117
|
-
def migration_files
|
1118
|
-
paths = Array(migrations_paths)
|
1119
|
-
Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
|
1120
|
-
end
|
1121
|
-
|
1122
1121
|
def current_environment
|
1123
1122
|
ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
|
1124
1123
|
end
|
@@ -1137,6 +1136,15 @@ module ActiveRecord
|
|
1137
1136
|
end
|
1138
1137
|
|
1139
1138
|
private
|
1139
|
+
def migration_files
|
1140
|
+
paths = Array(migrations_paths)
|
1141
|
+
Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
|
1142
|
+
end
|
1143
|
+
|
1144
|
+
def parse_migration_filename(filename)
|
1145
|
+
File.basename(filename).scan(Migration::MigrationFilenameRegexp).first
|
1146
|
+
end
|
1147
|
+
|
1140
1148
|
def move(direction, steps)
|
1141
1149
|
migrator = Migrator.new(direction, migrations)
|
1142
1150
|
|
@@ -1161,13 +1169,6 @@ module ActiveRecord
|
|
1161
1169
|
class << self
|
1162
1170
|
attr_accessor :migrations_paths
|
1163
1171
|
|
1164
|
-
def migrations_path=(path)
|
1165
|
-
ActiveSupport::Deprecation.warn \
|
1166
|
-
"`ActiveRecord::Migrator.migrations_path=` is now deprecated and will be removed in Rails 6.0. " \
|
1167
|
-
"You can set the `migrations_paths` on the `connection` instead through the `database.yml`."
|
1168
|
-
self.migrations_paths = [path]
|
1169
|
-
end
|
1170
|
-
|
1171
1172
|
# For cases where a table doesn't exist like loading from schema cache
|
1172
1173
|
def current_version
|
1173
1174
|
MigrationContext.new(migrations_paths).current_version
|
@@ -1293,7 +1294,7 @@ module ActiveRecord
|
|
1293
1294
|
record_version_state_after_migrating(migration.version)
|
1294
1295
|
end
|
1295
1296
|
rescue => e
|
1296
|
-
msg = "An error has occurred, "
|
1297
|
+
msg = +"An error has occurred, "
|
1297
1298
|
msg << "this and " if use_transaction?(migration)
|
1298
1299
|
msg << "all later migrations canceled:\n\n#{e}"
|
1299
1300
|
raise StandardError, msg, e.backtrace
|
@@ -1351,7 +1352,7 @@ module ActiveRecord
|
|
1351
1352
|
end
|
1352
1353
|
|
1353
1354
|
def use_advisory_lock?
|
1354
|
-
Base.connection.
|
1355
|
+
Base.connection.advisory_locks_enabled?
|
1355
1356
|
end
|
1356
1357
|
|
1357
1358
|
def with_advisory_lock
|