activerecord 5.2.8.1 → 6.1.0
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 +849 -630
- data/MIT-LICENSE +3 -1
- data/README.rdoc +7 -5
- data/examples/performance.rb +1 -1
- data/lib/active_record/aggregations.rb +5 -4
- data/lib/active_record/association_relation.rb +22 -12
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +95 -42
- data/lib/active_record/associations/association_scope.rb +21 -21
- data/lib/active_record/associations/belongs_to_association.rb +50 -46
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +1 -5
- data/lib/active_record/associations/builder/association.rb +23 -21
- data/lib/active_record/associations/builder/belongs_to.rb +29 -59
- data/lib/active_record/associations/builder/collection_association.rb +8 -17
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -41
- data/lib/active_record/associations/builder/has_many.rb +8 -2
- data/lib/active_record/associations/builder/has_one.rb +33 -2
- data/lib/active_record/associations/builder/singular_association.rb +3 -1
- data/lib/active_record/associations/collection_association.rb +31 -29
- data/lib/active_record/associations/collection_proxy.rb +25 -21
- data/lib/active_record/associations/foreign_association.rb +20 -0
- data/lib/active_record/associations/has_many_association.rb +26 -13
- data/lib/active_record/associations/has_many_through_association.rb +24 -18
- data/lib/active_record/associations/has_one_association.rb +43 -31
- data/lib/active_record/associations/has_one_through_association.rb +5 -5
- data/lib/active_record/associations/join_dependency/join_association.rb +41 -20
- data/lib/active_record/associations/join_dependency/join_part.rb +5 -5
- data/lib/active_record/associations/join_dependency.rb +91 -60
- data/lib/active_record/associations/preloader/association.rb +71 -43
- data/lib/active_record/associations/preloader/through_association.rb +49 -40
- data/lib/active_record/associations/preloader.rb +47 -34
- data/lib/active_record/associations/singular_association.rb +3 -17
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/associations.rb +133 -25
- data/lib/active_record/attribute_assignment.rb +17 -19
- data/lib/active_record/attribute_methods/before_type_cast.rb +13 -7
- data/lib/active_record/attribute_methods/dirty.rb +101 -40
- data/lib/active_record/attribute_methods/primary_key.rb +20 -25
- data/lib/active_record/attribute_methods/query.rb +4 -8
- data/lib/active_record/attribute_methods/read.rb +14 -56
- data/lib/active_record/attribute_methods/serialization.rb +12 -7
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -15
- data/lib/active_record/attribute_methods/write.rb +18 -34
- data/lib/active_record/attribute_methods.rb +81 -143
- data/lib/active_record/attributes.rb +45 -8
- data/lib/active_record/autosave_association.rb +57 -42
- data/lib/active_record/base.rb +4 -17
- data/lib/active_record/callbacks.rb +158 -43
- data/lib/active_record/coders/yaml_column.rb +2 -15
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +272 -130
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +7 -36
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +167 -146
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +18 -14
- data/lib/active_record/connection_adapters/abstract/quoting.rb +98 -47
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -110
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +203 -90
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -4
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +381 -146
- data/lib/active_record/connection_adapters/abstract/transaction.rb +155 -68
- data/lib/active_record/connection_adapters/abstract_adapter.rb +229 -98
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +243 -275
- data/lib/active_record/connection_adapters/column.rb +30 -12
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +31 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +86 -32
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
- data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -7
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +34 -10
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +48 -32
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +14 -6
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +139 -19
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +14 -9
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +53 -18
- data/lib/active_record/connection_adapters/pool_config.rb +63 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +43 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +37 -28
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +38 -54
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +10 -2
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +3 -4
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +3 -4
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +25 -7
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.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 +15 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +47 -10
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +19 -4
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -91
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +120 -100
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +31 -26
- data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +222 -112
- data/lib/active_record/connection_adapters/schema_cache.rb +127 -21
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +19 -6
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +144 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +42 -7
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +77 -13
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +174 -186
- data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
- data/lib/active_record/connection_adapters.rb +50 -0
- data/lib/active_record/connection_handling.rb +285 -33
- data/lib/active_record/core.rb +304 -106
- data/lib/active_record/counter_cache.rb +8 -30
- data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
- data/lib/active_record/database_configurations/database_config.rb +80 -0
- data/lib/active_record/database_configurations/hash_config.rb +96 -0
- data/lib/active_record/database_configurations/url_config.rb +53 -0
- data/lib/active_record/database_configurations.rb +272 -0
- data/lib/active_record/delegated_type.rb +209 -0
- data/lib/active_record/destroy_association_async_job.rb +36 -0
- data/lib/active_record/dynamic_matchers.rb +3 -4
- data/lib/active_record/enum.rb +71 -17
- data/lib/active_record/errors.rb +62 -19
- data/lib/active_record/explain.rb +10 -6
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +10 -17
- data/lib/active_record/fixture_set/model_metadata.rb +32 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +152 -0
- data/lib/active_record/fixture_set/table_rows.rb +46 -0
- data/lib/active_record/fixtures.rb +197 -481
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +53 -24
- data/lib/active_record/insert_all.rb +208 -0
- data/lib/active_record/integration.rb +67 -17
- data/lib/active_record/internal_metadata.rb +26 -9
- data/lib/active_record/legacy_yaml_adapter.rb +7 -3
- data/lib/active_record/locking/optimistic.rb +26 -22
- data/lib/active_record/locking/pessimistic.rb +9 -5
- data/lib/active_record/log_subscriber.rb +34 -35
- data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector.rb +77 -0
- data/lib/active_record/migration/command_recorder.rb +96 -44
- data/lib/active_record/migration/compatibility.rb +141 -64
- data/lib/active_record/migration/join_table.rb +0 -1
- data/lib/active_record/migration.rb +205 -156
- data/lib/active_record/model_schema.rb +148 -22
- data/lib/active_record/nested_attributes.rb +4 -7
- data/lib/active_record/no_touching.rb +8 -1
- data/lib/active_record/null_relation.rb +0 -1
- data/lib/active_record/persistence.rb +267 -59
- data/lib/active_record/query_cache.rb +21 -4
- data/lib/active_record/querying.rb +40 -23
- data/lib/active_record/railtie.rb +113 -74
- data/lib/active_record/railties/controller_runtime.rb +30 -35
- data/lib/active_record/railties/databases.rake +402 -78
- data/lib/active_record/readonly_attributes.rb +4 -0
- data/lib/active_record/reflection.rb +109 -93
- data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
- data/lib/active_record/relation/batches.rb +44 -35
- data/lib/active_record/relation/calculations.rb +153 -90
- data/lib/active_record/relation/delegation.rb +35 -50
- data/lib/active_record/relation/finder_methods.rb +64 -39
- data/lib/active_record/relation/from_clause.rb +5 -1
- data/lib/active_record/relation/merger.rb +32 -40
- data/lib/active_record/relation/predicate_builder/array_handler.rb +13 -13
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +5 -9
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +4 -7
- data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/predicate_builder.rb +58 -40
- data/lib/active_record/relation/query_attribute.rb +13 -8
- data/lib/active_record/relation/query_methods.rb +472 -186
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +9 -9
- data/lib/active_record/relation/where_clause.rb +108 -58
- data/lib/active_record/relation.rb +375 -104
- data/lib/active_record/result.rb +64 -38
- data/lib/active_record/runtime_registry.rb +2 -2
- data/lib/active_record/sanitization.rb +22 -41
- data/lib/active_record/schema.rb +2 -11
- data/lib/active_record/schema_dumper.rb +54 -9
- data/lib/active_record/schema_migration.rb +7 -9
- data/lib/active_record/scoping/default.rb +4 -6
- data/lib/active_record/scoping/named.rb +17 -24
- data/lib/active_record/scoping.rb +8 -9
- data/lib/active_record/secure_token.rb +16 -8
- data/lib/active_record/serialization.rb +5 -3
- data/lib/active_record/signed_id.rb +116 -0
- data/lib/active_record/statement_cache.rb +49 -6
- data/lib/active_record/store.rb +88 -9
- data/lib/active_record/suppressor.rb +2 -2
- data/lib/active_record/table_metadata.rb +39 -43
- data/lib/active_record/tasks/database_tasks.rb +276 -81
- data/lib/active_record/tasks/mysql_database_tasks.rb +37 -39
- data/lib/active_record/tasks/postgresql_database_tasks.rb +27 -32
- data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -17
- data/lib/active_record/test_databases.rb +24 -0
- data/lib/active_record/test_fixtures.rb +246 -0
- data/lib/active_record/timestamp.rb +43 -32
- data/lib/active_record/touch_later.rb +23 -22
- data/lib/active_record/transactions.rb +58 -116
- data/lib/active_record/translation.rb +1 -1
- data/lib/active_record/type/adapter_specific_registry.rb +3 -13
- data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
- data/lib/active_record/type/serialized.rb +6 -3
- data/lib/active_record/type/time.rb +10 -0
- data/lib/active_record/type/type_map.rb +0 -1
- data/lib/active_record/type/unsigned_integer.rb +0 -1
- data/lib/active_record/type.rb +10 -5
- data/lib/active_record/type_caster/connection.rb +15 -15
- data/lib/active_record/type_caster/map.rb +8 -8
- data/lib/active_record/validations/associated.rb +1 -2
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/uniqueness.rb +38 -30
- data/lib/active_record/validations.rb +4 -3
- data/lib/active_record.rb +13 -12
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +41 -0
- data/lib/arel/collectors/bind.rb +29 -0
- data/lib/arel/collectors/composite.rb +39 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +27 -0
- data/lib/arel/collectors/substitute_binds.rb +35 -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 +126 -0
- data/lib/arel/nodes/bind_param.rb +44 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +62 -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 +15 -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 +11 -0
- data/lib/arel/nodes/homogeneous_in.rb +72 -0
- data/lib/arel/nodes/in.rb +15 -0
- data/lib/arel/nodes/infix_operation.rb +92 -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 +51 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/ordering.rb +27 -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 +19 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +31 -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_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/nodes.rb +70 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +250 -0
- data/lib/arel/select_manager.rb +270 -0
- data/lib/arel/table.rb +118 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors/dot.rb +308 -0
- data/lib/arel/visitors/mysql.rb +93 -0
- data/lib/arel/visitors/postgresql.rb +120 -0
- data/lib/arel/visitors/sqlite.rb +38 -0
- data/lib/arel/visitors/to_sql.rb +899 -0
- data/lib/arel/visitors/visitor.rb +45 -0
- data/lib/arel/visitors.rb +13 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +54 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -5
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +3 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +7 -5
- data/lib/rails/generators/active_record/migration.rb +19 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
- metadata +120 -35
- data/lib/active_record/attribute_decorators.rb +0 -90
- data/lib/active_record/collection_cache_key.rb +0 -53
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -287
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -33
- data/lib/active_record/define_callbacks.rb +0 -22
- data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -19
- data/lib/active_record/relation/where_clause_factory.rb +0 -34
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,13 +65,10 @@ module ActiveRecord
|
|
60
65
|
end
|
61
66
|
end
|
62
67
|
|
63
|
-
# Returns an array of hashes representing each row record.
|
64
|
-
def to_hash
|
65
|
-
hash_rows
|
66
|
-
end
|
67
|
-
|
68
68
|
alias :map! :map
|
69
69
|
alias :collect! :map
|
70
|
+
deprecate "map!": :map
|
71
|
+
deprecate "collect!": :map
|
70
72
|
|
71
73
|
# Returns true if there are no records, otherwise false.
|
72
74
|
def empty?
|
@@ -78,31 +80,41 @@ module ActiveRecord
|
|
78
80
|
hash_rows
|
79
81
|
end
|
80
82
|
|
83
|
+
alias :to_a :to_ary
|
84
|
+
|
81
85
|
def [](idx)
|
82
86
|
hash_rows[idx]
|
83
87
|
end
|
84
88
|
|
85
|
-
# Returns the first record from the rows collection.
|
86
|
-
# If the rows collection is empty, returns +nil+.
|
87
|
-
def first
|
88
|
-
return nil if @rows.empty?
|
89
|
-
Hash[@columns.zip(@rows.first)]
|
90
|
-
end
|
91
|
-
|
92
89
|
# Returns the last record from the rows collection.
|
93
|
-
|
94
|
-
|
95
|
-
return nil if @rows.empty?
|
96
|
-
Hash[@columns.zip(@rows.last)]
|
90
|
+
def last(n = nil)
|
91
|
+
n ? hash_rows.last(n) : hash_rows.last
|
97
92
|
end
|
98
93
|
|
99
94
|
def cast_values(type_overrides = {}) # :nodoc:
|
100
|
-
|
101
|
-
|
102
|
-
types.zip(values).map { |type, value| type.deserialize(value) }
|
103
|
-
end
|
95
|
+
if columns.one?
|
96
|
+
# Separated to avoid allocating an array per row
|
104
97
|
|
105
|
-
|
98
|
+
type = if type_overrides.is_a?(Array)
|
99
|
+
type_overrides.first
|
100
|
+
else
|
101
|
+
column_type(columns.first, type_overrides)
|
102
|
+
end
|
103
|
+
|
104
|
+
rows.map do |(value)|
|
105
|
+
type.deserialize(value)
|
106
|
+
end
|
107
|
+
else
|
108
|
+
types = if type_overrides.is_a?(Array)
|
109
|
+
type_overrides
|
110
|
+
else
|
111
|
+
columns.map { |name| column_type(name, type_overrides) }
|
112
|
+
end
|
113
|
+
|
114
|
+
rows.map do |values|
|
115
|
+
Array.new(values.size) { |i| types[i].deserialize(values[i]) }
|
116
|
+
end
|
117
|
+
end
|
106
118
|
end
|
107
119
|
|
108
120
|
def initialize_copy(other)
|
@@ -113,7 +125,6 @@ module ActiveRecord
|
|
113
125
|
end
|
114
126
|
|
115
127
|
private
|
116
|
-
|
117
128
|
def column_type(name, type_overrides = {})
|
118
129
|
type_overrides.fetch(name) do
|
119
130
|
column_types.fetch(name, Type.default_value)
|
@@ -125,23 +136,38 @@ module ActiveRecord
|
|
125
136
|
begin
|
126
137
|
# We freeze the strings to prevent them getting duped when
|
127
138
|
# used as keys in ActiveRecord::Base's @attributes hash
|
128
|
-
columns = @columns.map
|
139
|
+
columns = @columns.map(&:-@)
|
140
|
+
length = columns.length
|
141
|
+
template = nil
|
142
|
+
|
129
143
|
@rows.map { |row|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
144
|
+
if template
|
145
|
+
# We use transform_values to build subsequent rows from the
|
146
|
+
# hash of the first row. This is faster because we avoid any
|
147
|
+
# reallocs and in Ruby 2.7+ avoid hashing entirely.
|
148
|
+
index = -1
|
149
|
+
template.transform_values do
|
150
|
+
row[index += 1]
|
151
|
+
end
|
152
|
+
else
|
153
|
+
# In the past we used Hash[columns.zip(row)]
|
154
|
+
# though elegant, the verbose way is much more efficient
|
155
|
+
# both time and memory wise cause it avoids a big array allocation
|
156
|
+
# this method is called a lot and needs to be micro optimised
|
157
|
+
hash = {}
|
158
|
+
|
159
|
+
index = 0
|
160
|
+
while index < length
|
161
|
+
hash[columns[index]] = row[index]
|
162
|
+
index += 1
|
163
|
+
end
|
164
|
+
|
165
|
+
# It's possible to select the same column twice, in which case
|
166
|
+
# we can't use a template
|
167
|
+
template = hash if hash.length == length
|
168
|
+
|
169
|
+
hash
|
142
170
|
end
|
143
|
-
|
144
|
-
hash
|
145
171
|
}
|
146
172
|
end
|
147
173
|
end
|
@@ -14,9 +14,9 @@ module ActiveRecord
|
|
14
14
|
class RuntimeRegistry # :nodoc:
|
15
15
|
extend ActiveSupport::PerThreadRegistry
|
16
16
|
|
17
|
-
attr_accessor :
|
17
|
+
attr_accessor :sql_runtime
|
18
18
|
|
19
|
-
[:
|
19
|
+
[:sql_runtime].each do |val|
|
20
20
|
class_eval %{ def self.#{val}; instance.#{val}; end }, __FILE__, __LINE__
|
21
21
|
class_eval %{ def self.#{val}=(x); instance.#{val}=x; end }, __FILE__, __LINE__
|
22
22
|
end
|
@@ -61,12 +61,13 @@ 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
|
69
|
-
# override methods we use (
|
70
|
+
# override methods we use (e.g. Arel::Nodes::SqlLiteral).
|
70
71
|
if condition.first.kind_of?(String) && !condition.first.instance_of?(String)
|
71
72
|
condition = [String.new(condition.first), *condition[1..-1]]
|
72
73
|
end
|
@@ -133,44 +134,22 @@ 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
|
+
if unexpected
|
145
|
+
raise(ActiveRecord::UnknownAttributeReference,
|
146
|
+
"Query method called with non-attribute argument(s): " +
|
147
|
+
unexpected.map(&:inspect).join(", ")
|
148
|
+
)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
private
|
174
153
|
def replace_bind_variables(statement, values)
|
175
154
|
raise_if_bind_arity_mismatch(statement, statement.count("?"), values.size)
|
176
155
|
bound = values.dup
|
@@ -202,12 +181,14 @@ module ActiveRecord
|
|
202
181
|
|
203
182
|
def quote_bound_value(value, c = connection)
|
204
183
|
if value.respond_to?(:map) && !value.acts_like?(:string)
|
205
|
-
|
184
|
+
values = value.map { |v| v.respond_to?(:id_for_database) ? v.id_for_database : v }
|
185
|
+
if values.empty?
|
206
186
|
c.quote(nil)
|
207
187
|
else
|
208
|
-
|
188
|
+
values.map! { |v| c.quote(v) }.join(",")
|
209
189
|
end
|
210
190
|
else
|
191
|
+
value = value.id_for_database if value.respond_to?(:id_for_database)
|
211
192
|
c.quote(value)
|
212
193
|
end
|
213
194
|
end
|
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,18 @@ 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
|
+
|
26
|
+
##
|
27
|
+
# :singleton-method:
|
28
|
+
# Specify a custom regular expression matching check constraints which name
|
29
|
+
# should not be dumped to db/schema.rb.
|
30
|
+
cattr_accessor :chk_ignore_pattern, default: /^chk_rails_[0-9a-f]{10}$/
|
31
|
+
|
20
32
|
class << self
|
21
33
|
def dump(connection = ActiveRecord::Base.connection, stream = STDOUT, config = ActiveRecord::Base)
|
22
34
|
connection.create_schema_dumper(generate_options(config)).dump(stream)
|
@@ -41,6 +53,7 @@ module ActiveRecord
|
|
41
53
|
end
|
42
54
|
|
43
55
|
private
|
56
|
+
attr_accessor :table_name
|
44
57
|
|
45
58
|
def initialize(connection, options = {})
|
46
59
|
@connection = connection
|
@@ -65,11 +78,11 @@ module ActiveRecord
|
|
65
78
|
# of editing this file, please use the migrations feature of Active Record to
|
66
79
|
# incrementally modify your database, and then regenerate this schema definition.
|
67
80
|
#
|
68
|
-
#
|
69
|
-
#
|
70
|
-
#
|
71
|
-
# from scratch.
|
72
|
-
#
|
81
|
+
# This file is the source Rails uses to define your schema when running `bin/rails
|
82
|
+
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
|
83
|
+
# be faster and is potentially less error prone than running all of your
|
84
|
+
# migrations from scratch. Old migrations may fail to apply correctly if those
|
85
|
+
# migrations use external dependencies or application code.
|
73
86
|
#
|
74
87
|
# It's strongly recommended that you check this file into your version control system.
|
75
88
|
|
@@ -104,6 +117,8 @@ HEADER
|
|
104
117
|
def table(table, stream)
|
105
118
|
columns = @connection.columns(table)
|
106
119
|
begin
|
120
|
+
self.table_name = table
|
121
|
+
|
107
122
|
tbl = StringIO.new
|
108
123
|
|
109
124
|
# first dump primary key column
|
@@ -116,7 +131,10 @@ HEADER
|
|
116
131
|
tbl.print ", primary_key: #{pk.inspect}" unless pk == "id"
|
117
132
|
pkcol = columns.detect { |c| c.name == pk }
|
118
133
|
pkcolspec = column_spec_for_primary_key(pkcol)
|
119
|
-
|
134
|
+
unless pkcolspec.empty?
|
135
|
+
if pkcolspec != pkcolspec.slice(:id, :default)
|
136
|
+
pkcolspec = { id: { type: pkcolspec.delete(:id), **pkcolspec }.compact }
|
137
|
+
end
|
120
138
|
tbl.print ", #{format_colspec(pkcolspec)}"
|
121
139
|
end
|
122
140
|
when Array
|
@@ -137,12 +155,17 @@ HEADER
|
|
137
155
|
raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" unless @connection.valid_type?(column.type)
|
138
156
|
next if column.name == pk
|
139
157
|
type, colspec = column_spec(column)
|
140
|
-
|
158
|
+
if type.is_a?(Symbol)
|
159
|
+
tbl.print " t.#{type} #{column.name.inspect}"
|
160
|
+
else
|
161
|
+
tbl.print " t.column #{column.name.inspect}, #{type.inspect}"
|
162
|
+
end
|
141
163
|
tbl.print ", #{format_colspec(colspec)}" if colspec.present?
|
142
164
|
tbl.puts
|
143
165
|
end
|
144
166
|
|
145
167
|
indexes_in_create(table, tbl)
|
168
|
+
check_constraints_in_create(table, tbl) if @connection.supports_check_constraints?
|
146
169
|
|
147
170
|
tbl.puts " end"
|
148
171
|
tbl.puts
|
@@ -153,6 +176,8 @@ HEADER
|
|
153
176
|
stream.puts "# Could not dump table #{table.inspect} because of following #{e.class}"
|
154
177
|
stream.puts "# #{e.message}"
|
155
178
|
stream.puts
|
179
|
+
ensure
|
180
|
+
self.table_name = nil
|
156
181
|
end
|
157
182
|
end
|
158
183
|
|
@@ -194,6 +219,24 @@ HEADER
|
|
194
219
|
index_parts
|
195
220
|
end
|
196
221
|
|
222
|
+
def check_constraints_in_create(table, stream)
|
223
|
+
if (check_constraints = @connection.check_constraints(table)).any?
|
224
|
+
add_check_constraint_statements = check_constraints.map do |check_constraint|
|
225
|
+
parts = [
|
226
|
+
"t.check_constraint #{check_constraint.expression.inspect}"
|
227
|
+
]
|
228
|
+
|
229
|
+
if check_constraint.export_name_on_schema_dump?
|
230
|
+
parts << "name: #{check_constraint.name.inspect}"
|
231
|
+
end
|
232
|
+
|
233
|
+
" #{parts.join(', ')}"
|
234
|
+
end
|
235
|
+
|
236
|
+
stream.puts add_check_constraint_statements.sort.join("\n")
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
197
240
|
def foreign_keys(table, stream)
|
198
241
|
if (foreign_keys = @connection.foreign_keys(table)).any?
|
199
242
|
add_foreign_key_statements = foreign_keys.map do |foreign_key|
|
@@ -210,7 +253,7 @@ HEADER
|
|
210
253
|
parts << "primary_key: #{foreign_key.primary_key.inspect}"
|
211
254
|
end
|
212
255
|
|
213
|
-
if foreign_key.
|
256
|
+
if foreign_key.export_name_on_schema_dump?
|
214
257
|
parts << "name: #{foreign_key.name.inspect}"
|
215
258
|
end
|
216
259
|
|
@@ -225,7 +268,9 @@ HEADER
|
|
225
268
|
end
|
226
269
|
|
227
270
|
def format_colspec(colspec)
|
228
|
-
colspec.map
|
271
|
+
colspec.map do |key, value|
|
272
|
+
"#{key}: #{ value.is_a?(Hash) ? "{ #{format_colspec(value)} }" : value }"
|
273
|
+
end.join(", ")
|
229
274
|
end
|
230
275
|
|
231
276
|
def format_options(options)
|
@@ -10,24 +10,22 @@ 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}#{
|
19
|
-
end
|
20
|
-
|
21
|
-
def table_exists?
|
22
|
-
connection.table_exists?(table_name)
|
22
|
+
"#{table_name_prefix}#{schema_migrations_table_name}#{table_name_suffix}"
|
23
23
|
end
|
24
24
|
|
25
25
|
def create_table
|
26
|
-
unless table_exists?
|
27
|
-
version_options = connection.internal_string_options_for_primary_key
|
28
|
-
|
26
|
+
unless connection.table_exists?(table_name)
|
29
27
|
connection.create_table(table_name, id: false) do |t|
|
30
|
-
t.string :version,
|
28
|
+
t.string :version, **connection.internal_string_options_for_primary_key
|
31
29
|
end
|
32
30
|
end
|
33
31
|
end
|
@@ -44,7 +44,6 @@ module ActiveRecord
|
|
44
44
|
end
|
45
45
|
|
46
46
|
private
|
47
|
-
|
48
47
|
# Use this macro in your model to set a default scope for all operations on
|
49
48
|
# the model.
|
50
49
|
#
|
@@ -100,7 +99,7 @@ module ActiveRecord
|
|
100
99
|
self.default_scopes += [scope]
|
101
100
|
end
|
102
101
|
|
103
|
-
def build_default_scope(
|
102
|
+
def build_default_scope(relation = relation())
|
104
103
|
return if abstract_class?
|
105
104
|
|
106
105
|
if default_scope_override.nil?
|
@@ -111,15 +110,14 @@ module ActiveRecord
|
|
111
110
|
# The user has defined their own default scope method, so call that
|
112
111
|
evaluate_default_scope do
|
113
112
|
if scope = default_scope
|
114
|
-
|
113
|
+
relation.merge!(scope)
|
115
114
|
end
|
116
115
|
end
|
117
116
|
elsif default_scopes.any?
|
118
|
-
base_rel ||= relation
|
119
117
|
evaluate_default_scope do
|
120
|
-
default_scopes.inject(
|
118
|
+
default_scopes.inject(relation) do |default_scope, scope|
|
121
119
|
scope = scope.respond_to?(:to_proc) ? scope : scope.method(:call)
|
122
|
-
default_scope.
|
120
|
+
default_scope.instance_exec(&scope) || default_scope
|
123
121
|
end
|
124
122
|
end
|
125
123
|
end
|
@@ -1,9 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "active_support/core_ext/array"
|
4
|
-
require "active_support/core_ext/hash/except"
|
5
|
-
require "active_support/core_ext/kernel/singleton_class"
|
6
|
-
|
7
3
|
module ActiveRecord
|
8
4
|
# = Active Record \Named \Scopes
|
9
5
|
module Scoping
|
@@ -24,13 +20,13 @@ module ActiveRecord
|
|
24
20
|
# You can define a scope that applies to all finders using
|
25
21
|
# {default_scope}[rdoc-ref:Scoping::Default::ClassMethods#default_scope].
|
26
22
|
def all
|
27
|
-
|
23
|
+
scope = current_scope
|
28
24
|
|
29
|
-
if
|
30
|
-
if self ==
|
31
|
-
|
25
|
+
if scope
|
26
|
+
if self == scope.klass
|
27
|
+
scope.clone
|
32
28
|
else
|
33
|
-
relation.merge!(
|
29
|
+
relation.merge!(scope)
|
34
30
|
end
|
35
31
|
else
|
36
32
|
default_scoped
|
@@ -38,21 +34,20 @@ module ActiveRecord
|
|
38
34
|
end
|
39
35
|
|
40
36
|
def scope_for_association(scope = relation) # :nodoc:
|
41
|
-
|
42
|
-
|
43
|
-
if current_scope && current_scope.empty_scope?
|
37
|
+
if current_scope&.empty_scope?
|
44
38
|
scope
|
45
39
|
else
|
46
40
|
default_scoped(scope)
|
47
41
|
end
|
48
42
|
end
|
49
43
|
|
50
|
-
|
44
|
+
# Returns a scope for the model with default scopes.
|
45
|
+
def default_scoped(scope = relation)
|
51
46
|
build_default_scope(scope) || scope
|
52
47
|
end
|
53
48
|
|
54
49
|
def default_extensions # :nodoc:
|
55
|
-
if scope =
|
50
|
+
if scope = scope_for_association || build_default_scope
|
56
51
|
scope.extensions
|
57
52
|
else
|
58
53
|
[]
|
@@ -77,10 +72,6 @@ module ActiveRecord
|
|
77
72
|
# <tt>Shirt.dry_clean_only</tt>. <tt>Shirt.red</tt>, in effect,
|
78
73
|
# represents the query <tt>Shirt.where(color: 'red')</tt>.
|
79
74
|
#
|
80
|
-
# You should always pass a callable object to the scopes defined
|
81
|
-
# with #scope. This ensures that the scope is re-evaluated each
|
82
|
-
# time it is called.
|
83
|
-
#
|
84
75
|
# Note that this is simply 'syntactic sugar' for defining an actual
|
85
76
|
# class method:
|
86
77
|
#
|
@@ -181,25 +172,27 @@ module ActiveRecord
|
|
181
172
|
extension = Module.new(&block) if block
|
182
173
|
|
183
174
|
if body.respond_to?(:to_proc)
|
184
|
-
singleton_class.
|
185
|
-
scope = all
|
186
|
-
scope = scope._exec_scope(*args, &body)
|
175
|
+
singleton_class.define_method(name) do |*args|
|
176
|
+
scope = all._exec_scope(*args, &body)
|
187
177
|
scope = scope.extending(extension) if extension
|
188
178
|
scope
|
189
179
|
end
|
190
180
|
else
|
191
|
-
singleton_class.
|
192
|
-
scope = all
|
193
|
-
scope = scope.scoping { body.call(*args) || scope }
|
181
|
+
singleton_class.define_method(name) do |*args|
|
182
|
+
scope = body.call(*args) || all
|
194
183
|
scope = scope.extending(extension) if extension
|
195
184
|
scope
|
196
185
|
end
|
197
186
|
end
|
187
|
+
singleton_class.send(:ruby2_keywords, name) if respond_to?(:ruby2_keywords, true)
|
198
188
|
|
199
189
|
generate_relation_method(name)
|
200
190
|
end
|
201
191
|
|
202
192
|
private
|
193
|
+
def singleton_method_added(name)
|
194
|
+
generate_relation_method(name) if Kernel.respond_to?(name) && !ActiveRecord::Relation.method_defined?(name)
|
195
|
+
end
|
203
196
|
|
204
197
|
def valid_scope_name?(name)
|
205
198
|
if respond_to?(name, true) && logger
|
@@ -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:
|
@@ -95,7 +95,6 @@ module ActiveRecord
|
|
95
95
|
end
|
96
96
|
|
97
97
|
private
|
98
|
-
|
99
98
|
def raise_invalid_scope_type!(scope_type)
|
100
99
|
if !VALID_SCOPE_TYPES.include?(scope_type)
|
101
100
|
raise ArgumentError, "Invalid scope type '#{scope_type}' sent to the registry. Scope types must be included in VALID_SCOPE_TYPES"
|