activerecord 6.0.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 +843 -626
- data/MIT-LICENSE +1 -1
- data/README.rdoc +3 -3
- data/lib/active_record/aggregations.rb +1 -2
- data/lib/active_record/association_relation.rb +18 -17
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +49 -37
- data/lib/active_record/associations/association_scope.rb +17 -15
- data/lib/active_record/associations/belongs_to_association.rb +15 -5
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +1 -1
- data/lib/active_record/associations/builder/association.rb +9 -3
- data/lib/active_record/associations/builder/belongs_to.rb +10 -7
- data/lib/active_record/associations/builder/collection_association.rb +5 -4
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +0 -3
- data/lib/active_record/associations/builder/has_many.rb +6 -2
- data/lib/active_record/associations/builder/has_one.rb +11 -14
- data/lib/active_record/associations/builder/singular_association.rb +1 -1
- data/lib/active_record/associations/collection_association.rb +25 -8
- data/lib/active_record/associations/collection_proxy.rb +14 -7
- data/lib/active_record/associations/foreign_association.rb +13 -0
- data/lib/active_record/associations/has_many_association.rb +24 -3
- data/lib/active_record/associations/has_many_through_association.rb +10 -4
- data/lib/active_record/associations/has_one_association.rb +15 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +36 -14
- data/lib/active_record/associations/join_dependency/join_part.rb +3 -3
- data/lib/active_record/associations/join_dependency.rb +73 -42
- data/lib/active_record/associations/preloader/association.rb +51 -25
- data/lib/active_record/associations/preloader/through_association.rb +2 -2
- data/lib/active_record/associations/preloader.rb +12 -7
- data/lib/active_record/associations/singular_association.rb +1 -1
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/associations.rb +115 -12
- data/lib/active_record/attribute_assignment.rb +10 -9
- data/lib/active_record/attribute_methods/before_type_cast.rb +13 -10
- data/lib/active_record/attribute_methods/dirty.rb +3 -13
- data/lib/active_record/attribute_methods/primary_key.rb +6 -4
- data/lib/active_record/attribute_methods/query.rb +3 -6
- data/lib/active_record/attribute_methods/read.rb +8 -12
- data/lib/active_record/attribute_methods/serialization.rb +11 -6
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -15
- data/lib/active_record/attribute_methods/write.rb +12 -21
- data/lib/active_record/attribute_methods.rb +64 -54
- data/lib/active_record/attributes.rb +32 -8
- data/lib/active_record/autosave_association.rb +56 -41
- data/lib/active_record/base.rb +2 -14
- data/lib/active_record/callbacks.rb +153 -24
- data/lib/active_record/coders/yaml_column.rb +1 -2
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +190 -136
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -44
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +82 -37
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -8
- data/lib/active_record/connection_adapters/abstract/quoting.rb +34 -34
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +152 -116
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +137 -52
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +263 -107
- data/lib/active_record/connection_adapters/abstract/transaction.rb +82 -35
- data/lib/active_record/connection_adapters/abstract_adapter.rb +60 -73
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +136 -111
- data/lib/active_record/connection_adapters/column.rb +15 -1
- 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 +28 -36
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
- data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +32 -7
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +8 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +17 -13
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +31 -13
- 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 +24 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +19 -56
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +0 -1
- 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 +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -3
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -3
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +24 -6
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +11 -2
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +7 -3
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +72 -54
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +77 -57
- data/lib/active_record/connection_adapters/schema_cache.rb +98 -15
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +10 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +36 -12
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +1 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +38 -5
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +57 -57
- 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 +210 -87
- data/lib/active_record/core.rb +229 -65
- data/lib/active_record/counter_cache.rb +4 -1
- data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
- data/lib/active_record/database_configurations/database_config.rb +52 -9
- data/lib/active_record/database_configurations/hash_config.rb +54 -8
- data/lib/active_record/database_configurations/url_config.rb +15 -41
- data/lib/active_record/database_configurations.rb +124 -85
- 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 +2 -3
- data/lib/active_record/enum.rb +40 -16
- data/lib/active_record/errors.rb +47 -12
- data/lib/active_record/explain.rb +9 -5
- 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 +1 -2
- data/lib/active_record/fixture_set/render_context.rb +1 -1
- data/lib/active_record/fixture_set/table_row.rb +2 -3
- data/lib/active_record/fixture_set/table_rows.rb +0 -1
- data/lib/active_record/fixtures.rb +54 -11
- data/lib/active_record/gem_version.rb +2 -2
- data/lib/active_record/inheritance.rb +40 -21
- data/lib/active_record/insert_all.rb +38 -9
- data/lib/active_record/integration.rb +3 -5
- data/lib/active_record/internal_metadata.rb +16 -7
- data/lib/active_record/legacy_yaml_adapter.rb +7 -3
- data/lib/active_record/locking/optimistic.rb +22 -17
- data/lib/active_record/locking/pessimistic.rb +6 -2
- data/lib/active_record/log_subscriber.rb +27 -9
- data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +6 -2
- data/lib/active_record/middleware/database_selector.rb +4 -2
- data/lib/active_record/migration/command_recorder.rb +53 -45
- data/lib/active_record/migration/compatibility.rb +70 -20
- data/lib/active_record/migration/join_table.rb +0 -1
- data/lib/active_record/migration.rb +114 -84
- data/lib/active_record/model_schema.rb +117 -15
- data/lib/active_record/nested_attributes.rb +2 -5
- data/lib/active_record/no_touching.rb +1 -1
- data/lib/active_record/null_relation.rb +0 -1
- data/lib/active_record/persistence.rb +50 -46
- data/lib/active_record/query_cache.rb +15 -5
- data/lib/active_record/querying.rb +12 -7
- data/lib/active_record/railtie.rb +65 -45
- data/lib/active_record/railties/databases.rake +267 -93
- data/lib/active_record/readonly_attributes.rb +4 -0
- data/lib/active_record/reflection.rb +77 -63
- data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
- data/lib/active_record/relation/batches.rb +38 -32
- data/lib/active_record/relation/calculations.rb +102 -45
- data/lib/active_record/relation/delegation.rb +9 -7
- data/lib/active_record/relation/finder_methods.rb +45 -16
- data/lib/active_record/relation/from_clause.rb +5 -1
- data/lib/active_record/relation/merger.rb +27 -26
- data/lib/active_record/relation/predicate_builder/array_handler.rb +8 -9
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +4 -5
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +3 -3
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/predicate_builder.rb +55 -35
- data/lib/active_record/relation/query_methods.rb +335 -187
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +8 -8
- data/lib/active_record/relation/where_clause.rb +104 -58
- data/lib/active_record/relation.rb +108 -68
- data/lib/active_record/result.rb +41 -34
- data/lib/active_record/runtime_registry.rb +2 -2
- data/lib/active_record/sanitization.rb +6 -17
- data/lib/active_record/schema_dumper.rb +34 -4
- data/lib/active_record/schema_migration.rb +2 -8
- data/lib/active_record/scoping/default.rb +0 -1
- data/lib/active_record/scoping/named.rb +7 -18
- data/lib/active_record/scoping.rb +0 -1
- 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 +20 -4
- data/lib/active_record/store.rb +3 -3
- data/lib/active_record/suppressor.rb +2 -2
- data/lib/active_record/table_metadata.rb +39 -36
- data/lib/active_record/tasks/database_tasks.rb +139 -113
- data/lib/active_record/tasks/mysql_database_tasks.rb +34 -36
- data/lib/active_record/tasks/postgresql_database_tasks.rb +24 -27
- data/lib/active_record/tasks/sqlite_database_tasks.rb +13 -10
- data/lib/active_record/test_databases.rb +5 -4
- data/lib/active_record/test_fixtures.rb +38 -16
- data/lib/active_record/timestamp.rb +4 -7
- data/lib/active_record/touch_later.rb +20 -21
- data/lib/active_record/transactions.rb +21 -70
- data/lib/active_record/type/adapter_specific_registry.rb +2 -5
- 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 +8 -2
- data/lib/active_record/type_caster/connection.rb +0 -1
- data/lib/active_record/type_caster/map.rb +8 -5
- 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 +24 -4
- data/lib/active_record/validations.rb +3 -3
- data/lib/active_record.rb +7 -13
- data/lib/arel/attributes/attribute.rb +4 -0
- data/lib/arel/collectors/bind.rb +5 -0
- data/lib/arel/collectors/composite.rb +8 -0
- data/lib/arel/collectors/sql_string.rb +7 -0
- data/lib/arel/collectors/substitute_binds.rb +7 -0
- data/lib/arel/nodes/binary.rb +82 -8
- data/lib/arel/nodes/bind_param.rb +8 -0
- data/lib/arel/nodes/casted.rb +21 -9
- data/lib/arel/nodes/equality.rb +6 -9
- data/lib/arel/nodes/grouping.rb +3 -0
- data/lib/arel/nodes/homogeneous_in.rb +72 -0
- data/lib/arel/nodes/in.rb +8 -1
- data/lib/arel/nodes/infix_operation.rb +13 -1
- data/lib/arel/nodes/join_source.rb +1 -1
- data/lib/arel/nodes/node.rb +7 -6
- data/lib/arel/nodes/ordering.rb +27 -0
- data/lib/arel/nodes/sql_literal.rb +3 -0
- data/lib/arel/nodes/table_alias.rb +7 -3
- data/lib/arel/nodes/unary.rb +0 -1
- data/lib/arel/nodes.rb +3 -1
- data/lib/arel/predications.rb +17 -24
- data/lib/arel/select_manager.rb +1 -2
- data/lib/arel/table.rb +13 -5
- data/lib/arel/visitors/dot.rb +14 -3
- data/lib/arel/visitors/mysql.rb +11 -1
- data/lib/arel/visitors/postgresql.rb +15 -5
- data/lib/arel/visitors/sqlite.rb +0 -1
- data/lib/arel/visitors/to_sql.rb +89 -79
- data/lib/arel/visitors/visitor.rb +0 -1
- data/lib/arel/visitors.rb +0 -7
- data/lib/arel.rb +5 -9
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +2 -0
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -4
- data/lib/rails/generators/active_record/migration.rb +6 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +38 -2
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- metadata +26 -26
- data/lib/active_record/attribute_decorators.rb +0 -90
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -297
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
- data/lib/active_record/define_callbacks.rb +0 -22
- data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
- data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
- data/lib/active_record/relation/where_clause_factory.rb +0 -33
- data/lib/arel/attributes.rb +0 -22
- data/lib/arel/visitors/depth_first.rb +0 -204
- data/lib/arel/visitors/ibm_db.rb +0 -34
- data/lib/arel/visitors/informix.rb +0 -62
- data/lib/arel/visitors/mssql.rb +0 -157
- data/lib/arel/visitors/oracle.rb +0 -159
- data/lib/arel/visitors/oracle12.rb +0 -66
- data/lib/arel/visitors/where_sql.rb +0 -23
@@ -7,7 +7,7 @@ module ActiveRecord
|
|
7
7
|
:order, :joins, :left_outer_joins, :references,
|
8
8
|
:extending, :unscope, :optimizer_hints, :annotate]
|
9
9
|
|
10
|
-
SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :reordering,
|
10
|
+
SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :reordering, :strict_loading,
|
11
11
|
:reverse_order, :distinct, :create_with, :skip_query_cache]
|
12
12
|
|
13
13
|
CLAUSE_METHODS = [:where, :having, :from]
|
@@ -28,7 +28,6 @@ module ActiveRecord
|
|
28
28
|
@klass = klass
|
29
29
|
@table = table
|
30
30
|
@values = values
|
31
|
-
@offsets = {}
|
32
31
|
@loaded = false
|
33
32
|
@predicate_builder = predicate_builder
|
34
33
|
@delegate_to_klass = false
|
@@ -40,8 +39,9 @@ module ActiveRecord
|
|
40
39
|
end
|
41
40
|
|
42
41
|
def arel_attribute(name) # :nodoc:
|
43
|
-
|
42
|
+
table[name]
|
44
43
|
end
|
44
|
+
deprecate :arel_attribute
|
45
45
|
|
46
46
|
def bind_attribute(name, value) # :nodoc:
|
47
47
|
if reflection = klass._reflect_on_association(name)
|
@@ -49,7 +49,7 @@ module ActiveRecord
|
|
49
49
|
value = value.read_attribute(reflection.klass.primary_key) unless value.nil?
|
50
50
|
end
|
51
51
|
|
52
|
-
attr =
|
52
|
+
attr = table[name]
|
53
53
|
bind = predicate_builder.build_bind_attribute(attr.name, value)
|
54
54
|
yield attr, bind
|
55
55
|
end
|
@@ -67,10 +67,9 @@ module ActiveRecord
|
|
67
67
|
# user = users.new { |user| user.name = 'Oscar' }
|
68
68
|
# user.name # => Oscar
|
69
69
|
def new(attributes = nil, &block)
|
70
|
-
block =
|
71
|
-
scoping {
|
70
|
+
block = current_scope_restoring_block(&block)
|
71
|
+
scoping { _new(attributes, &block) }
|
72
72
|
end
|
73
|
-
|
74
73
|
alias build new
|
75
74
|
|
76
75
|
# Tries to create a new record with the same scoped attributes
|
@@ -96,8 +95,8 @@ module ActiveRecord
|
|
96
95
|
if attributes.is_a?(Array)
|
97
96
|
attributes.collect { |attr| create(attr, &block) }
|
98
97
|
else
|
99
|
-
block =
|
100
|
-
scoping {
|
98
|
+
block = current_scope_restoring_block(&block)
|
99
|
+
scoping { _create(attributes, &block) }
|
101
100
|
end
|
102
101
|
end
|
103
102
|
|
@@ -111,8 +110,8 @@ module ActiveRecord
|
|
111
110
|
if attributes.is_a?(Array)
|
112
111
|
attributes.collect { |attr| create!(attr, &block) }
|
113
112
|
else
|
114
|
-
block =
|
115
|
-
scoping {
|
113
|
+
block = current_scope_restoring_block(&block)
|
114
|
+
scoping { _create!(attributes, &block) }
|
116
115
|
end
|
117
116
|
end
|
118
117
|
|
@@ -308,7 +307,7 @@ module ActiveRecord
|
|
308
307
|
# last updated record.
|
309
308
|
#
|
310
309
|
# Product.where("name like ?", "%Game%").cache_key(:last_reviewed_at)
|
311
|
-
def cache_key(timestamp_column =
|
310
|
+
def cache_key(timestamp_column = "updated_at")
|
312
311
|
@cache_keys ||= {}
|
313
312
|
@cache_keys[timestamp_column] ||= klass.collection_cache_key(self, timestamp_column)
|
314
313
|
end
|
@@ -317,7 +316,7 @@ module ActiveRecord
|
|
317
316
|
query_signature = ActiveSupport::Digest.hexdigest(to_sql)
|
318
317
|
key = "#{klass.model_name.cache_key}/query-#{query_signature}"
|
319
318
|
|
320
|
-
if
|
319
|
+
if collection_cache_versioning
|
321
320
|
key
|
322
321
|
else
|
323
322
|
"#{key}-#{compute_cache_version(timestamp_column)}"
|
@@ -343,15 +342,17 @@ module ActiveRecord
|
|
343
342
|
end
|
344
343
|
|
345
344
|
def compute_cache_version(timestamp_column) # :nodoc:
|
345
|
+
timestamp_column = timestamp_column.to_s
|
346
|
+
|
346
347
|
if loaded? || distinct_value
|
347
348
|
size = records.size
|
348
349
|
if size > 0
|
349
|
-
timestamp =
|
350
|
+
timestamp = records.map { |record| record.read_attribute(timestamp_column) }.max
|
350
351
|
end
|
351
352
|
else
|
352
353
|
collection = eager_loading? ? apply_join_dependency : self
|
353
354
|
|
354
|
-
column = connection.visitor.compile(
|
355
|
+
column = connection.visitor.compile(table[timestamp_column])
|
355
356
|
select_values = "COUNT(*) AS #{connection.quote_column_name("size")}, MAX(%s) AS timestamp"
|
356
357
|
|
357
358
|
if collection.has_limit_or_offset?
|
@@ -365,14 +366,12 @@ module ActiveRecord
|
|
365
366
|
arel = query.arel
|
366
367
|
end
|
367
368
|
|
368
|
-
|
369
|
+
size, timestamp = connection.select_rows(arel, nil).first
|
369
370
|
|
370
|
-
if
|
371
|
+
if size
|
371
372
|
column_type = klass.type_for_attribute(timestamp_column)
|
372
|
-
timestamp = column_type.deserialize(
|
373
|
-
size = result["size"]
|
373
|
+
timestamp = column_type.deserialize(timestamp)
|
374
374
|
else
|
375
|
-
timestamp = nil
|
376
375
|
size = 0
|
377
376
|
end
|
378
377
|
end
|
@@ -385,6 +384,15 @@ module ActiveRecord
|
|
385
384
|
end
|
386
385
|
private :compute_cache_version
|
387
386
|
|
387
|
+
# Returns a cache key along with the version.
|
388
|
+
def cache_key_with_version
|
389
|
+
if version = cache_version
|
390
|
+
"#{cache_key}-#{version}"
|
391
|
+
else
|
392
|
+
cache_key
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
388
396
|
# Scope all queries to the current scope.
|
389
397
|
#
|
390
398
|
# Comment.where(post_id: 1).scoping do
|
@@ -398,9 +406,9 @@ module ActiveRecord
|
|
398
406
|
already_in_scope? ? yield : _scoping(self) { yield }
|
399
407
|
end
|
400
408
|
|
401
|
-
def _exec_scope(
|
409
|
+
def _exec_scope(*args, &block) # :nodoc:
|
402
410
|
@delegate_to_klass = true
|
403
|
-
_scoping(
|
411
|
+
_scoping(nil) { instance_exec(*args, &block) || self }
|
404
412
|
ensure
|
405
413
|
@delegate_to_klass = false
|
406
414
|
end
|
@@ -408,7 +416,7 @@ module ActiveRecord
|
|
408
416
|
# Updates all records in the current relation with details given. This method constructs a single SQL UPDATE
|
409
417
|
# statement and sends it straight to the database. It does not instantiate the involved models and it does not
|
410
418
|
# trigger Active Record callbacks or validations. However, values passed to #update_all will still go through
|
411
|
-
# Active Record's normal type casting and serialization.
|
419
|
+
# Active Record's normal type casting and serialization. Returns the number of rows affected.
|
412
420
|
#
|
413
421
|
# Note: As Active Record callbacks are not triggered, this method will not automatically update +updated_at+/+updated_on+ columns.
|
414
422
|
#
|
@@ -439,7 +447,7 @@ module ActiveRecord
|
|
439
447
|
|
440
448
|
stmt = Arel::UpdateManager.new
|
441
449
|
stmt.table(arel.join_sources.empty? ? table : arel.source)
|
442
|
-
stmt.key =
|
450
|
+
stmt.key = table[primary_key]
|
443
451
|
stmt.take(arel.limit)
|
444
452
|
stmt.offset(arel.offset)
|
445
453
|
stmt.order(*arel.orders)
|
@@ -449,7 +457,7 @@ module ActiveRecord
|
|
449
457
|
if klass.locking_enabled? &&
|
450
458
|
!updates.key?(klass.locking_column) &&
|
451
459
|
!updates.key?(klass.locking_column.to_sym)
|
452
|
-
attr =
|
460
|
+
attr = table[klass.locking_column]
|
453
461
|
updates[attr.name] = _increment_attribute(attr)
|
454
462
|
end
|
455
463
|
stmt.set _substitute_values(updates)
|
@@ -468,26 +476,40 @@ module ActiveRecord
|
|
468
476
|
end
|
469
477
|
end
|
470
478
|
|
471
|
-
|
479
|
+
# Updates the counters of the records in the current relation.
|
480
|
+
#
|
481
|
+
# ==== Parameters
|
482
|
+
#
|
483
|
+
# * +counter+ - A Hash containing the names of the fields to update as keys and the amount to update as values.
|
484
|
+
# * <tt>:touch</tt> option - Touch the timestamp columns when updating.
|
485
|
+
# * If attributes names are passed, they are updated along with update_at/on attributes.
|
486
|
+
#
|
487
|
+
# ==== Examples
|
488
|
+
#
|
489
|
+
# # For Posts by a given author increment the comment_count by 1.
|
490
|
+
# Post.where(author_id: author.id).update_counters(comment_count: 1)
|
491
|
+
def update_counters(counters)
|
472
492
|
touch = counters.delete(:touch)
|
473
493
|
|
474
494
|
updates = {}
|
475
495
|
counters.each do |counter_name, value|
|
476
|
-
attr =
|
496
|
+
attr = table[counter_name]
|
477
497
|
updates[attr.name] = _increment_attribute(attr, value)
|
478
498
|
end
|
479
499
|
|
480
500
|
if touch
|
481
501
|
names = touch if touch != true
|
482
|
-
|
502
|
+
names = Array.wrap(names)
|
503
|
+
options = names.extract_options!
|
504
|
+
touch_updates = klass.touch_attributes_with_time(*names, **options)
|
483
505
|
updates.merge!(touch_updates) unless touch_updates.empty?
|
484
506
|
end
|
485
507
|
|
486
508
|
update_all updates
|
487
509
|
end
|
488
510
|
|
489
|
-
# Touches all records in the current relation
|
490
|
-
#
|
511
|
+
# Touches all records in the current relation, setting the +updated_at+/+updated_on+ attributes to the current time or the time specified.
|
512
|
+
# It does not instantiate the involved models, and it does not trigger Active Record callbacks or validations.
|
491
513
|
# This method can be passed attribute names and an optional time argument.
|
492
514
|
# If attribute names are passed, they are updated along with +updated_at+/+updated_on+ attributes.
|
493
515
|
# If no time argument is passed, the current time is used as default.
|
@@ -567,7 +589,7 @@ module ActiveRecord
|
|
567
589
|
|
568
590
|
stmt = Arel::DeleteManager.new
|
569
591
|
stmt.from(arel.join_sources.empty? ? table : arel.source)
|
570
|
-
stmt.key =
|
592
|
+
stmt.key = table[primary_key]
|
571
593
|
stmt.take(arel.limit)
|
572
594
|
stmt.offset(arel.offset)
|
573
595
|
stmt.order(*arel.orders)
|
@@ -612,7 +634,10 @@ module ActiveRecord
|
|
612
634
|
#
|
613
635
|
# Post.where(published: true).load # => #<ActiveRecord::Relation>
|
614
636
|
def load(&block)
|
615
|
-
|
637
|
+
unless loaded?
|
638
|
+
@records = exec_queries(&block)
|
639
|
+
@loaded = true
|
640
|
+
end
|
616
641
|
|
617
642
|
self
|
618
643
|
end
|
@@ -625,11 +650,9 @@ module ActiveRecord
|
|
625
650
|
|
626
651
|
def reset
|
627
652
|
@delegate_to_klass = false
|
628
|
-
@_deprecated_scope_source = nil
|
629
653
|
@to_sql = @arel = @loaded = @should_eager_load = nil
|
654
|
+
@offsets = @take = nil
|
630
655
|
@records = [].freeze
|
631
|
-
@offsets = {}
|
632
|
-
@take = nil
|
633
656
|
self
|
634
657
|
end
|
635
658
|
|
@@ -660,7 +683,10 @@ module ActiveRecord
|
|
660
683
|
end
|
661
684
|
|
662
685
|
def scope_for_create
|
663
|
-
where_values_hash
|
686
|
+
hash = where_values_hash
|
687
|
+
hash.delete(klass.inheritance_column) if klass.finder_needs_type_condition?
|
688
|
+
create_with_value.each { |k, v| hash[k.to_s] = v } unless create_with_value.empty?
|
689
|
+
hash
|
664
690
|
end
|
665
691
|
|
666
692
|
# Returns true if relation needs eager loading.
|
@@ -704,7 +730,7 @@ module ActiveRecord
|
|
704
730
|
end
|
705
731
|
|
706
732
|
def inspect
|
707
|
-
subject = loaded? ? records :
|
733
|
+
subject = loaded? ? records : annotate("loading for inspect")
|
708
734
|
entries = subject.take([limit_value, 11].compact.min).map!(&:inspect)
|
709
735
|
|
710
736
|
entries[10] = "..." if entries.size == 11
|
@@ -721,25 +747,31 @@ module ActiveRecord
|
|
721
747
|
end
|
722
748
|
|
723
749
|
def alias_tracker(joins = [], aliases = nil) # :nodoc:
|
724
|
-
|
725
|
-
|
750
|
+
ActiveRecord::Associations::AliasTracker.create(connection, table.name, joins, aliases)
|
751
|
+
end
|
752
|
+
|
753
|
+
class StrictLoadingScope # :nodoc:
|
754
|
+
def self.empty_scope?
|
755
|
+
true
|
756
|
+
end
|
757
|
+
|
758
|
+
def self.strict_loading_value
|
759
|
+
true
|
760
|
+
end
|
726
761
|
end
|
727
762
|
|
728
763
|
def preload_associations(records) # :nodoc:
|
729
764
|
preload = preload_values
|
730
765
|
preload += includes_values unless eager_loading?
|
731
766
|
preloader = nil
|
767
|
+
scope = strict_loading_value ? StrictLoadingScope : nil
|
732
768
|
preload.each do |associations|
|
733
769
|
preloader ||= build_preloader
|
734
|
-
preloader.preload records, associations
|
770
|
+
preloader.preload records, associations, scope
|
735
771
|
end
|
736
772
|
end
|
737
773
|
|
738
|
-
attr_reader :_deprecated_scope_source # :nodoc:
|
739
|
-
|
740
774
|
protected
|
741
|
-
attr_writer :_deprecated_scope_source # :nodoc:
|
742
|
-
|
743
775
|
def load_records(records)
|
744
776
|
@records = records.freeze
|
745
777
|
@loaded = true
|
@@ -751,23 +783,29 @@ module ActiveRecord
|
|
751
783
|
|
752
784
|
private
|
753
785
|
def already_in_scope?
|
754
|
-
@delegate_to_klass &&
|
755
|
-
scope = klass.current_scope(true)
|
756
|
-
scope && !scope._deprecated_scope_source
|
757
|
-
end
|
786
|
+
@delegate_to_klass && klass.current_scope(true)
|
758
787
|
end
|
759
788
|
|
760
|
-
def
|
761
|
-
|
762
|
-
end
|
763
|
-
|
764
|
-
def _deprecated_scope_block(name, &block)
|
789
|
+
def current_scope_restoring_block(&block)
|
790
|
+
current_scope = klass.current_scope(true)
|
765
791
|
-> record do
|
766
|
-
klass.current_scope =
|
792
|
+
klass.current_scope = current_scope
|
767
793
|
yield record if block_given?
|
768
794
|
end
|
769
795
|
end
|
770
796
|
|
797
|
+
def _new(attributes, &block)
|
798
|
+
klass.new(attributes, &block)
|
799
|
+
end
|
800
|
+
|
801
|
+
def _create(attributes, &block)
|
802
|
+
klass.create(attributes, &block)
|
803
|
+
end
|
804
|
+
|
805
|
+
def _create!(attributes, &block)
|
806
|
+
klass.create!(attributes, &block)
|
807
|
+
end
|
808
|
+
|
771
809
|
def _scoping(scope)
|
772
810
|
previous, klass.current_scope = klass.current_scope(true), scope
|
773
811
|
yield
|
@@ -777,7 +815,7 @@ module ActiveRecord
|
|
777
815
|
|
778
816
|
def _substitute_values(values)
|
779
817
|
values.map do |name, value|
|
780
|
-
attr =
|
818
|
+
attr = table[name]
|
781
819
|
unless Arel.arel_node?(value)
|
782
820
|
type = klass.type_for_attribute(attr.name)
|
783
821
|
value = predicate_builder.build_bind_attribute(attr.name, type.cast(value))
|
@@ -795,27 +833,29 @@ module ActiveRecord
|
|
795
833
|
|
796
834
|
def exec_queries(&block)
|
797
835
|
skip_query_cache_if_necessary do
|
798
|
-
|
799
|
-
if
|
836
|
+
records =
|
837
|
+
if where_clause.contradiction?
|
838
|
+
[]
|
839
|
+
elsif eager_loading?
|
800
840
|
apply_join_dependency do |relation, join_dependency|
|
801
841
|
if relation.null_relation?
|
802
842
|
[]
|
803
843
|
else
|
804
844
|
relation = join_dependency.apply_column_aliases(relation)
|
805
845
|
rows = connection.select_all(relation.arel, "SQL")
|
806
|
-
join_dependency.instantiate(rows, &block)
|
846
|
+
join_dependency.instantiate(rows, strict_loading_value, &block)
|
807
847
|
end.freeze
|
808
848
|
end
|
809
849
|
else
|
810
850
|
klass.find_by_sql(arel, &block).freeze
|
811
851
|
end
|
812
852
|
|
813
|
-
preload_associations(
|
853
|
+
preload_associations(records) unless skip_preloading_value
|
814
854
|
|
815
|
-
|
855
|
+
records.each(&:readonly!) if readonly_value
|
856
|
+
records.each(&:strict_loading!) if strict_loading_value
|
816
857
|
|
817
|
-
|
818
|
-
@records
|
858
|
+
records
|
819
859
|
end
|
820
860
|
end
|
821
861
|
|
@@ -834,27 +874,27 @@ module ActiveRecord
|
|
834
874
|
end
|
835
875
|
|
836
876
|
def references_eager_loaded_tables?
|
837
|
-
joined_tables =
|
877
|
+
joined_tables = build_joins([]).flat_map do |join|
|
838
878
|
if join.is_a?(Arel::Nodes::StringJoin)
|
839
879
|
tables_in_string(join.left)
|
840
880
|
else
|
841
|
-
|
881
|
+
join.left.name
|
842
882
|
end
|
843
883
|
end
|
844
884
|
|
845
|
-
joined_tables
|
885
|
+
joined_tables << table.name
|
846
886
|
|
847
887
|
# always convert table names to downcase as in Oracle quoted table names are in uppercase
|
848
|
-
joined_tables
|
888
|
+
joined_tables.map!(&:downcase)
|
849
889
|
|
850
|
-
(references_values - joined_tables).
|
890
|
+
!(references_values.map(&:to_s) - joined_tables).empty?
|
851
891
|
end
|
852
892
|
|
853
893
|
def tables_in_string(string)
|
854
894
|
return [] if string.blank?
|
855
895
|
# always convert table names to downcase as in Oracle quoted table names are in uppercase
|
856
896
|
# ignore raw_sql_ that is used by Oracle adapter as alias for limit/offset subqueries
|
857
|
-
string.scan(/
|
897
|
+
string.scan(/[a-zA-Z_][.\w]+(?=.?\.)/).map!(&:downcase) - ["raw_sql_"]
|
858
898
|
end
|
859
899
|
end
|
860
900
|
end
|
data/lib/active_record/result.rb
CHANGED
@@ -65,16 +65,10 @@ module ActiveRecord
|
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
68
|
-
def to_hash
|
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
|
74
|
-
end
|
75
|
-
|
76
68
|
alias :map! :map
|
77
69
|
alias :collect! :map
|
70
|
+
deprecate "map!": :map
|
71
|
+
deprecate "collect!": :map
|
78
72
|
|
79
73
|
# Returns true if there are no records, otherwise false.
|
80
74
|
def empty?
|
@@ -92,31 +86,30 @@ module ActiveRecord
|
|
92
86
|
hash_rows[idx]
|
93
87
|
end
|
94
88
|
|
95
|
-
# Returns the first record from the rows collection.
|
96
|
-
# If the rows collection is empty, returns +nil+.
|
97
|
-
def first
|
98
|
-
return nil if @rows.empty?
|
99
|
-
Hash[@columns.zip(@rows.first)]
|
100
|
-
end
|
101
|
-
|
102
89
|
# Returns the last record from the rows collection.
|
103
|
-
|
104
|
-
|
105
|
-
return nil if @rows.empty?
|
106
|
-
Hash[@columns.zip(@rows.last)]
|
90
|
+
def last(n = nil)
|
91
|
+
n ? hash_rows.last(n) : hash_rows.last
|
107
92
|
end
|
108
93
|
|
109
94
|
def cast_values(type_overrides = {}) # :nodoc:
|
110
95
|
if columns.one?
|
111
96
|
# Separated to avoid allocating an array per row
|
112
97
|
|
113
|
-
type =
|
98
|
+
type = if type_overrides.is_a?(Array)
|
99
|
+
type_overrides.first
|
100
|
+
else
|
101
|
+
column_type(columns.first, type_overrides)
|
102
|
+
end
|
114
103
|
|
115
104
|
rows.map do |(value)|
|
116
105
|
type.deserialize(value)
|
117
106
|
end
|
118
107
|
else
|
119
|
-
types =
|
108
|
+
types = if type_overrides.is_a?(Array)
|
109
|
+
type_overrides
|
110
|
+
else
|
111
|
+
columns.map { |name| column_type(name, type_overrides) }
|
112
|
+
end
|
120
113
|
|
121
114
|
rows.map do |values|
|
122
115
|
Array.new(values.size) { |i| types[i].deserialize(values[i]) }
|
@@ -132,7 +125,6 @@ module ActiveRecord
|
|
132
125
|
end
|
133
126
|
|
134
127
|
private
|
135
|
-
|
136
128
|
def column_type(name, type_overrides = {})
|
137
129
|
type_overrides.fetch(name) do
|
138
130
|
column_types.fetch(name, Type.default_value)
|
@@ -146,21 +138,36 @@ module ActiveRecord
|
|
146
138
|
# used as keys in ActiveRecord::Base's @attributes hash
|
147
139
|
columns = @columns.map(&:-@)
|
148
140
|
length = columns.length
|
141
|
+
template = nil
|
149
142
|
|
150
143
|
@rows.map { |row|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
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
|
161
170
|
end
|
162
|
-
|
163
|
-
hash
|
164
171
|
}
|
165
172
|
end
|
166
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
|
@@ -67,7 +67,7 @@ module ActiveRecord
|
|
67
67
|
)
|
68
68
|
|
69
69
|
# Ensure we aren't dealing with a subclass of String that might
|
70
|
-
# override methods we use (
|
70
|
+
# override methods we use (e.g. Arel::Nodes::SqlLiteral).
|
71
71
|
if condition.first.kind_of?(String) && !condition.first.instance_of?(String)
|
72
72
|
condition = [String.new(condition.first), *condition[1..-1]]
|
73
73
|
end
|
@@ -141,19 +141,7 @@ module ActiveRecord
|
|
141
141
|
(unexpected ||= []) << arg
|
142
142
|
end
|
143
143
|
|
144
|
-
|
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
|
144
|
+
if unexpected
|
157
145
|
raise(ActiveRecord::UnknownAttributeReference,
|
158
146
|
"Query method called with non-attribute argument(s): " +
|
159
147
|
unexpected.map(&:inspect).join(", ")
|
@@ -193,13 +181,14 @@ module ActiveRecord
|
|
193
181
|
|
194
182
|
def quote_bound_value(value, c = connection)
|
195
183
|
if value.respond_to?(:map) && !value.acts_like?(:string)
|
196
|
-
|
197
|
-
if
|
184
|
+
values = value.map { |v| v.respond_to?(:id_for_database) ? v.id_for_database : v }
|
185
|
+
if values.empty?
|
198
186
|
c.quote(nil)
|
199
187
|
else
|
200
|
-
|
188
|
+
values.map! { |v| c.quote(v) }.join(",")
|
201
189
|
end
|
202
190
|
else
|
191
|
+
value = value.id_for_database if value.respond_to?(:id_for_database)
|
203
192
|
c.quote(value)
|
204
193
|
end
|
205
194
|
end
|