activerecord 5.0.7.2 → 5.1.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 +5 -5
- data/CHANGELOG.md +389 -2252
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/examples/performance.rb +28 -28
- data/examples/simple.rb +3 -3
- data/lib/active_record.rb +20 -20
- data/lib/active_record/aggregations.rb +244 -244
- data/lib/active_record/association_relation.rb +5 -5
- data/lib/active_record/associations.rb +1579 -1569
- data/lib/active_record/associations/alias_tracker.rb +1 -1
- data/lib/active_record/associations/association.rb +23 -15
- data/lib/active_record/associations/association_scope.rb +83 -81
- data/lib/active_record/associations/belongs_to_association.rb +0 -1
- data/lib/active_record/associations/builder/belongs_to.rb +16 -14
- data/lib/active_record/associations/builder/collection_association.rb +1 -2
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +27 -27
- data/lib/active_record/associations/collection_association.rb +74 -241
- data/lib/active_record/associations/collection_proxy.rb +144 -70
- data/lib/active_record/associations/has_many_association.rb +15 -19
- data/lib/active_record/associations/has_many_through_association.rb +12 -5
- data/lib/active_record/associations/has_one_association.rb +22 -28
- data/lib/active_record/associations/has_one_through_association.rb +5 -1
- data/lib/active_record/associations/join_dependency.rb +117 -115
- data/lib/active_record/associations/join_dependency/join_association.rb +16 -13
- data/lib/active_record/associations/join_dependency/join_base.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_part.rb +1 -1
- data/lib/active_record/associations/preloader.rb +94 -94
- data/lib/active_record/associations/preloader/association.rb +87 -64
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -2
- data/lib/active_record/associations/preloader/collection_association.rb +6 -6
- data/lib/active_record/associations/preloader/has_many.rb +0 -2
- data/lib/active_record/associations/preloader/singular_association.rb +6 -8
- data/lib/active_record/associations/preloader/through_association.rb +34 -41
- data/lib/active_record/associations/singular_association.rb +8 -25
- data/lib/active_record/associations/through_association.rb +3 -6
- data/lib/active_record/attribute.rb +98 -71
- data/lib/active_record/attribute/user_provided_default.rb +4 -2
- data/lib/active_record/attribute_assignment.rb +61 -61
- data/lib/active_record/attribute_decorators.rb +35 -13
- data/lib/active_record/attribute_methods.rb +56 -65
- data/lib/active_record/attribute_methods/before_type_cast.rb +7 -7
- data/lib/active_record/attribute_methods/dirty.rb +216 -34
- data/lib/active_record/attribute_methods/primary_key.rb +78 -73
- data/lib/active_record/attribute_methods/read.rb +39 -35
- data/lib/active_record/attribute_methods/serialization.rb +7 -7
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +35 -58
- data/lib/active_record/attribute_methods/write.rb +36 -30
- data/lib/active_record/attribute_mutation_tracker.rb +53 -10
- data/lib/active_record/attribute_set.rb +9 -6
- data/lib/active_record/attribute_set/builder.rb +41 -49
- data/lib/active_record/attribute_set/yaml_encoder.rb +41 -0
- data/lib/active_record/attributes.rb +21 -21
- data/lib/active_record/autosave_association.rb +13 -13
- data/lib/active_record/base.rb +24 -22
- data/lib/active_record/callbacks.rb +52 -14
- data/lib/active_record/coders/yaml_column.rb +9 -11
- data/lib/active_record/collection_cache_key.rb +6 -17
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +320 -278
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +1 -3
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +22 -34
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +31 -27
- data/lib/active_record/connection_adapters/abstract/quoting.rb +44 -57
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +9 -19
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +78 -79
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +53 -41
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +99 -93
- data/lib/active_record/connection_adapters/abstract/transaction.rb +1 -5
- data/lib/active_record/connection_adapters/abstract_adapter.rb +156 -128
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +424 -382
- data/lib/active_record/connection_adapters/column.rb +27 -5
- data/lib/active_record/connection_adapters/connection_specification.rb +128 -118
- data/lib/active_record/connection_adapters/mysql/column.rb +6 -31
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +45 -43
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +22 -22
- data/lib/active_record/connection_adapters/mysql/quoting.rb +6 -12
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +49 -45
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +16 -19
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +49 -31
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +5 -6
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +24 -26
- data/lib/active_record/connection_adapters/postgresql/column.rb +1 -28
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +46 -35
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +22 -21
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +9 -9
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +16 -16
- data/lib/active_record/connection_adapters/postgresql/oid/{rails_5_1_point.rb → legacy_point.rb} +9 -16
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +28 -8
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +28 -30
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +51 -51
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +38 -36
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +37 -24
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +19 -23
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +161 -170
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -7
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +179 -152
- data/lib/active_record/connection_adapters/schema_cache.rb +16 -7
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +3 -3
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +1 -1
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +16 -20
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +1 -8
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +28 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +17 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +187 -130
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -7
- data/lib/active_record/connection_handling.rb +14 -26
- data/lib/active_record/core.rb +110 -93
- data/lib/active_record/counter_cache.rb +62 -13
- data/lib/active_record/define_callbacks.rb +20 -0
- data/lib/active_record/dynamic_matchers.rb +80 -79
- data/lib/active_record/enum.rb +8 -6
- data/lib/active_record/errors.rb +58 -15
- data/lib/active_record/explain.rb +1 -2
- data/lib/active_record/explain_registry.rb +1 -1
- data/lib/active_record/explain_subscriber.rb +7 -4
- data/lib/active_record/fixture_set/file.rb +11 -8
- data/lib/active_record/fixtures.rb +66 -53
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +93 -79
- data/lib/active_record/integration.rb +7 -7
- data/lib/active_record/internal_metadata.rb +3 -16
- data/lib/active_record/legacy_yaml_adapter.rb +1 -1
- data/lib/active_record/locking/optimistic.rb +64 -56
- data/lib/active_record/locking/pessimistic.rb +10 -1
- data/lib/active_record/log_subscriber.rb +29 -29
- data/lib/active_record/migration.rb +155 -172
- data/lib/active_record/migration/command_recorder.rb +94 -94
- data/lib/active_record/migration/compatibility.rb +76 -37
- data/lib/active_record/migration/join_table.rb +6 -6
- data/lib/active_record/model_schema.rb +85 -119
- data/lib/active_record/nested_attributes.rb +200 -199
- data/lib/active_record/null_relation.rb +10 -33
- data/lib/active_record/persistence.rb +45 -38
- data/lib/active_record/query_cache.rb +4 -8
- data/lib/active_record/querying.rb +2 -3
- data/lib/active_record/railtie.rb +16 -17
- data/lib/active_record/railties/controller_runtime.rb +6 -2
- data/lib/active_record/railties/databases.rake +125 -140
- data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
- data/lib/active_record/readonly_attributes.rb +2 -2
- data/lib/active_record/reflection.rb +79 -96
- data/lib/active_record/relation.rb +72 -115
- data/lib/active_record/relation/batches.rb +87 -58
- data/lib/active_record/relation/batches/batch_enumerator.rb +1 -1
- data/lib/active_record/relation/calculations.rb +154 -160
- data/lib/active_record/relation/delegation.rb +30 -29
- data/lib/active_record/relation/finder_methods.rb +195 -226
- data/lib/active_record/relation/merger.rb +58 -62
- data/lib/active_record/relation/predicate_builder.rb +92 -89
- data/lib/active_record/relation/predicate_builder/array_handler.rb +7 -5
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +23 -23
- data/lib/active_record/relation/predicate_builder/base_handler.rb +3 -1
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +0 -8
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +12 -10
- data/lib/active_record/relation/predicate_builder/range_handler.rb +0 -8
- data/lib/active_record/relation/query_attribute.rb +1 -1
- data/lib/active_record/relation/query_methods.rb +247 -295
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +4 -5
- data/lib/active_record/relation/where_clause.rb +79 -65
- data/lib/active_record/relation/where_clause_factory.rb +47 -8
- data/lib/active_record/result.rb +29 -31
- data/lib/active_record/runtime_registry.rb +3 -3
- data/lib/active_record/sanitization.rb +182 -197
- data/lib/active_record/schema.rb +3 -3
- data/lib/active_record/schema_dumper.rb +14 -37
- data/lib/active_record/schema_migration.rb +3 -3
- data/lib/active_record/scoping.rb +9 -10
- data/lib/active_record/scoping/default.rb +87 -91
- data/lib/active_record/scoping/named.rb +16 -28
- data/lib/active_record/secure_token.rb +2 -2
- data/lib/active_record/statement_cache.rb +13 -15
- data/lib/active_record/store.rb +31 -32
- data/lib/active_record/suppressor.rb +2 -1
- data/lib/active_record/table_metadata.rb +9 -5
- data/lib/active_record/tasks/database_tasks.rb +72 -65
- data/lib/active_record/tasks/mysql_database_tasks.rb +75 -72
- data/lib/active_record/tasks/postgresql_database_tasks.rb +53 -48
- data/lib/active_record/tasks/sqlite_database_tasks.rb +18 -16
- data/lib/active_record/timestamp.rb +39 -25
- data/lib/active_record/touch_later.rb +1 -2
- data/lib/active_record/transactions.rb +98 -110
- data/lib/active_record/type.rb +17 -13
- data/lib/active_record/type/adapter_specific_registry.rb +46 -42
- data/lib/active_record/type/decimal_without_scale.rb +9 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +3 -3
- data/lib/active_record/type/serialized.rb +8 -8
- data/lib/active_record/type/text.rb +9 -0
- data/lib/active_record/type/time.rb +0 -1
- data/lib/active_record/type/type_map.rb +11 -15
- data/lib/active_record/type/unsigned_integer.rb +15 -0
- data/lib/active_record/type_caster.rb +2 -2
- data/lib/active_record/type_caster/connection.rb +8 -6
- data/lib/active_record/type_caster/map.rb +3 -1
- data/lib/active_record/validations.rb +4 -4
- data/lib/active_record/validations/associated.rb +1 -1
- data/lib/active_record/validations/presence.rb +2 -2
- data/lib/active_record/validations/uniqueness.rb +8 -39
- data/lib/active_record/version.rb +1 -1
- data/lib/rails/generators/active_record.rb +4 -4
- data/lib/rails/generators/active_record/migration.rb +2 -2
- data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -34
- data/lib/rails/generators/active_record/model/model_generator.rb +9 -9
- metadata +22 -13
- data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
@@ -25,9 +25,9 @@ module ActiveRecord
|
|
25
25
|
# You're encouraged to add a unique index in the database to deal with this even more unlikely scenario.
|
26
26
|
def has_secure_token(attribute = :token)
|
27
27
|
# Load securerandom only when has_secure_token is used.
|
28
|
-
require
|
28
|
+
require "active_support/core_ext/securerandom"
|
29
29
|
define_method("regenerate_#{attribute}") { update! attribute => self.class.generate_unique_secure_token }
|
30
|
-
before_create {
|
30
|
+
before_create { send("#{attribute}=", self.class.generate_unique_secure_token) unless send("#{attribute}?") }
|
31
31
|
end
|
32
32
|
|
33
33
|
def generate_unique_secure_token
|
@@ -1,5 +1,4 @@
|
|
1
1
|
module ActiveRecord
|
2
|
-
|
3
2
|
# Statement cache is used to cache a single statement in order to avoid creating the AST again.
|
4
3
|
# Initializing the cache is done by passing the statement in the create block:
|
5
4
|
#
|
@@ -8,12 +7,12 @@ module ActiveRecord
|
|
8
7
|
# end
|
9
8
|
#
|
10
9
|
# The cached statement is executed by using the
|
11
|
-
#
|
10
|
+
# {connection.execute}[rdoc-ref:ConnectionAdapters::DatabaseStatements#execute] method:
|
12
11
|
#
|
13
12
|
# cache.execute([], Book, Book.connection)
|
14
13
|
#
|
15
14
|
# The relation returned by the block is cached, and for each
|
16
|
-
# [
|
15
|
+
# {execute}[rdoc-ref:ConnectionAdapters::DatabaseStatements#execute]
|
17
16
|
# call the cached relation gets duped. Database is queried when +to_a+ is called on the relation.
|
18
17
|
#
|
19
18
|
# If you want to cache the statement without the values you can use the +bind+ method of the
|
@@ -40,28 +39,27 @@ module ActiveRecord
|
|
40
39
|
end
|
41
40
|
|
42
41
|
class PartialQuery < Query # :nodoc:
|
43
|
-
def initialize
|
42
|
+
def initialize(values)
|
44
43
|
@values = values
|
45
|
-
@indexes = values.each_with_index.find_all { |thing,i|
|
44
|
+
@indexes = values.each_with_index.find_all { |thing, i|
|
46
45
|
Arel::Nodes::BindParam === thing
|
47
46
|
}.map(&:last)
|
48
47
|
end
|
49
48
|
|
50
49
|
def sql_for(binds, connection)
|
51
50
|
val = @values.dup
|
52
|
-
|
53
|
-
@indexes.each { |i| val[i] = connection.quote(
|
51
|
+
casted_binds = binds.map(&:value_for_database)
|
52
|
+
@indexes.each { |i| val[i] = connection.quote(casted_binds.shift) }
|
54
53
|
val.join
|
55
54
|
end
|
56
55
|
end
|
57
56
|
|
58
|
-
def self.query(
|
59
|
-
Query.new
|
57
|
+
def self.query(sql)
|
58
|
+
Query.new(sql)
|
60
59
|
end
|
61
60
|
|
62
|
-
def self.partial_query(
|
63
|
-
|
64
|
-
PartialQuery.new collected
|
61
|
+
def self.partial_query(values)
|
62
|
+
PartialQuery.new(values)
|
65
63
|
end
|
66
64
|
|
67
65
|
class Params # :nodoc:
|
@@ -70,7 +68,7 @@ module ActiveRecord
|
|
70
68
|
|
71
69
|
class BindMap # :nodoc:
|
72
70
|
def initialize(bound_attributes)
|
73
|
-
@indexes
|
71
|
+
@indexes = []
|
74
72
|
@bound_attributes = bound_attributes
|
75
73
|
|
76
74
|
bound_attributes.each_with_index do |attr, i|
|
@@ -82,7 +80,7 @@ module ActiveRecord
|
|
82
80
|
|
83
81
|
def bind(values)
|
84
82
|
bas = @bound_attributes.dup
|
85
|
-
@indexes.each_with_index { |offset,i| bas[offset] = bas[offset].with_cast_value(values[i]) }
|
83
|
+
@indexes.each_with_index { |offset, i| bas[offset] = bas[offset].with_cast_value(values[i]) }
|
86
84
|
bas
|
87
85
|
end
|
88
86
|
end
|
@@ -92,7 +90,7 @@ module ActiveRecord
|
|
92
90
|
def self.create(connection, block = Proc.new)
|
93
91
|
relation = block.call Params.new
|
94
92
|
bind_map = BindMap.new relation.bound_attributes
|
95
|
-
query_builder = connection.cacheable_query relation.arel
|
93
|
+
query_builder = connection.cacheable_query(self, relation.arel)
|
96
94
|
new query_builder, bind_map
|
97
95
|
end
|
98
96
|
|
data/lib/active_record/store.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "active_support/core_ext/hash/indifferent_access"
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
# Store gives you a thin wrapper around serialize for the purpose of storing hashes in a single column.
|
@@ -78,7 +78,7 @@ module ActiveRecord
|
|
78
78
|
|
79
79
|
module ClassMethods
|
80
80
|
def store(store_attribute, options = {})
|
81
|
-
serialize store_attribute, IndifferentCoder.new(options[:coder])
|
81
|
+
serialize store_attribute, IndifferentCoder.new(store_attribute, options[:coder])
|
82
82
|
store_accessor(store_attribute, options[:accessors]) if options.has_key? :accessors
|
83
83
|
end
|
84
84
|
|
@@ -114,25 +114,24 @@ module ActiveRecord
|
|
114
114
|
|
115
115
|
def stored_attributes
|
116
116
|
parent = superclass.respond_to?(:stored_attributes) ? superclass.stored_attributes : {}
|
117
|
-
if
|
118
|
-
parent.merge!(
|
117
|
+
if local_stored_attributes
|
118
|
+
parent.merge!(local_stored_attributes) { |k, a, b| a | b }
|
119
119
|
end
|
120
120
|
parent
|
121
121
|
end
|
122
122
|
end
|
123
123
|
|
124
|
-
|
125
|
-
def read_store_attribute(store_attribute, key)
|
124
|
+
private
|
125
|
+
def read_store_attribute(store_attribute, key) # :doc:
|
126
126
|
accessor = store_accessor_for(store_attribute)
|
127
127
|
accessor.read(self, store_attribute, key)
|
128
128
|
end
|
129
129
|
|
130
|
-
def write_store_attribute(store_attribute, key, value)
|
130
|
+
def write_store_attribute(store_attribute, key, value) # :doc:
|
131
131
|
accessor = store_accessor_for(store_attribute)
|
132
132
|
accessor.write(self, store_attribute, key, value)
|
133
133
|
end
|
134
134
|
|
135
|
-
private
|
136
135
|
def store_accessor_for(store_attribute)
|
137
136
|
type_for_attribute(store_attribute.to_s).accessor
|
138
137
|
end
|
@@ -177,34 +176,34 @@ module ActiveRecord
|
|
177
176
|
end
|
178
177
|
end
|
179
178
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
179
|
+
class IndifferentCoder # :nodoc:
|
180
|
+
def initialize(attr_name, coder_or_class_name)
|
181
|
+
@coder =
|
182
|
+
if coder_or_class_name.respond_to?(:load) && coder_or_class_name.respond_to?(:dump)
|
183
|
+
coder_or_class_name
|
184
|
+
else
|
185
|
+
ActiveRecord::Coders::YAMLColumn.new(attr_name, coder_or_class_name || Object)
|
186
|
+
end
|
187
|
+
end
|
189
188
|
|
190
|
-
|
191
|
-
|
192
|
-
|
189
|
+
def dump(obj)
|
190
|
+
@coder.dump self.class.as_indifferent_hash(obj)
|
191
|
+
end
|
193
192
|
|
194
|
-
|
195
|
-
|
196
|
-
|
193
|
+
def load(yaml)
|
194
|
+
self.class.as_indifferent_hash(@coder.load(yaml || ""))
|
195
|
+
end
|
197
196
|
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
197
|
+
def self.as_indifferent_hash(obj)
|
198
|
+
case obj
|
199
|
+
when ActiveSupport::HashWithIndifferentAccess
|
200
|
+
obj
|
201
|
+
when Hash
|
202
|
+
obj.with_indifferent_access
|
203
|
+
else
|
204
|
+
ActiveSupport::HashWithIndifferentAccess.new
|
205
|
+
end
|
206
206
|
end
|
207
207
|
end
|
208
|
-
end
|
209
208
|
end
|
210
209
|
end
|
@@ -30,10 +30,11 @@ module ActiveRecord
|
|
30
30
|
|
31
31
|
module ClassMethods
|
32
32
|
def suppress(&block)
|
33
|
+
previous_state = SuppressorRegistry.suppressed[name]
|
33
34
|
SuppressorRegistry.suppressed[name] = true
|
34
35
|
yield
|
35
36
|
ensure
|
36
|
-
SuppressorRegistry.suppressed[name] =
|
37
|
+
SuppressorRegistry.suppressed[name] = previous_state
|
37
38
|
end
|
38
39
|
end
|
39
40
|
|
@@ -10,9 +10,7 @@ module ActiveRecord
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def resolve_column_aliases(hash)
|
13
|
-
|
14
|
-
# https://bugs.ruby-lang.org/issues/7166
|
15
|
-
new_hash = Hash[hash]
|
13
|
+
new_hash = hash.dup
|
16
14
|
hash.each do |key, _|
|
17
15
|
if (key.is_a?(Symbol)) && klass.attribute_alias?(key)
|
18
16
|
new_hash[klass.attribute_alias(key)] = new_hash.delete(key)
|
@@ -33,10 +31,14 @@ module ActiveRecord
|
|
33
31
|
if klass
|
34
32
|
klass.type_for_attribute(column_name.to_s)
|
35
33
|
else
|
36
|
-
Type
|
34
|
+
Type.default_value
|
37
35
|
end
|
38
36
|
end
|
39
37
|
|
38
|
+
def has_column?(column_name)
|
39
|
+
klass && klass.columns_hash.key?(column_name.to_s)
|
40
|
+
end
|
41
|
+
|
40
42
|
def associated_with?(association_name)
|
41
43
|
klass && klass._reflect_on_association(association_name)
|
42
44
|
end
|
@@ -62,8 +64,10 @@ module ActiveRecord
|
|
62
64
|
association && association.polymorphic?
|
63
65
|
end
|
64
66
|
|
67
|
+
# TODO Change this to private once we've dropped Ruby 2.2 support.
|
68
|
+
# Workaround for Ruby 2.2 "private attribute?" warning.
|
65
69
|
protected
|
66
70
|
|
67
|
-
|
71
|
+
attr_reader :klass, :arel_table, :association
|
68
72
|
end
|
69
73
|
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'active_support/core_ext/string/filters'
|
2
|
-
|
3
1
|
module ActiveRecord
|
4
2
|
module Tasks # :nodoc:
|
5
3
|
class DatabaseAlreadyExists < StandardError; end # :nodoc:
|
@@ -35,15 +33,25 @@ module ActiveRecord
|
|
35
33
|
#
|
36
34
|
# DatabaseTasks.create_current('production')
|
37
35
|
module DatabaseTasks
|
36
|
+
##
|
37
|
+
# :singleton-method:
|
38
|
+
# Extra flags passed to database CLI tool (mysqldump/pg_dump) when calling db:structure:dump
|
39
|
+
mattr_accessor :structure_dump_flags, instance_accessor: false
|
40
|
+
|
41
|
+
##
|
42
|
+
# :singleton-method:
|
43
|
+
# Extra flags passed to database CLI tool when calling db:structure:load
|
44
|
+
mattr_accessor :structure_load_flags, instance_accessor: false
|
45
|
+
|
38
46
|
extend self
|
39
47
|
|
40
48
|
attr_writer :current_config, :db_dir, :migrations_paths, :fixtures_path, :root, :env, :seed_loader
|
41
49
|
attr_accessor :database_configuration
|
42
50
|
|
43
|
-
LOCAL_HOSTS
|
51
|
+
LOCAL_HOSTS = ["127.0.0.1", "localhost"]
|
44
52
|
|
45
53
|
def check_protected_environments!
|
46
|
-
unless ENV[
|
54
|
+
unless ENV["DISABLE_DATABASE_ENVIRONMENT_CHECK"]
|
47
55
|
current = ActiveRecord::Migrator.current_environment
|
48
56
|
stored = ActiveRecord::Migrator.last_stored_environment
|
49
57
|
|
@@ -72,15 +80,15 @@ module ActiveRecord
|
|
72
80
|
end
|
73
81
|
|
74
82
|
def migrations_paths
|
75
|
-
@migrations_paths ||= Rails.application.paths[
|
83
|
+
@migrations_paths ||= Rails.application.paths["db/migrate"].to_a
|
76
84
|
end
|
77
85
|
|
78
86
|
def fixtures_path
|
79
|
-
@fixtures_path ||= if ENV[
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
87
|
+
@fixtures_path ||= if ENV["FIXTURES_PATH"]
|
88
|
+
File.join(root, ENV["FIXTURES_PATH"])
|
89
|
+
else
|
90
|
+
File.join(root, "test", "fixtures")
|
91
|
+
end
|
84
92
|
end
|
85
93
|
|
86
94
|
def root
|
@@ -96,7 +104,7 @@ module ActiveRecord
|
|
96
104
|
end
|
97
105
|
|
98
106
|
def current_config(options = {})
|
99
|
-
options.reverse_merge! :
|
107
|
+
options.reverse_merge! env: env
|
100
108
|
if options.has_key?(:config)
|
101
109
|
@current_config = options[:config]
|
102
110
|
else
|
@@ -106,7 +114,7 @@ module ActiveRecord
|
|
106
114
|
|
107
115
|
def create(*arguments)
|
108
116
|
configuration = arguments.first
|
109
|
-
class_for_adapter(configuration[
|
117
|
+
class_for_adapter(configuration["adapter"]).new(*arguments).create
|
110
118
|
$stdout.puts "Created database '#{configuration['database']}'"
|
111
119
|
rescue DatabaseAlreadyExists
|
112
120
|
$stderr.puts "Database '#{configuration['database']}' already exists"
|
@@ -120,7 +128,7 @@ module ActiveRecord
|
|
120
128
|
old_pool = ActiveRecord::Base.connection_handler.retrieve_connection_pool(ActiveRecord::Base.connection_specification_name)
|
121
129
|
each_local_configuration { |configuration| create configuration }
|
122
130
|
if old_pool
|
123
|
-
ActiveRecord::Base.connection_handler.establish_connection(old_pool.spec)
|
131
|
+
ActiveRecord::Base.connection_handler.establish_connection(old_pool.spec.to_hash)
|
124
132
|
end
|
125
133
|
end
|
126
134
|
|
@@ -133,7 +141,7 @@ module ActiveRecord
|
|
133
141
|
|
134
142
|
def drop(*arguments)
|
135
143
|
configuration = arguments.first
|
136
|
-
class_for_adapter(configuration[
|
144
|
+
class_for_adapter(configuration["adapter"]).new(*arguments).drop
|
137
145
|
$stdout.puts "Dropped database '#{configuration['database']}'"
|
138
146
|
rescue ActiveRecord::NoDatabaseError
|
139
147
|
$stderr.puts "Database '#{configuration['database']}' does not exist"
|
@@ -154,11 +162,9 @@ module ActiveRecord
|
|
154
162
|
end
|
155
163
|
|
156
164
|
def migrate
|
157
|
-
raise "Empty VERSION provided" if ENV["VERSION"] && ENV["VERSION"].empty?
|
158
|
-
|
159
165
|
verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
|
160
166
|
version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
|
161
|
-
scope = ENV[
|
167
|
+
scope = ENV["SCOPE"]
|
162
168
|
verbose_was, Migration.verbose = Migration.verbose, verbose
|
163
169
|
Migrator.migrate(migrations_paths, version) do |migration|
|
164
170
|
scope.blank? || scope == migration.scope
|
@@ -174,7 +180,7 @@ module ActiveRecord
|
|
174
180
|
|
175
181
|
def charset(*arguments)
|
176
182
|
configuration = arguments.first
|
177
|
-
class_for_adapter(configuration[
|
183
|
+
class_for_adapter(configuration["adapter"]).new(*arguments).charset
|
178
184
|
end
|
179
185
|
|
180
186
|
def collation_current(environment = env)
|
@@ -183,11 +189,11 @@ module ActiveRecord
|
|
183
189
|
|
184
190
|
def collation(*arguments)
|
185
191
|
configuration = arguments.first
|
186
|
-
class_for_adapter(configuration[
|
192
|
+
class_for_adapter(configuration["adapter"]).new(*arguments).collation
|
187
193
|
end
|
188
194
|
|
189
195
|
def purge(configuration)
|
190
|
-
class_for_adapter(configuration[
|
196
|
+
class_for_adapter(configuration["adapter"]).new(configuration).purge
|
191
197
|
end
|
192
198
|
|
193
199
|
def purge_all
|
@@ -206,39 +212,31 @@ module ActiveRecord
|
|
206
212
|
def structure_dump(*arguments)
|
207
213
|
configuration = arguments.first
|
208
214
|
filename = arguments.delete_at 1
|
209
|
-
class_for_adapter(configuration[
|
215
|
+
class_for_adapter(configuration["adapter"]).new(*arguments).structure_dump(filename, structure_dump_flags)
|
210
216
|
end
|
211
217
|
|
212
218
|
def structure_load(*arguments)
|
213
219
|
configuration = arguments.first
|
214
220
|
filename = arguments.delete_at 1
|
215
|
-
class_for_adapter(configuration[
|
221
|
+
class_for_adapter(configuration["adapter"]).new(*arguments).structure_load(filename, structure_load_flags)
|
216
222
|
end
|
217
223
|
|
218
|
-
def load_schema(configuration, format = ActiveRecord::Base.schema_format, file = nil
|
224
|
+
def load_schema(configuration, format = ActiveRecord::Base.schema_format, file = nil) # :nodoc:
|
219
225
|
file ||= schema_file(format)
|
220
226
|
|
221
|
-
check_schema_file(file)
|
222
|
-
ActiveRecord::Base.establish_connection(configuration)
|
223
|
-
|
224
227
|
case format
|
225
228
|
when :ruby
|
229
|
+
check_schema_file(file)
|
230
|
+
ActiveRecord::Base.establish_connection(configuration)
|
226
231
|
load(file)
|
227
232
|
when :sql
|
233
|
+
check_schema_file(file)
|
228
234
|
structure_load(configuration, file)
|
229
235
|
else
|
230
236
|
raise ArgumentError, "unknown format #{format.inspect}"
|
231
237
|
end
|
232
238
|
ActiveRecord::InternalMetadata.create_table
|
233
|
-
ActiveRecord::InternalMetadata[:environment] =
|
234
|
-
end
|
235
|
-
|
236
|
-
def load_schema_for(*args)
|
237
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
238
|
-
This method was renamed to `#load_schema` and will be removed in the future.
|
239
|
-
Use `#load_schema` instead.
|
240
|
-
MSG
|
241
|
-
load_schema(*args)
|
239
|
+
ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Migrator.current_environment
|
242
240
|
end
|
243
241
|
|
244
242
|
def schema_file(format = ActiveRecord::Base.schema_format)
|
@@ -251,8 +249,8 @@ module ActiveRecord
|
|
251
249
|
end
|
252
250
|
|
253
251
|
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
|
252
|
+
each_current_configuration(environment) { |configuration|
|
253
|
+
load_schema configuration, format, file
|
256
254
|
}
|
257
255
|
ActiveRecord::Base.establish_connection(environment.to_sym)
|
258
256
|
end
|
@@ -260,7 +258,7 @@ module ActiveRecord
|
|
260
258
|
def check_schema_file(filename)
|
261
259
|
unless File.exist?(filename)
|
262
260
|
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
|
261
|
+
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)
|
264
262
|
Kernel.abort message
|
265
263
|
end
|
266
264
|
end
|
@@ -269,48 +267,57 @@ module ActiveRecord
|
|
269
267
|
if seed_loader
|
270
268
|
seed_loader.load_seed
|
271
269
|
else
|
272
|
-
raise "You tried to load seed data, but no seed loader is specified. Please specify seed "
|
273
|
-
"loader with ActiveRecord::Tasks::DatabaseTasks.seed_loader = your_seed_loader\n"
|
270
|
+
raise "You tried to load seed data, but no seed loader is specified. Please specify seed " \
|
271
|
+
"loader with ActiveRecord::Tasks::DatabaseTasks.seed_loader = your_seed_loader\n" \
|
274
272
|
"Seed loader should respond to load_seed method"
|
275
273
|
end
|
276
274
|
end
|
277
275
|
|
276
|
+
# Dumps the schema cache in YAML format for the connection into the file
|
277
|
+
#
|
278
|
+
# ==== Examples:
|
279
|
+
# ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(ActiveRecord::Base.connection, "tmp/schema_dump.yaml")
|
280
|
+
def dump_schema_cache(conn, filename)
|
281
|
+
conn.schema_cache.clear!
|
282
|
+
conn.data_sources.each { |table| conn.schema_cache.add(table) }
|
283
|
+
open(filename, "wb") { |f| f.write(YAML.dump(conn.schema_cache)) }
|
284
|
+
end
|
285
|
+
|
278
286
|
private
|
279
287
|
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
288
|
+
def class_for_adapter(adapter)
|
289
|
+
key = @tasks.keys.detect { |pattern| adapter[pattern] }
|
290
|
+
unless key
|
291
|
+
raise DatabaseNotSupported, "Rake tasks not supported by '#{adapter}' adapter"
|
292
|
+
end
|
293
|
+
@tasks[key]
|
284
294
|
end
|
285
|
-
@tasks[key]
|
286
|
-
end
|
287
|
-
|
288
|
-
def each_current_configuration(environment)
|
289
|
-
environments = [environment]
|
290
|
-
environments << 'test' if environment == 'development'
|
291
295
|
|
292
|
-
|
293
|
-
|
296
|
+
def each_current_configuration(environment)
|
297
|
+
environments = [environment]
|
298
|
+
environments << "test" if environment == "development"
|
294
299
|
|
295
|
-
|
300
|
+
configurations = ActiveRecord::Base.configurations.values_at(*environments)
|
301
|
+
configurations.compact.each do |configuration|
|
302
|
+
yield configuration unless configuration["database"].blank?
|
303
|
+
end
|
296
304
|
end
|
297
|
-
end
|
298
305
|
|
299
|
-
|
300
|
-
|
301
|
-
|
306
|
+
def each_local_configuration
|
307
|
+
ActiveRecord::Base.configurations.each_value do |configuration|
|
308
|
+
next unless configuration["database"]
|
302
309
|
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
310
|
+
if local_database?(configuration)
|
311
|
+
yield configuration
|
312
|
+
else
|
313
|
+
$stderr.puts "This task only modifies local databases. #{configuration['database']} is on a remote host."
|
314
|
+
end
|
307
315
|
end
|
308
316
|
end
|
309
|
-
end
|
310
317
|
|
311
|
-
|
312
|
-
|
313
|
-
|
318
|
+
def local_database?(configuration)
|
319
|
+
configuration["host"].blank? || LOCAL_HOSTS.include?(configuration["host"])
|
320
|
+
end
|
314
321
|
end
|
315
322
|
end
|
316
323
|
end
|