activerecord 5.2.7 → 6.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +299 -778
- data/MIT-LICENSE +3 -1
- data/README.rdoc +1 -1
- data/examples/performance.rb +1 -1
- data/lib/active_record/aggregations.rb +4 -2
- data/lib/active_record/associations/association.rb +35 -19
- data/lib/active_record/associations/association_scope.rb +4 -6
- data/lib/active_record/associations/belongs_to_association.rb +36 -42
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +0 -4
- data/lib/active_record/associations/builder/belongs_to.rb +14 -50
- data/lib/active_record/associations/builder/collection_association.rb +3 -3
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -38
- data/lib/active_record/associations/collection_association.rb +11 -25
- data/lib/active_record/associations/collection_proxy.rb +32 -6
- data/lib/active_record/associations/foreign_association.rb +7 -0
- data/lib/active_record/associations/has_many_association.rb +1 -1
- data/lib/active_record/associations/has_many_through_association.rb +25 -18
- data/lib/active_record/associations/has_one_association.rb +28 -30
- data/lib/active_record/associations/has_one_through_association.rb +5 -5
- data/lib/active_record/associations/join_dependency/join_association.rb +11 -26
- data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
- data/lib/active_record/associations/join_dependency.rb +15 -20
- data/lib/active_record/associations/preloader/association.rb +1 -2
- data/lib/active_record/associations/preloader.rb +32 -29
- data/lib/active_record/associations/singular_association.rb +2 -16
- data/lib/active_record/associations.rb +16 -12
- data/lib/active_record/attribute_assignment.rb +7 -10
- data/lib/active_record/attribute_methods/dirty.rb +64 -26
- data/lib/active_record/attribute_methods/primary_key.rb +8 -7
- data/lib/active_record/attribute_methods/read.rb +16 -48
- data/lib/active_record/attribute_methods/serialization.rb +1 -1
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +1 -1
- data/lib/active_record/attribute_methods/write.rb +15 -16
- data/lib/active_record/attribute_methods.rb +34 -56
- data/lib/active_record/autosave_association.rb +7 -21
- data/lib/active_record/base.rb +2 -2
- data/lib/active_record/callbacks.rb +3 -17
- data/lib/active_record/collection_cache_key.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +13 -36
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +25 -84
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +17 -14
- data/lib/active_record/connection_adapters/abstract/quoting.rb +5 -11
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +15 -11
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +30 -13
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +0 -2
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +41 -27
- data/lib/active_record/connection_adapters/abstract/transaction.rb +81 -52
- data/lib/active_record/connection_adapters/abstract_adapter.rb +95 -31
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +65 -90
- data/lib/active_record/connection_adapters/connection_specification.rb +52 -42
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +5 -9
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +29 -7
- data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +3 -4
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +65 -10
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -4
- data/lib/active_record/connection_adapters/postgresql/column.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +16 -1
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +11 -36
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +9 -2
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +38 -20
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +75 -56
- data/lib/active_record/connection_adapters/schema_cache.rb +5 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +5 -5
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +14 -9
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +95 -62
- data/lib/active_record/connection_handling.rb +132 -26
- data/lib/active_record/core.rb +76 -43
- data/lib/active_record/counter_cache.rb +4 -29
- data/lib/active_record/database_configurations/database_config.rb +37 -0
- data/lib/active_record/database_configurations/hash_config.rb +50 -0
- data/lib/active_record/database_configurations/url_config.rb +74 -0
- data/lib/active_record/database_configurations.rb +184 -0
- data/lib/active_record/enum.rb +22 -7
- data/lib/active_record/errors.rb +24 -21
- data/lib/active_record/explain.rb +1 -1
- data/lib/active_record/fixture_set/model_metadata.rb +33 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +153 -0
- data/lib/active_record/fixture_set/table_rows.rb +47 -0
- data/lib/active_record/fixtures.rb +140 -472
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +12 -2
- data/lib/active_record/integration.rb +56 -16
- data/lib/active_record/internal_metadata.rb +5 -1
- data/lib/active_record/locking/optimistic.rb +2 -2
- data/lib/active_record/locking/pessimistic.rb +3 -3
- data/lib/active_record/log_subscriber.rb +7 -26
- data/lib/active_record/migration/command_recorder.rb +35 -5
- data/lib/active_record/migration/compatibility.rb +34 -16
- data/lib/active_record/migration.rb +38 -37
- data/lib/active_record/model_schema.rb +30 -9
- data/lib/active_record/nested_attributes.rb +2 -2
- data/lib/active_record/no_touching.rb +7 -0
- data/lib/active_record/persistence.rb +18 -7
- data/lib/active_record/query_cache.rb +11 -4
- data/lib/active_record/querying.rb +19 -11
- data/lib/active_record/railtie.rb +71 -42
- data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
- data/lib/active_record/railties/controller_runtime.rb +30 -35
- data/lib/active_record/railties/databases.rake +94 -43
- data/lib/active_record/reflection.rb +60 -44
- data/lib/active_record/relation/batches.rb +13 -10
- data/lib/active_record/relation/calculations.rb +38 -28
- data/lib/active_record/relation/delegation.rb +4 -13
- data/lib/active_record/relation/finder_methods.rb +12 -25
- data/lib/active_record/relation/merger.rb +2 -6
- data/lib/active_record/relation/predicate_builder/array_handler.rb +5 -4
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +1 -4
- data/lib/active_record/relation/predicate_builder/base_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -4
- data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
- data/lib/active_record/relation/predicate_builder.rb +4 -6
- data/lib/active_record/relation/query_attribute.rb +15 -12
- data/lib/active_record/relation/query_methods.rb +29 -52
- data/lib/active_record/relation/where_clause.rb +4 -0
- data/lib/active_record/relation/where_clause_factory.rb +1 -2
- data/lib/active_record/relation.rb +150 -69
- data/lib/active_record/result.rb +30 -11
- data/lib/active_record/sanitization.rb +2 -39
- data/lib/active_record/schema.rb +1 -10
- data/lib/active_record/schema_dumper.rb +12 -6
- data/lib/active_record/schema_migration.rb +4 -0
- data/lib/active_record/scoping/default.rb +10 -3
- data/lib/active_record/scoping/named.rb +10 -14
- data/lib/active_record/scoping.rb +9 -8
- data/lib/active_record/statement_cache.rb +32 -5
- data/lib/active_record/store.rb +39 -8
- data/lib/active_record/table_metadata.rb +1 -4
- data/lib/active_record/tasks/database_tasks.rb +89 -23
- data/lib/active_record/tasks/mysql_database_tasks.rb +2 -4
- data/lib/active_record/tasks/postgresql_database_tasks.rb +5 -7
- data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -8
- data/lib/active_record/test_databases.rb +38 -0
- data/lib/active_record/test_fixtures.rb +224 -0
- data/lib/active_record/timestamp.rb +4 -6
- data/lib/active_record/transactions.rb +3 -22
- data/lib/active_record/translation.rb +1 -1
- data/lib/active_record/type/adapter_specific_registry.rb +1 -8
- data/lib/active_record/type.rb +3 -4
- data/lib/active_record/type_caster/connection.rb +1 -6
- data/lib/active_record/type_caster/map.rb +1 -4
- data/lib/active_record/validations/uniqueness.rb +13 -25
- data/lib/active_record.rb +2 -1
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +37 -0
- data/lib/arel/attributes.rb +22 -0
- data/lib/arel/collectors/bind.rb +24 -0
- data/lib/arel/collectors/composite.rb +31 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +20 -0
- data/lib/arel/collectors/substitute_binds.rb +28 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/insert_manager.rb +49 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +52 -0
- data/lib/arel/nodes/bind_param.rb +36 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +50 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +45 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +18 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +8 -0
- data/lib/arel/nodes/in.rb +8 -0
- data/lib/arel/nodes/infix_operation.rb +80 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +50 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +63 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +16 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +27 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +44 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +41 -0
- data/lib/arel/nodes/values.rb +16 -0
- data/lib/arel/nodes/values_list.rb +24 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/nodes.rb +67 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +257 -0
- data/lib/arel/select_manager.rb +271 -0
- data/lib/arel/table.rb +110 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors/depth_first.rb +199 -0
- data/lib/arel/visitors/dot.rb +292 -0
- data/lib/arel/visitors/ibm_db.rb +21 -0
- data/lib/arel/visitors/informix.rb +56 -0
- data/lib/arel/visitors/mssql.rb +143 -0
- data/lib/arel/visitors/mysql.rb +83 -0
- data/lib/arel/visitors/oracle.rb +159 -0
- data/lib/arel/visitors/oracle12.rb +67 -0
- data/lib/arel/visitors/postgresql.rb +116 -0
- data/lib/arel/visitors/sqlite.rb +39 -0
- data/lib/arel/visitors/to_sql.rb +913 -0
- data/lib/arel/visitors/visitor.rb +42 -0
- data/lib/arel/visitors/where_sql.rb +23 -0
- data/lib/arel/visitors.rb +20 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +44 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +2 -5
- data/lib/rails/generators/active_record/migration.rb +14 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +1 -0
- metadata +104 -26
@@ -102,6 +102,21 @@ module ActiveRecord
|
|
102
102
|
# If true, the default table name for a Product class will be "products". If false, it would just be "product".
|
103
103
|
# See table_name for the full rules on table/class naming. This is true, by default.
|
104
104
|
|
105
|
+
##
|
106
|
+
# :singleton-method: implicit_order_column
|
107
|
+
# :call-seq: implicit_order_column
|
108
|
+
#
|
109
|
+
# The name of the column records are ordered by if no explicit order clause
|
110
|
+
# is used during an ordered finder call. If not set the primary key is used.
|
111
|
+
|
112
|
+
##
|
113
|
+
# :singleton-method: implicit_order_column=
|
114
|
+
# :call-seq: implicit_order_column=(column_name)
|
115
|
+
#
|
116
|
+
# Sets the column to sort records by when no explicit order clause is used
|
117
|
+
# during an ordered finder call. Useful when the primary key is not an
|
118
|
+
# auto-incrementing integer, for example when it's a UUID. Note that using
|
119
|
+
# a non-unique column can result in non-deterministic results.
|
105
120
|
included do
|
106
121
|
mattr_accessor :primary_key_prefix_type, instance_writer: false
|
107
122
|
|
@@ -110,6 +125,7 @@ module ActiveRecord
|
|
110
125
|
class_attribute :schema_migrations_table_name, instance_accessor: false, default: "schema_migrations"
|
111
126
|
class_attribute :internal_metadata_table_name, instance_accessor: false, default: "ar_internal_metadata"
|
112
127
|
class_attribute :pluralize_table_names, instance_writer: false, default: true
|
128
|
+
class_attribute :implicit_order_column, instance_accessor: false
|
113
129
|
|
114
130
|
self.protected_environments = ["production"]
|
115
131
|
self.inheritance_column = "type"
|
@@ -218,11 +234,11 @@ module ActiveRecord
|
|
218
234
|
end
|
219
235
|
|
220
236
|
def full_table_name_prefix #:nodoc:
|
221
|
-
(
|
237
|
+
(module_parents.detect { |p| p.respond_to?(:table_name_prefix) } || self).table_name_prefix
|
222
238
|
end
|
223
239
|
|
224
240
|
def full_table_name_suffix #:nodoc:
|
225
|
-
(
|
241
|
+
(module_parents.detect { |p| p.respond_to?(:table_name_suffix) } || self).table_name_suffix
|
226
242
|
end
|
227
243
|
|
228
244
|
# The array of names of environments where destructive actions should be prohibited. By default,
|
@@ -276,7 +292,7 @@ module ActiveRecord
|
|
276
292
|
end
|
277
293
|
|
278
294
|
def sequence_name
|
279
|
-
if base_class
|
295
|
+
if base_class?
|
280
296
|
@sequence_name ||= reset_sequence_name
|
281
297
|
else
|
282
298
|
(@sequence_name ||= nil) || base_class.sequence_name
|
@@ -388,6 +404,11 @@ module ActiveRecord
|
|
388
404
|
@column_names ||= columns.map(&:name)
|
389
405
|
end
|
390
406
|
|
407
|
+
def symbol_column_to_string(name_symbol) # :nodoc:
|
408
|
+
@symbol_column_to_string_name_hash ||= column_names.index_by(&:to_sym)
|
409
|
+
@symbol_column_to_string_name_hash[name_symbol]
|
410
|
+
end
|
411
|
+
|
391
412
|
# Returns an array of column objects where the primary id, all columns ending in "_id" or "_count",
|
392
413
|
# and columns used for single table inheritance have been removed.
|
393
414
|
def content_columns
|
@@ -477,6 +498,7 @@ module ActiveRecord
|
|
477
498
|
def reload_schema_from_cache
|
478
499
|
@arel_table = nil
|
479
500
|
@column_names = nil
|
501
|
+
@symbol_column_to_string_name_hash = nil
|
480
502
|
@attribute_types = nil
|
481
503
|
@content_columns = nil
|
482
504
|
@default_attributes = nil
|
@@ -501,19 +523,18 @@ module ActiveRecord
|
|
501
523
|
|
502
524
|
# Computes and returns a table name according to default conventions.
|
503
525
|
def compute_table_name
|
504
|
-
|
505
|
-
if self == base
|
526
|
+
if base_class?
|
506
527
|
# Nested classes are prefixed with singular parent table name.
|
507
|
-
if
|
508
|
-
contained =
|
509
|
-
contained = contained.singularize if
|
528
|
+
if module_parent < Base && !module_parent.abstract_class?
|
529
|
+
contained = module_parent.table_name
|
530
|
+
contained = contained.singularize if module_parent.pluralize_table_names
|
510
531
|
contained += "_"
|
511
532
|
end
|
512
533
|
|
513
534
|
"#{full_table_name_prefix}#{contained}#{undecorated_table_name(name)}#{full_table_name_suffix}"
|
514
535
|
else
|
515
536
|
# STI subclasses always use their superclass' table.
|
516
|
-
|
537
|
+
base_class.table_name
|
517
538
|
end
|
518
539
|
end
|
519
540
|
end
|
@@ -426,7 +426,7 @@ module ActiveRecord
|
|
426
426
|
existing_record.assign_attributes(assignable_attributes)
|
427
427
|
association(association_name).initialize_attributes(existing_record)
|
428
428
|
else
|
429
|
-
method = "build_#{association_name}"
|
429
|
+
method = :"build_#{association_name}"
|
430
430
|
if respond_to?(method)
|
431
431
|
send(method, assignable_attributes)
|
432
432
|
else
|
@@ -501,7 +501,7 @@ module ActiveRecord
|
|
501
501
|
|
502
502
|
if attributes["id"].blank?
|
503
503
|
unless reject_new_record?(association_name, attributes)
|
504
|
-
association.build(attributes.except(*UNASSIGNABLE_KEYS))
|
504
|
+
association.reader.build(attributes.except(*UNASSIGNABLE_KEYS))
|
505
505
|
end
|
506
506
|
elsif existing_record = existing_records.detect { |record| record.id.to_s == attributes["id"].to_s }
|
507
507
|
unless call_reject_if(association_name, attributes)
|
@@ -43,6 +43,13 @@ module ActiveRecord
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
+
# Returns +true+ if the class has +no_touching+ set, +false+ otherwise.
|
47
|
+
#
|
48
|
+
# Project.no_touching do
|
49
|
+
# Project.first.no_touching? # true
|
50
|
+
# Message.first.no_touching? # false
|
51
|
+
# end
|
52
|
+
#
|
46
53
|
def no_touching?
|
47
54
|
NoTouching.applied_to?(self.class)
|
48
55
|
end
|
@@ -67,8 +67,7 @@ module ActiveRecord
|
|
67
67
|
# how this "single-table" inheritance mapping is implemented.
|
68
68
|
def instantiate(attributes, column_types = {}, &block)
|
69
69
|
klass = discriminate_class_for_record(attributes)
|
70
|
-
|
71
|
-
klass.allocate.init_with("attributes" => attributes, "new_record" => false, &block)
|
70
|
+
instantiate_instance_of(klass, attributes, column_types, &block)
|
72
71
|
end
|
73
72
|
|
74
73
|
# Updates an object (or multiple objects) and saves it to the database, if validations pass.
|
@@ -178,7 +177,7 @@ module ActiveRecord
|
|
178
177
|
end
|
179
178
|
|
180
179
|
if values.empty?
|
181
|
-
im = arel_table.compile_insert(connection.empty_insert_statement_value)
|
180
|
+
im = arel_table.compile_insert(connection.empty_insert_statement_value(primary_key))
|
182
181
|
im.into arel_table
|
183
182
|
else
|
184
183
|
im = arel_table.compile_insert(_substitute_values(values))
|
@@ -208,6 +207,13 @@ module ActiveRecord
|
|
208
207
|
end
|
209
208
|
|
210
209
|
private
|
210
|
+
# Given a class, an attributes hash, +instantiate_instance_of+ returns a
|
211
|
+
# new instance of the class. Accepts only keys as strings.
|
212
|
+
def instantiate_instance_of(klass, attributes, column_types = {}, &block)
|
213
|
+
attributes = klass.attributes_builder.build_from_database(attributes, column_types)
|
214
|
+
klass.allocate.init_with_attributes(attributes, &block)
|
215
|
+
end
|
216
|
+
|
211
217
|
# Called by +instantiate+ to decide which class to use for a new
|
212
218
|
# record instance.
|
213
219
|
#
|
@@ -430,6 +436,7 @@ module ActiveRecord
|
|
430
436
|
end
|
431
437
|
|
432
438
|
alias update_attributes update
|
439
|
+
deprecate :update_attributes
|
433
440
|
|
434
441
|
# Updates its receiver just like #update but calls #save! instead
|
435
442
|
# of +save+, so an exception is raised if the record is invalid and saving will fail.
|
@@ -443,6 +450,7 @@ module ActiveRecord
|
|
443
450
|
end
|
444
451
|
|
445
452
|
alias update_attributes! update!
|
453
|
+
deprecate :update_attributes!
|
446
454
|
|
447
455
|
# Equivalent to <code>update_columns(name => value)</code>.
|
448
456
|
def update_column(name, value)
|
@@ -709,7 +717,6 @@ module ActiveRecord
|
|
709
717
|
# Updates the associated record with values matching those of the instance attributes.
|
710
718
|
# Returns the number of affected rows.
|
711
719
|
def _update_record(attribute_names = self.attribute_names)
|
712
|
-
attribute_names &= self.class.column_names
|
713
720
|
attribute_names = attributes_for_update(attribute_names)
|
714
721
|
|
715
722
|
if attribute_names.empty?
|
@@ -728,10 +735,12 @@ module ActiveRecord
|
|
728
735
|
# Creates a record with values matching those of the instance attributes
|
729
736
|
# and returns its id.
|
730
737
|
def _create_record(attribute_names = self.attribute_names)
|
731
|
-
attribute_names
|
732
|
-
|
738
|
+
attribute_names = attributes_for_create(attribute_names)
|
739
|
+
|
740
|
+
new_id = self.class._insert_record(
|
741
|
+
attributes_with_values(attribute_names)
|
742
|
+
)
|
733
743
|
|
734
|
-
new_id = self.class._insert_record(attributes_values)
|
735
744
|
self.id ||= new_id if self.class.primary_key
|
736
745
|
|
737
746
|
@new_record = false
|
@@ -752,6 +761,8 @@ module ActiveRecord
|
|
752
761
|
@_association_destroy_exception = nil
|
753
762
|
end
|
754
763
|
|
764
|
+
# The name of the method used to touch a +belongs_to+ association when the
|
765
|
+
# +:touch+ option is used.
|
755
766
|
def belongs_to_touch_method
|
756
767
|
:touch
|
757
768
|
end
|
@@ -26,15 +26,22 @@ module ActiveRecord
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def self.run
|
29
|
-
|
30
|
-
|
29
|
+
pools = []
|
30
|
+
|
31
|
+
ActiveRecord::Base.connection_handlers.each do |key, handler|
|
32
|
+
pools << handler.connection_pool_list.reject { |p| p.query_cache_enabled }.each { |p| p.enable_query_cache! }
|
33
|
+
end
|
34
|
+
|
35
|
+
pools.flatten
|
31
36
|
end
|
32
37
|
|
33
38
|
def self.complete(pools)
|
34
39
|
pools.each { |pool| pool.disable_query_cache! }
|
35
40
|
|
36
|
-
ActiveRecord::Base.
|
37
|
-
|
41
|
+
ActiveRecord::Base.connection_handlers.each do |_, handler|
|
42
|
+
handler.connection_pool_list.each do |pool|
|
43
|
+
pool.release_connection if pool.active_connection? && !pool.connection.transaction_open?
|
44
|
+
end
|
38
45
|
end
|
39
46
|
end
|
40
47
|
|
@@ -5,7 +5,7 @@ module ActiveRecord
|
|
5
5
|
delegate :find, :take, :take!, :first, :first!, :last, :last!, :exists?, :any?, :many?, :none?, :one?, to: :all
|
6
6
|
delegate :second, :second!, :third, :third!, :fourth, :fourth!, :fifth, :fifth!, :forty_two, :forty_two!, :third_to_last, :third_to_last!, :second_to_last, :second_to_last!, to: :all
|
7
7
|
delegate :first_or_create, :first_or_create!, :first_or_initialize, to: :all
|
8
|
-
delegate :find_or_create_by, :find_or_create_by!, :find_or_initialize_by, to: :all
|
8
|
+
delegate :find_or_create_by, :find_or_create_by!, :create_or_find_by, :create_or_find_by!, :find_or_initialize_by, to: :all
|
9
9
|
delegate :find_by, :find_by!, to: :all
|
10
10
|
delegate :destroy_all, :delete_all, :update_all, to: :all
|
11
11
|
delegate :find_each, :find_in_batches, :in_batches, to: :all
|
@@ -13,20 +13,20 @@ module ActiveRecord
|
|
13
13
|
:where, :rewhere, :preload, :eager_load, :includes, :from, :lock, :readonly, :extending,
|
14
14
|
:having, :create_with, :distinct, :references, :none, :unscope, :merge, to: :all
|
15
15
|
delegate :count, :average, :minimum, :maximum, :sum, :calculate, to: :all
|
16
|
-
delegate :pluck, :ids, to: :all
|
16
|
+
delegate :pluck, :pick, :ids, to: :all
|
17
17
|
|
18
18
|
# Executes a custom SQL query against your database and returns all the results. The results will
|
19
|
-
# be returned as an array with
|
20
|
-
# this method from.
|
19
|
+
# be returned as an array, with the requested columns encapsulated as attributes of the model you call
|
20
|
+
# this method from. For example, if you call <tt>Product.find_by_sql</tt>, then the results will be returned in
|
21
21
|
# a +Product+ object with the attributes you specified in the SQL query.
|
22
22
|
#
|
23
|
-
# If you call a complicated SQL query which spans multiple tables the columns specified by the
|
23
|
+
# If you call a complicated SQL query which spans multiple tables, the columns specified by the
|
24
24
|
# SELECT will be attributes of the model, whether or not they are columns of the corresponding
|
25
25
|
# table.
|
26
26
|
#
|
27
|
-
# The +sql+ parameter is a full SQL query as a string. It will be called as is
|
28
|
-
# no database agnostic conversions performed. This should be a last resort because using
|
29
|
-
#
|
27
|
+
# The +sql+ parameter is a full SQL query as a string. It will be called as is; there will be
|
28
|
+
# no database agnostic conversions performed. This should be a last resort because using
|
29
|
+
# database-specific terms will lock you into using that particular database engine, or require you to
|
30
30
|
# change your call if you switch engines.
|
31
31
|
#
|
32
32
|
# # A simple SQL query spanning multiple tables
|
@@ -40,7 +40,8 @@ module ActiveRecord
|
|
40
40
|
def find_by_sql(sql, binds = [], preparable: nil, &block)
|
41
41
|
result_set = connection.select_all(sanitize_sql(sql), "#{name} Load", binds, preparable: preparable)
|
42
42
|
column_types = result_set.column_types.dup
|
43
|
-
|
43
|
+
cached_columns_hash = connection.schema_cache.columns_hash(table_name)
|
44
|
+
cached_columns_hash.each_key { |k| column_types.delete k }
|
44
45
|
message_bus = ActiveSupport::Notifications.instrumenter
|
45
46
|
|
46
47
|
payload = {
|
@@ -49,13 +50,20 @@ module ActiveRecord
|
|
49
50
|
}
|
50
51
|
|
51
52
|
message_bus.instrument("instantiation.active_record", payload) do
|
52
|
-
result_set.
|
53
|
+
if result_set.includes_column?(inheritance_column)
|
54
|
+
result_set.map { |record| instantiate(record, column_types, &block) }
|
55
|
+
else
|
56
|
+
# Instantiate a homogeneous set
|
57
|
+
result_set.map { |record| instantiate_instance_of(self, record, column_types, &block) }
|
58
|
+
end
|
53
59
|
end
|
54
60
|
end
|
55
61
|
|
56
62
|
# Returns the result of an SQL statement that should only include a COUNT(*) in the SELECT part.
|
57
63
|
# The use of this method should be restricted to complicated SQL queries that can't be executed
|
58
|
-
# using the ActiveRecord::Calculations class methods. Look into those before using this
|
64
|
+
# using the ActiveRecord::Calculations class methods. Look into those before using this method,
|
65
|
+
# as it could lock you into a specific database engine or require a code change to switch
|
66
|
+
# database engines.
|
59
67
|
#
|
60
68
|
# Product.count_by_sql "SELECT COUNT(*) FROM sales s, customers c WHERE s.customer_id = c.id"
|
61
69
|
# # => 12
|
@@ -77,6 +77,10 @@ module ActiveRecord
|
|
77
77
|
ActiveSupport.on_load(:active_record) { self.logger ||= ::Rails.logger }
|
78
78
|
end
|
79
79
|
|
80
|
+
initializer "active_record.backtrace_cleaner" do
|
81
|
+
ActiveSupport.on_load(:active_record) { LogSubscriber.backtrace_cleaner = ::Rails.backtrace_cleaner }
|
82
|
+
end
|
83
|
+
|
80
84
|
initializer "active_record.migration_error" do
|
81
85
|
if config.active_record.delete(:migration_error) == :page_load
|
82
86
|
config.app_middleware.insert_after ::ActionDispatch::Callbacks,
|
@@ -84,6 +88,31 @@ module ActiveRecord
|
|
84
88
|
end
|
85
89
|
end
|
86
90
|
|
91
|
+
initializer "Check for cache versioning support" do
|
92
|
+
config.after_initialize do |app|
|
93
|
+
ActiveSupport.on_load(:active_record) do
|
94
|
+
if app.config.active_record.cache_versioning && Rails.cache
|
95
|
+
unless Rails.cache.class.try(:supports_cache_versioning?)
|
96
|
+
raise <<-end_error
|
97
|
+
|
98
|
+
You're using a cache store that doesn't support native cache versioning.
|
99
|
+
Your best option is to upgrade to a newer version of #{Rails.cache.class}
|
100
|
+
that supports cache versioning (#{Rails.cache.class}.supports_cache_versioning? #=> true).
|
101
|
+
|
102
|
+
Next best, switch to a different cache store that does support cache versioning:
|
103
|
+
https://guides.rubyonrails.org/caching_with_rails.html#cache-stores.
|
104
|
+
|
105
|
+
To keep using the current cache store, you can turn off cache versioning entirely:
|
106
|
+
|
107
|
+
config.active_record.cache_versioning = false
|
108
|
+
|
109
|
+
end_error
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
87
116
|
initializer "active_record.check_schema_cache_dump" do
|
88
117
|
if config.active_record.delete(:use_schema_cache_dump)
|
89
118
|
config.after_initialize do |app|
|
@@ -108,6 +137,26 @@ module ActiveRecord
|
|
108
137
|
end
|
109
138
|
end
|
110
139
|
|
140
|
+
initializer "active_record.define_attribute_methods" do |app|
|
141
|
+
config.after_initialize do
|
142
|
+
ActiveSupport.on_load(:active_record) do
|
143
|
+
if app.config.eager_load
|
144
|
+
descendants.each do |model|
|
145
|
+
# SchemaMigration and InternalMetadata both override `table_exists?`
|
146
|
+
# to bypass the schema cache, so skip them to avoid the extra queries.
|
147
|
+
next if model._internal?
|
148
|
+
|
149
|
+
# If there's no connection yet, or the schema cache doesn't have the columns
|
150
|
+
# hash for the model cached, `define_attribute_methods` would trigger a query.
|
151
|
+
next unless model.connected? && model.connection.schema_cache.columns_hash?(model.table_name)
|
152
|
+
|
153
|
+
model.define_attribute_methods
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
111
160
|
initializer "active_record.warn_on_records_fetched_greater_than" do
|
112
161
|
if config.active_record.warn_on_records_fetched_greater_than
|
113
162
|
ActiveSupport.on_load(:active_record) do
|
@@ -118,8 +167,18 @@ module ActiveRecord
|
|
118
167
|
|
119
168
|
initializer "active_record.set_configs" do |app|
|
120
169
|
ActiveSupport.on_load(:active_record) do
|
121
|
-
configs = app.config.active_record
|
170
|
+
configs = app.config.active_record
|
171
|
+
|
172
|
+
represent_boolean_as_integer = configs.sqlite3.delete(:represent_boolean_as_integer)
|
173
|
+
|
174
|
+
unless represent_boolean_as_integer.nil?
|
175
|
+
ActiveSupport.on_load(:active_record_sqlite3adapter) do
|
176
|
+
ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = represent_boolean_as_integer
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
122
180
|
configs.delete(:sqlite3)
|
181
|
+
|
123
182
|
configs.each do |k, v|
|
124
183
|
send "#{k}=", v
|
125
184
|
end
|
@@ -131,21 +190,7 @@ module ActiveRecord
|
|
131
190
|
initializer "active_record.initialize_database" do
|
132
191
|
ActiveSupport.on_load(:active_record) do
|
133
192
|
self.configurations = Rails.application.config.database_configuration
|
134
|
-
|
135
|
-
begin
|
136
|
-
establish_connection
|
137
|
-
rescue ActiveRecord::NoDatabaseError
|
138
|
-
warn <<-end_warning
|
139
|
-
Oops - You have a database configured, but it doesn't exist yet!
|
140
|
-
|
141
|
-
Here's how to get started:
|
142
|
-
|
143
|
-
1. Configure your database in config/database.yml.
|
144
|
-
2. Run `bin/rails db:create` to create the database.
|
145
|
-
3. Run `bin/rails db:setup` to load your database schema.
|
146
|
-
end_warning
|
147
|
-
raise
|
148
|
-
end
|
193
|
+
establish_connection
|
149
194
|
end
|
150
195
|
end
|
151
196
|
|
@@ -157,6 +202,13 @@ end_warning
|
|
157
202
|
end
|
158
203
|
end
|
159
204
|
|
205
|
+
initializer "active_record.collection_cache_association_loading" do
|
206
|
+
require "active_record/railties/collection_cache_association_loading"
|
207
|
+
ActiveSupport.on_load(:action_view) do
|
208
|
+
ActionView::PartialRenderer.prepend(ActiveRecord::Railties::CollectionCacheAssociationLoading)
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
160
212
|
initializer "active_record.set_reloader_hooks" do
|
161
213
|
ActiveSupport.on_load(:active_record) do
|
162
214
|
ActiveSupport::Reloader.before_class_unload do
|
@@ -194,32 +246,9 @@ end_warning
|
|
194
246
|
end
|
195
247
|
end
|
196
248
|
|
197
|
-
initializer "active_record.
|
198
|
-
|
199
|
-
|
200
|
-
represent_boolean_as_integer = Rails.application.config.active_record.sqlite3.delete(:represent_boolean_as_integer)
|
201
|
-
unless represent_boolean_as_integer.nil?
|
202
|
-
ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = represent_boolean_as_integer
|
203
|
-
end
|
204
|
-
|
205
|
-
unless ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer
|
206
|
-
ActiveSupport::Deprecation.warn <<-MSG
|
207
|
-
Leaving `ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer`
|
208
|
-
set to false is deprecated. SQLite databases have used 't' and 'f' to serialize
|
209
|
-
boolean values and must have old data converted to 1 and 0 (its native boolean
|
210
|
-
serialization) before setting this flag to true. Conversion can be accomplished
|
211
|
-
by setting up a rake task which runs
|
212
|
-
|
213
|
-
ExampleModel.where("boolean_column = 't'").update_all(boolean_column: 1)
|
214
|
-
ExampleModel.where("boolean_column = 'f'").update_all(boolean_column: 0)
|
215
|
-
|
216
|
-
for all models and all boolean columns, after which the flag must be set to
|
217
|
-
true by adding the following to your application.rb file:
|
218
|
-
|
219
|
-
Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true
|
220
|
-
MSG
|
221
|
-
end
|
222
|
-
end
|
249
|
+
initializer "active_record.set_filter_attributes" do
|
250
|
+
ActiveSupport.on_load(:active_record) do
|
251
|
+
self.filter_attributes += Rails.application.config.filter_parameters
|
223
252
|
end
|
224
253
|
end
|
225
254
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module Railties # :nodoc:
|
5
|
+
module CollectionCacheAssociationLoading #:nodoc:
|
6
|
+
def setup(context, options, block)
|
7
|
+
@relation = relation_from_options(options)
|
8
|
+
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
def relation_from_options(cached: nil, partial: nil, collection: nil, **_)
|
13
|
+
return unless cached
|
14
|
+
|
15
|
+
relation = partial if partial.is_a?(ActiveRecord::Relation)
|
16
|
+
relation ||= collection if collection.is_a?(ActiveRecord::Relation)
|
17
|
+
|
18
|
+
if relation && !relation.loaded?
|
19
|
+
relation.skip_preloading!
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def collection_without_template
|
24
|
+
@relation.preload_associations(@collection) if @relation
|
25
|
+
super
|
26
|
+
end
|
27
|
+
|
28
|
+
def collection_with_template
|
29
|
+
@relation.preload_associations(@collection) if @relation
|
30
|
+
super
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -8,49 +8,44 @@ module ActiveRecord
|
|
8
8
|
module ControllerRuntime #:nodoc:
|
9
9
|
extend ActiveSupport::Concern
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
private
|
18
|
-
|
19
|
-
def process_action(action, *args)
|
20
|
-
# We also need to reset the runtime before each action
|
21
|
-
# because of queries in middleware or in cases we are streaming
|
22
|
-
# and it won't be cleaned up by the method below.
|
23
|
-
ActiveRecord::LogSubscriber.reset_runtime
|
24
|
-
super
|
11
|
+
module ClassMethods # :nodoc:
|
12
|
+
def log_process_action(payload)
|
13
|
+
messages, db_runtime = super, payload[:db_runtime]
|
14
|
+
messages << ("ActiveRecord: %.1fms" % db_runtime.to_f) if db_runtime
|
15
|
+
messages
|
16
|
+
end
|
25
17
|
end
|
26
18
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
runtime
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
else
|
19
|
+
private
|
20
|
+
attr_internal :db_runtime
|
21
|
+
|
22
|
+
def process_action(action, *args)
|
23
|
+
# We also need to reset the runtime before each action
|
24
|
+
# because of queries in middleware or in cases we are streaming
|
25
|
+
# and it won't be cleaned up by the method below.
|
26
|
+
ActiveRecord::LogSubscriber.reset_runtime
|
36
27
|
super
|
37
28
|
end
|
38
|
-
end
|
39
29
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
30
|
+
def cleanup_view_runtime
|
31
|
+
if logger && logger.info? && ActiveRecord::Base.connected?
|
32
|
+
db_rt_before_render = ActiveRecord::LogSubscriber.reset_runtime
|
33
|
+
self.db_runtime = (db_runtime || 0) + db_rt_before_render
|
34
|
+
runtime = super
|
35
|
+
db_rt_after_render = ActiveRecord::LogSubscriber.reset_runtime
|
36
|
+
self.db_runtime += db_rt_after_render
|
37
|
+
runtime - db_rt_after_render
|
38
|
+
else
|
39
|
+
super
|
40
|
+
end
|
44
41
|
end
|
45
|
-
end
|
46
42
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
43
|
+
def append_info_to_payload(payload)
|
44
|
+
super
|
45
|
+
if ActiveRecord::Base.connected?
|
46
|
+
payload[:db_runtime] = (db_runtime || 0) + ActiveRecord::LogSubscriber.reset_runtime
|
47
|
+
end
|
52
48
|
end
|
53
|
-
end
|
54
49
|
end
|
55
50
|
end
|
56
51
|
end
|