activerecord 5.2.1.1 → 6.0.1
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 +738 -445
- data/MIT-LICENSE +3 -1
- data/README.rdoc +4 -2
- data/examples/performance.rb +1 -1
- data/lib/active_record.rb +9 -2
- data/lib/active_record/aggregations.rb +4 -2
- data/lib/active_record/association_relation.rb +18 -9
- data/lib/active_record/associations.rb +20 -15
- data/lib/active_record/associations/association.rb +69 -20
- 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/association.rb +14 -18
- data/lib/active_record/associations/builder/belongs_to.rb +19 -52
- data/lib/active_record/associations/builder/collection_association.rb +5 -15
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -38
- data/lib/active_record/associations/builder/has_many.rb +2 -0
- data/lib/active_record/associations/builder/has_one.rb +35 -1
- data/lib/active_record/associations/builder/singular_association.rb +2 -0
- data/lib/active_record/associations/collection_association.rb +15 -29
- data/lib/active_record/associations/collection_proxy.rb +19 -48
- data/lib/active_record/associations/foreign_association.rb +7 -0
- data/lib/active_record/associations/has_many_association.rb +11 -10
- data/lib/active_record/associations/has_many_through_association.rb +42 -25
- 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.rb +28 -28
- data/lib/active_record/associations/join_dependency/join_association.rb +27 -7
- data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
- data/lib/active_record/associations/preloader.rb +39 -31
- data/lib/active_record/associations/preloader/association.rb +38 -36
- data/lib/active_record/associations/preloader/through_association.rb +48 -39
- data/lib/active_record/associations/singular_association.rb +2 -16
- data/lib/active_record/attribute_assignment.rb +7 -10
- data/lib/active_record/attribute_methods.rb +28 -100
- data/lib/active_record/attribute_methods/before_type_cast.rb +4 -1
- data/lib/active_record/attribute_methods/dirty.rb +114 -38
- data/lib/active_record/attribute_methods/primary_key.rb +15 -22
- data/lib/active_record/attribute_methods/query.rb +2 -3
- data/lib/active_record/attribute_methods/read.rb +15 -53
- 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 +17 -24
- data/lib/active_record/attributes.rb +13 -0
- data/lib/active_record/autosave_association.rb +27 -13
- data/lib/active_record/base.rb +2 -3
- data/lib/active_record/callbacks.rb +6 -20
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +140 -27
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +22 -4
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +116 -127
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +26 -11
- data/lib/active_record/connection_adapters/abstract/quoting.rb +68 -17
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +19 -12
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +76 -48
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +1 -3
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +135 -56
- data/lib/active_record/connection_adapters/abstract/transaction.rb +96 -56
- data/lib/active_record/connection_adapters/abstract_adapter.rb +189 -43
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +151 -198
- data/lib/active_record/connection_adapters/column.rb +17 -13
- data/lib/active_record/connection_adapters/connection_specification.rb +55 -45
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +9 -4
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +75 -13
- data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -7
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +3 -4
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +40 -32
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +14 -6
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +129 -13
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +6 -10
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +26 -9
- data/lib/active_record/connection_adapters/postgresql/column.rb +17 -31
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +22 -1
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +8 -2
- 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/range.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +6 -3
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +44 -7
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +47 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -91
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +65 -77
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +24 -27
- data/lib/active_record/connection_adapters/postgresql/utils.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +172 -74
- data/lib/active_record/connection_adapters/schema_cache.rb +37 -14
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +11 -8
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +120 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +45 -5
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +42 -11
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +131 -143
- data/lib/active_record/connection_handling.rb +155 -26
- data/lib/active_record/core.rb +104 -59
- data/lib/active_record/counter_cache.rb +4 -29
- data/lib/active_record/database_configurations.rb +233 -0
- 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 +79 -0
- data/lib/active_record/dynamic_matchers.rb +1 -1
- data/lib/active_record/enum.rb +38 -7
- data/lib/active_record/errors.rb +30 -16
- 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 +145 -472
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +13 -3
- data/lib/active_record/insert_all.rb +179 -0
- data/lib/active_record/integration.rb +68 -16
- data/lib/active_record/internal_metadata.rb +10 -2
- data/lib/active_record/locking/optimistic.rb +5 -6
- data/lib/active_record/locking/pessimistic.rb +3 -3
- data/lib/active_record/log_subscriber.rb +7 -26
- data/lib/active_record/middleware/database_selector.rb +75 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +88 -0
- data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
- data/lib/active_record/migration.rb +100 -81
- data/lib/active_record/migration/command_recorder.rb +50 -6
- data/lib/active_record/migration/compatibility.rb +91 -64
- data/lib/active_record/model_schema.rb +34 -10
- data/lib/active_record/nested_attributes.rb +2 -2
- data/lib/active_record/no_touching.rb +7 -0
- data/lib/active_record/persistence.rb +233 -28
- data/lib/active_record/query_cache.rb +11 -4
- data/lib/active_record/querying.rb +33 -21
- data/lib/active_record/railtie.rb +81 -46
- 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 +196 -46
- data/lib/active_record/reflection.rb +42 -44
- data/lib/active_record/relation.rb +320 -70
- data/lib/active_record/relation/batches.rb +13 -10
- data/lib/active_record/relation/calculations.rb +67 -57
- data/lib/active_record/relation/delegation.rb +48 -35
- data/lib/active_record/relation/finder_methods.rb +30 -30
- data/lib/active_record/relation/merger.rb +19 -25
- data/lib/active_record/relation/predicate_builder.rb +18 -15
- data/lib/active_record/relation/predicate_builder/array_handler.rb +7 -6
- 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/query_attribute.rb +17 -10
- data/lib/active_record/relation/query_methods.rb +236 -73
- data/lib/active_record/relation/spawn_methods.rb +1 -1
- data/lib/active_record/relation/where_clause.rb +14 -10
- data/lib/active_record/relation/where_clause_factory.rb +1 -2
- data/lib/active_record/result.rb +30 -11
- data/lib/active_record/sanitization.rb +32 -40
- data/lib/active_record/schema.rb +2 -11
- data/lib/active_record/schema_dumper.rb +22 -7
- data/lib/active_record/schema_migration.rb +5 -1
- data/lib/active_record/scoping.rb +8 -8
- data/lib/active_record/scoping/default.rb +6 -7
- data/lib/active_record/scoping/named.rb +21 -15
- data/lib/active_record/statement_cache.rb +32 -5
- data/lib/active_record/store.rb +87 -8
- data/lib/active_record/table_metadata.rb +10 -17
- data/lib/active_record/tasks/database_tasks.rb +195 -26
- data/lib/active_record/tasks/mysql_database_tasks.rb +5 -5
- 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 +23 -0
- data/lib/active_record/test_fixtures.rb +224 -0
- data/lib/active_record/timestamp.rb +39 -25
- data/lib/active_record/touch_later.rb +4 -2
- data/lib/active_record/transactions.rb +57 -66
- data/lib/active_record/translation.rb +1 -1
- data/lib/active_record/type.rb +3 -4
- data/lib/active_record/type/adapter_specific_registry.rb +1 -8
- data/lib/active_record/type_caster/connection.rb +15 -14
- data/lib/active_record/type_caster/map.rb +1 -4
- data/lib/active_record/validations.rb +1 -0
- data/lib/active_record/validations/uniqueness.rb +15 -27
- data/lib/arel.rb +58 -0
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes.rb +22 -0
- data/lib/arel/attributes/attribute.rb +37 -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.rb +68 -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/comment.rb +29 -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 +67 -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 +45 -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_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -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.rb +20 -0
- data/lib/arel/visitors/depth_first.rb +204 -0
- data/lib/arel/visitors/dot.rb +297 -0
- data/lib/arel/visitors/ibm_db.rb +34 -0
- data/lib/arel/visitors/informix.rb +62 -0
- data/lib/arel/visitors/mssql.rb +157 -0
- data/lib/arel/visitors/mysql.rb +83 -0
- data/lib/arel/visitors/oracle.rb +159 -0
- data/lib/arel/visitors/oracle12.rb +66 -0
- data/lib/arel/visitors/postgresql.rb +110 -0
- data/lib/arel/visitors/sqlite.rb +39 -0
- data/lib/arel/visitors/to_sql.rb +889 -0
- data/lib/arel/visitors/visitor.rb +46 -0
- data/lib/arel/visitors/where_sql.rb +23 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/rails/generators/active_record/migration.rb +14 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +2 -5
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +1 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +1 -0
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
- metadata +111 -27
- data/lib/active_record/collection_cache_key.rb +0 -53
@@ -8,7 +8,7 @@ module ActiveRecord
|
|
8
8
|
module SpawnMethods
|
9
9
|
# This is overridden by Associations::CollectionProxy
|
10
10
|
def spawn #:nodoc:
|
11
|
-
clone
|
11
|
+
already_in_scope? ? klass.all : clone
|
12
12
|
end
|
13
13
|
|
14
14
|
# Merges in the conditions from <tt>other</tt>, if <tt>other</tt> is an ActiveRecord::Relation.
|
@@ -70,7 +70,15 @@ module ActiveRecord
|
|
70
70
|
predicates == other.predicates
|
71
71
|
end
|
72
72
|
|
73
|
-
def invert
|
73
|
+
def invert(as = :nand)
|
74
|
+
if predicates.size == 1
|
75
|
+
inverted_predicates = [ invert_predicate(predicates.first) ]
|
76
|
+
elsif as == :nor
|
77
|
+
inverted_predicates = predicates.map { |node| invert_predicate(node) }
|
78
|
+
else
|
79
|
+
inverted_predicates = [ Arel::Nodes::Not.new(ast) ]
|
80
|
+
end
|
81
|
+
|
74
82
|
WhereClause.new(inverted_predicates)
|
75
83
|
end
|
76
84
|
|
@@ -115,16 +123,16 @@ module ActiveRecord
|
|
115
123
|
node.respond_to?(:operator) && node.operator == :==
|
116
124
|
end
|
117
125
|
|
118
|
-
def inverted_predicates
|
119
|
-
predicates.map { |node| invert_predicate(node) }
|
120
|
-
end
|
121
|
-
|
122
126
|
def invert_predicate(node)
|
123
127
|
case node
|
124
128
|
when NilClass
|
125
129
|
raise ArgumentError, "Invalid argument for .where.not(), got nil."
|
126
130
|
when Arel::Nodes::In
|
127
131
|
Arel::Nodes::NotIn.new(node.left, node.right)
|
132
|
+
when Arel::Nodes::IsNotDistinctFrom
|
133
|
+
Arel::Nodes::IsDistinctFrom.new(node.left, node.right)
|
134
|
+
when Arel::Nodes::IsDistinctFrom
|
135
|
+
Arel::Nodes::IsNotDistinctFrom.new(node.left, node.right)
|
128
136
|
when Arel::Nodes::Equality
|
129
137
|
Arel::Nodes::NotEqual.new(node.left, node.right)
|
130
138
|
when String
|
@@ -136,11 +144,7 @@ module ActiveRecord
|
|
136
144
|
|
137
145
|
def except_predicates(columns)
|
138
146
|
predicates.reject do |node|
|
139
|
-
|
140
|
-
when Arel::Nodes::Between, Arel::Nodes::In, Arel::Nodes::NotIn, Arel::Nodes::Equality, Arel::Nodes::NotEqual, Arel::Nodes::LessThan, Arel::Nodes::LessThanOrEqual, Arel::Nodes::GreaterThan, Arel::Nodes::GreaterThanOrEqual
|
141
|
-
subrelation = (node.left.kind_of?(Arel::Attributes::Attribute) ? node.left : node.right)
|
142
|
-
columns.include?(subrelation.name.to_s)
|
143
|
-
end
|
147
|
+
Arel.fetch_attribute(node) { |attr| columns.include?(attr.name.to_s) }
|
144
148
|
end
|
145
149
|
end
|
146
150
|
|
data/lib/active_record/result.rb
CHANGED
@@ -21,7 +21,7 @@ module ActiveRecord
|
|
21
21
|
# ]
|
22
22
|
#
|
23
23
|
# # Get an array of hashes representing the result (column => value):
|
24
|
-
# result.
|
24
|
+
# result.to_a
|
25
25
|
# # => [{"id" => 1, "title" => "title_1", "body" => "body_1"},
|
26
26
|
# {"id" => 2, "title" => "title_2", "body" => "body_2"},
|
27
27
|
# ...
|
@@ -43,6 +43,11 @@ module ActiveRecord
|
|
43
43
|
@column_types = column_types
|
44
44
|
end
|
45
45
|
|
46
|
+
# Returns true if this result set includes the column named +name+
|
47
|
+
def includes_column?(name)
|
48
|
+
@columns.include? name
|
49
|
+
end
|
50
|
+
|
46
51
|
# Returns the number of elements in the rows array.
|
47
52
|
def length
|
48
53
|
@rows.length
|
@@ -60,9 +65,12 @@ module ActiveRecord
|
|
60
65
|
end
|
61
66
|
end
|
62
67
|
|
63
|
-
# Returns an array of hashes representing each row record.
|
64
68
|
def to_hash
|
65
|
-
|
69
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
70
|
+
`ActiveRecord::Result#to_hash` has been renamed to `to_a`.
|
71
|
+
`to_hash` is deprecated and will be removed in Rails 6.1.
|
72
|
+
MSG
|
73
|
+
to_a
|
66
74
|
end
|
67
75
|
|
68
76
|
alias :map! :map
|
@@ -78,6 +86,8 @@ module ActiveRecord
|
|
78
86
|
hash_rows
|
79
87
|
end
|
80
88
|
|
89
|
+
alias :to_a :to_ary
|
90
|
+
|
81
91
|
def [](idx)
|
82
92
|
hash_rows[idx]
|
83
93
|
end
|
@@ -97,12 +107,21 @@ module ActiveRecord
|
|
97
107
|
end
|
98
108
|
|
99
109
|
def cast_values(type_overrides = {}) # :nodoc:
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
110
|
+
if columns.one?
|
111
|
+
# Separated to avoid allocating an array per row
|
112
|
+
|
113
|
+
type = column_type(columns.first, type_overrides)
|
104
114
|
|
105
|
-
|
115
|
+
rows.map do |(value)|
|
116
|
+
type.deserialize(value)
|
117
|
+
end
|
118
|
+
else
|
119
|
+
types = columns.map { |name| column_type(name, type_overrides) }
|
120
|
+
|
121
|
+
rows.map do |values|
|
122
|
+
Array.new(values.size) { |i| types[i].deserialize(values[i]) }
|
123
|
+
end
|
124
|
+
end
|
106
125
|
end
|
107
126
|
|
108
127
|
def initialize_copy(other)
|
@@ -125,7 +144,9 @@ module ActiveRecord
|
|
125
144
|
begin
|
126
145
|
# We freeze the strings to prevent them getting duped when
|
127
146
|
# used as keys in ActiveRecord::Base's @attributes hash
|
128
|
-
columns = @columns.map
|
147
|
+
columns = @columns.map(&:-@)
|
148
|
+
length = columns.length
|
149
|
+
|
129
150
|
@rows.map { |row|
|
130
151
|
# In the past we used Hash[columns.zip(row)]
|
131
152
|
# though elegant, the verbose way is much more efficient
|
@@ -134,8 +155,6 @@ module ActiveRecord
|
|
134
155
|
hash = {}
|
135
156
|
|
136
157
|
index = 0
|
137
|
-
length = columns.length
|
138
|
-
|
139
158
|
while index < length
|
140
159
|
hash[columns[index]] = row[index]
|
141
160
|
index += 1
|
@@ -61,8 +61,9 @@ module ActiveRecord
|
|
61
61
|
# # => "id ASC"
|
62
62
|
def sanitize_sql_for_order(condition)
|
63
63
|
if condition.is_a?(Array) && condition.first.to_s.include?("?")
|
64
|
-
|
65
|
-
|
64
|
+
disallow_raw_sql!(
|
65
|
+
[condition.first],
|
66
|
+
permit: connection.column_name_with_order_matcher
|
66
67
|
)
|
67
68
|
|
68
69
|
# Ensure we aren't dealing with a subclass of String that might
|
@@ -133,44 +134,34 @@ module ActiveRecord
|
|
133
134
|
end
|
134
135
|
end
|
135
136
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
# Given:
|
142
|
-
#
|
143
|
-
# class Person < ActiveRecord::Base
|
144
|
-
# composed_of :address, class_name: "Address",
|
145
|
-
# mapping: [%w(address_street street), %w(address_city city)]
|
146
|
-
# end
|
147
|
-
#
|
148
|
-
# Then:
|
149
|
-
#
|
150
|
-
# { address: Address.new("813 abc st.", "chicago") }
|
151
|
-
# # => { address_street: "813 abc st.", address_city: "chicago" }
|
152
|
-
def expand_hash_conditions_for_aggregates(attrs) # :doc:
|
153
|
-
expanded_attrs = {}
|
154
|
-
attrs.each do |attr, value|
|
155
|
-
if aggregation = reflect_on_aggregation(attr.to_sym)
|
156
|
-
mapping = aggregation.mapping
|
157
|
-
mapping.each do |field_attr, aggregate_attr|
|
158
|
-
expanded_attrs[field_attr] = if value.is_a?(Array)
|
159
|
-
value.map { |it| it.send(aggregate_attr) }
|
160
|
-
elsif mapping.size == 1 && !value.respond_to?(aggregate_attr)
|
161
|
-
value
|
162
|
-
else
|
163
|
-
value.send(aggregate_attr)
|
164
|
-
end
|
165
|
-
end
|
166
|
-
else
|
167
|
-
expanded_attrs[attr] = value
|
168
|
-
end
|
169
|
-
end
|
170
|
-
expanded_attrs
|
137
|
+
def disallow_raw_sql!(args, permit: connection.column_name_matcher) # :nodoc:
|
138
|
+
unexpected = nil
|
139
|
+
args.each do |arg|
|
140
|
+
next if arg.is_a?(Symbol) || Arel.arel_node?(arg) || permit.match?(arg.to_s)
|
141
|
+
(unexpected ||= []) << arg
|
171
142
|
end
|
172
|
-
deprecate :expand_hash_conditions_for_aggregates
|
173
143
|
|
144
|
+
return unless unexpected
|
145
|
+
|
146
|
+
if allow_unsafe_raw_sql == :deprecated
|
147
|
+
ActiveSupport::Deprecation.warn(
|
148
|
+
"Dangerous query method (method whose arguments are used as raw " \
|
149
|
+
"SQL) called with non-attribute argument(s): " \
|
150
|
+
"#{unexpected.map(&:inspect).join(", ")}. Non-attribute " \
|
151
|
+
"arguments will be disallowed in Rails 6.1. This method should " \
|
152
|
+
"not be called with user-provided values, such as request " \
|
153
|
+
"parameters or model attributes. Known-safe values can be passed " \
|
154
|
+
"by wrapping them in Arel.sql()."
|
155
|
+
)
|
156
|
+
else
|
157
|
+
raise(ActiveRecord::UnknownAttributeReference,
|
158
|
+
"Query method called with non-attribute argument(s): " +
|
159
|
+
unexpected.map(&:inspect).join(", ")
|
160
|
+
)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
private
|
174
165
|
def replace_bind_variables(statement, values)
|
175
166
|
raise_if_bind_arity_mismatch(statement, statement.count("?"), values.size)
|
176
167
|
bound = values.dup
|
@@ -202,10 +193,11 @@ module ActiveRecord
|
|
202
193
|
|
203
194
|
def quote_bound_value(value, c = connection)
|
204
195
|
if value.respond_to?(:map) && !value.acts_like?(:string)
|
205
|
-
|
196
|
+
quoted = value.map { |v| c.quote(v) }
|
197
|
+
if quoted.empty?
|
206
198
|
c.quote(nil)
|
207
199
|
else
|
208
|
-
|
200
|
+
quoted.join(",")
|
209
201
|
end
|
210
202
|
else
|
211
203
|
c.quote(value)
|
data/lib/active_record/schema.rb
CHANGED
@@ -50,21 +50,12 @@ module ActiveRecord
|
|
50
50
|
instance_eval(&block)
|
51
51
|
|
52
52
|
if info[:version].present?
|
53
|
-
|
54
|
-
connection.assume_migrated_upto_version(info[:version]
|
53
|
+
connection.schema_migration.create_table
|
54
|
+
connection.assume_migrated_upto_version(info[:version])
|
55
55
|
end
|
56
56
|
|
57
57
|
ActiveRecord::InternalMetadata.create_table
|
58
58
|
ActiveRecord::InternalMetadata[:environment] = connection.migration_context.current_environment
|
59
59
|
end
|
60
|
-
|
61
|
-
private
|
62
|
-
# Returns the migrations paths.
|
63
|
-
#
|
64
|
-
# ActiveRecord::Schema.new.migrations_paths
|
65
|
-
# # => ["db/migrate"] # Rails migration path by default.
|
66
|
-
def migrations_paths
|
67
|
-
ActiveRecord::Migrator.migrations_paths
|
68
|
-
end
|
69
60
|
end
|
70
61
|
end
|
@@ -17,6 +17,12 @@ module ActiveRecord
|
|
17
17
|
# Only strings are accepted if ActiveRecord::Base.schema_format == :sql.
|
18
18
|
cattr_accessor :ignore_tables, default: []
|
19
19
|
|
20
|
+
##
|
21
|
+
# :singleton-method:
|
22
|
+
# Specify a custom regular expression matching foreign keys which name
|
23
|
+
# should not be dumped to db/schema.rb.
|
24
|
+
cattr_accessor :fk_ignore_pattern, default: /^fk_rails_[0-9a-f]{10}$/
|
25
|
+
|
20
26
|
class << self
|
21
27
|
def dump(connection = ActiveRecord::Base.connection, stream = STDOUT, config = ActiveRecord::Base)
|
22
28
|
connection.create_schema_dumper(generate_options(config)).dump(stream)
|
@@ -41,6 +47,7 @@ module ActiveRecord
|
|
41
47
|
end
|
42
48
|
|
43
49
|
private
|
50
|
+
attr_accessor :table_name
|
44
51
|
|
45
52
|
def initialize(connection, options = {})
|
46
53
|
@connection = connection
|
@@ -65,11 +72,11 @@ module ActiveRecord
|
|
65
72
|
# of editing this file, please use the migrations feature of Active Record to
|
66
73
|
# incrementally modify your database, and then regenerate this schema definition.
|
67
74
|
#
|
68
|
-
#
|
69
|
-
#
|
70
|
-
#
|
71
|
-
# from scratch.
|
72
|
-
#
|
75
|
+
# This file is the source Rails uses to define your schema when running `rails
|
76
|
+
# db:schema:load`. When creating a new database, `rails db:schema:load` tends to
|
77
|
+
# be faster and is potentially less error prone than running all of your
|
78
|
+
# migrations from scratch. Old migrations may fail to apply correctly if those
|
79
|
+
# migrations use external dependencies or application code.
|
73
80
|
#
|
74
81
|
# It's strongly recommended that you check this file into your version control system.
|
75
82
|
|
@@ -104,6 +111,8 @@ HEADER
|
|
104
111
|
def table(table, stream)
|
105
112
|
columns = @connection.columns(table)
|
106
113
|
begin
|
114
|
+
self.table_name = table
|
115
|
+
|
107
116
|
tbl = StringIO.new
|
108
117
|
|
109
118
|
# first dump primary key column
|
@@ -137,7 +146,11 @@ HEADER
|
|
137
146
|
raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" unless @connection.valid_type?(column.type)
|
138
147
|
next if column.name == pk
|
139
148
|
type, colspec = column_spec(column)
|
140
|
-
|
149
|
+
if type.is_a?(Symbol)
|
150
|
+
tbl.print " t.#{type} #{column.name.inspect}"
|
151
|
+
else
|
152
|
+
tbl.print " t.column #{column.name.inspect}, #{type.inspect}"
|
153
|
+
end
|
141
154
|
tbl.print ", #{format_colspec(colspec)}" if colspec.present?
|
142
155
|
tbl.puts
|
143
156
|
end
|
@@ -153,6 +166,8 @@ HEADER
|
|
153
166
|
stream.puts "# Could not dump table #{table.inspect} because of following #{e.class}"
|
154
167
|
stream.puts "# #{e.message}"
|
155
168
|
stream.puts
|
169
|
+
ensure
|
170
|
+
self.table_name = nil
|
156
171
|
end
|
157
172
|
end
|
158
173
|
|
@@ -210,7 +225,7 @@ HEADER
|
|
210
225
|
parts << "primary_key: #{foreign_key.primary_key.inspect}"
|
211
226
|
end
|
212
227
|
|
213
|
-
if foreign_key.
|
228
|
+
if foreign_key.export_name_on_schema_dump?
|
214
229
|
parts << "name: #{foreign_key.name.inspect}"
|
215
230
|
end
|
216
231
|
|
@@ -10,12 +10,16 @@ module ActiveRecord
|
|
10
10
|
# to be executed the next time.
|
11
11
|
class SchemaMigration < ActiveRecord::Base # :nodoc:
|
12
12
|
class << self
|
13
|
+
def _internal?
|
14
|
+
true
|
15
|
+
end
|
16
|
+
|
13
17
|
def primary_key
|
14
18
|
"version"
|
15
19
|
end
|
16
20
|
|
17
21
|
def table_name
|
18
|
-
"#{table_name_prefix}#{
|
22
|
+
"#{table_name_prefix}#{schema_migrations_table_name}#{table_name_suffix}"
|
19
23
|
end
|
20
24
|
|
21
25
|
def table_exists?
|
@@ -12,14 +12,6 @@ module ActiveRecord
|
|
12
12
|
end
|
13
13
|
|
14
14
|
module ClassMethods # :nodoc:
|
15
|
-
def current_scope(skip_inherited_scope = false)
|
16
|
-
ScopeRegistry.value_for(:current_scope, self, skip_inherited_scope)
|
17
|
-
end
|
18
|
-
|
19
|
-
def current_scope=(scope)
|
20
|
-
ScopeRegistry.set_value_for(:current_scope, self, scope)
|
21
|
-
end
|
22
|
-
|
23
15
|
# Collects attributes from scopes that should be applied when creating
|
24
16
|
# an AR instance for the particular class this is called on.
|
25
17
|
def scope_attributes
|
@@ -30,6 +22,14 @@ module ActiveRecord
|
|
30
22
|
def scope_attributes?
|
31
23
|
current_scope
|
32
24
|
end
|
25
|
+
|
26
|
+
def current_scope(skip_inherited_scope = false)
|
27
|
+
ScopeRegistry.value_for(:current_scope, self, skip_inherited_scope)
|
28
|
+
end
|
29
|
+
|
30
|
+
def current_scope=(scope)
|
31
|
+
ScopeRegistry.set_value_for(:current_scope, self, scope)
|
32
|
+
end
|
33
33
|
end
|
34
34
|
|
35
35
|
def populate_with_current_scope_attributes # :nodoc:
|
@@ -86,8 +86,8 @@ module ActiveRecord
|
|
86
86
|
# # Should return a scope, you can call 'super' here etc.
|
87
87
|
# end
|
88
88
|
# end
|
89
|
-
def default_scope(scope = nil) # :doc:
|
90
|
-
scope =
|
89
|
+
def default_scope(scope = nil, &block) # :doc:
|
90
|
+
scope = block if block_given?
|
91
91
|
|
92
92
|
if scope.is_a?(Relation) || !scope.respond_to?(:call)
|
93
93
|
raise ArgumentError,
|
@@ -100,7 +100,7 @@ module ActiveRecord
|
|
100
100
|
self.default_scopes += [scope]
|
101
101
|
end
|
102
102
|
|
103
|
-
def build_default_scope(
|
103
|
+
def build_default_scope(relation = relation())
|
104
104
|
return if abstract_class?
|
105
105
|
|
106
106
|
if default_scope_override.nil?
|
@@ -111,15 +111,14 @@ module ActiveRecord
|
|
111
111
|
# The user has defined their own default scope method, so call that
|
112
112
|
evaluate_default_scope do
|
113
113
|
if scope = default_scope
|
114
|
-
|
114
|
+
relation.merge!(scope)
|
115
115
|
end
|
116
116
|
end
|
117
117
|
elsif default_scopes.any?
|
118
|
-
base_rel ||= relation
|
119
118
|
evaluate_default_scope do
|
120
|
-
default_scopes.inject(
|
119
|
+
default_scopes.inject(relation) do |default_scope, scope|
|
121
120
|
scope = scope.respond_to?(:to_proc) ? scope : scope.method(:call)
|
122
|
-
default_scope.
|
121
|
+
default_scope.instance_exec(&scope) || default_scope
|
123
122
|
end
|
124
123
|
end
|
125
124
|
end
|
@@ -24,13 +24,21 @@ module ActiveRecord
|
|
24
24
|
# You can define a scope that applies to all finders using
|
25
25
|
# {default_scope}[rdoc-ref:Scoping::Default::ClassMethods#default_scope].
|
26
26
|
def all
|
27
|
-
|
27
|
+
scope = current_scope
|
28
28
|
|
29
|
-
if
|
30
|
-
if
|
31
|
-
|
29
|
+
if scope
|
30
|
+
if scope._deprecated_scope_source
|
31
|
+
ActiveSupport::Deprecation.warn(<<~MSG.squish)
|
32
|
+
Class level methods will no longer inherit scoping from `#{scope._deprecated_scope_source}`
|
33
|
+
in Rails 6.1. To continue using the scoped relation, pass it into the block directly.
|
34
|
+
To instead access the full set of models, as Rails 6.1 will, use `#{name}.unscoped`.
|
35
|
+
MSG
|
36
|
+
end
|
37
|
+
|
38
|
+
if self == scope.klass
|
39
|
+
scope.clone
|
32
40
|
else
|
33
|
-
relation.merge!(
|
41
|
+
relation.merge!(scope)
|
34
42
|
end
|
35
43
|
else
|
36
44
|
default_scoped
|
@@ -38,9 +46,7 @@ module ActiveRecord
|
|
38
46
|
end
|
39
47
|
|
40
48
|
def scope_for_association(scope = relation) # :nodoc:
|
41
|
-
|
42
|
-
|
43
|
-
if current_scope && current_scope.empty_scope?
|
49
|
+
if current_scope&.empty_scope?
|
44
50
|
scope
|
45
51
|
else
|
46
52
|
default_scoped(scope)
|
@@ -52,7 +58,7 @@ module ActiveRecord
|
|
52
58
|
end
|
53
59
|
|
54
60
|
def default_extensions # :nodoc:
|
55
|
-
if scope =
|
61
|
+
if scope = scope_for_association || build_default_scope
|
56
62
|
scope.extensions
|
57
63
|
else
|
58
64
|
[]
|
@@ -181,20 +187,20 @@ module ActiveRecord
|
|
181
187
|
extension = Module.new(&block) if block
|
182
188
|
|
183
189
|
if body.respond_to?(:to_proc)
|
184
|
-
singleton_class.
|
185
|
-
scope = all
|
186
|
-
scope = scope._exec_scope(*args, &body)
|
190
|
+
singleton_class.define_method(name) do |*args|
|
191
|
+
scope = all._exec_scope(name, *args, &body)
|
187
192
|
scope = scope.extending(extension) if extension
|
188
193
|
scope
|
189
194
|
end
|
190
195
|
else
|
191
|
-
singleton_class.
|
192
|
-
scope = all
|
193
|
-
scope = scope.scoping { body.call(*args) || scope }
|
196
|
+
singleton_class.define_method(name) do |*args|
|
197
|
+
scope = body.call(*args) || all
|
194
198
|
scope = scope.extending(extension) if extension
|
195
199
|
scope
|
196
200
|
end
|
197
201
|
end
|
202
|
+
|
203
|
+
generate_relation_method(name)
|
198
204
|
end
|
199
205
|
|
200
206
|
private
|