activerecord 7.1.6 → 7.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +839 -2248
- data/README.rdoc +16 -16
- data/examples/performance.rb +2 -2
- data/lib/active_record/association_relation.rb +1 -1
- data/lib/active_record/associations/alias_tracker.rb +31 -23
- data/lib/active_record/associations/association.rb +15 -8
- data/lib/active_record/associations/belongs_to_association.rb +31 -8
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -2
- data/lib/active_record/associations/builder/belongs_to.rb +1 -0
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +2 -2
- data/lib/active_record/associations/builder/has_many.rb +3 -4
- data/lib/active_record/associations/builder/has_one.rb +3 -4
- data/lib/active_record/associations/collection_association.rb +16 -8
- data/lib/active_record/associations/collection_proxy.rb +14 -1
- data/lib/active_record/associations/errors.rb +265 -0
- data/lib/active_record/associations/has_many_association.rb +1 -1
- data/lib/active_record/associations/has_many_through_association.rb +7 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +1 -1
- data/lib/active_record/associations/nested_error.rb +47 -0
- data/lib/active_record/associations/preloader/association.rb +2 -1
- data/lib/active_record/associations/preloader/branch.rb +7 -1
- data/lib/active_record/associations/preloader/through_association.rb +1 -3
- data/lib/active_record/associations/singular_association.rb +6 -0
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/associations.rb +59 -292
- data/lib/active_record/attribute_assignment.rb +0 -2
- data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
- data/lib/active_record/attribute_methods/primary_key.rb +23 -55
- data/lib/active_record/attribute_methods/read.rb +1 -13
- data/lib/active_record/attribute_methods/serialization.rb +5 -25
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +7 -6
- data/lib/active_record/attribute_methods.rb +51 -60
- data/lib/active_record/attributes.rb +93 -68
- data/lib/active_record/autosave_association.rb +25 -32
- data/lib/active_record/base.rb +4 -5
- data/lib/active_record/callbacks.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +24 -107
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +1 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +294 -72
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +34 -17
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +201 -75
- data/lib/active_record/connection_adapters/abstract/quoting.rb +65 -91
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +6 -2
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +18 -6
- data/lib/active_record/connection_adapters/abstract/transaction.rb +125 -62
- data/lib/active_record/connection_adapters/abstract_adapter.rb +46 -44
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +53 -15
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +9 -1
- data/lib/active_record/connection_adapters/mysql/quoting.rb +43 -48
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +6 -0
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +19 -18
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -23
- data/lib/active_record/connection_adapters/pool_config.rb +7 -6
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +27 -4
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +58 -58
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +30 -8
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +16 -12
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +36 -26
- data/lib/active_record/connection_adapters/schema_cache.rb +123 -128
- data/lib/active_record/connection_adapters/sqlite3/column.rb +14 -1
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +10 -6
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +57 -46
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +13 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +26 -2
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +133 -78
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +15 -15
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +19 -48
- data/lib/active_record/connection_adapters.rb +121 -0
- data/lib/active_record/connection_handling.rb +68 -49
- data/lib/active_record/core.rb +112 -44
- data/lib/active_record/counter_cache.rb +19 -10
- data/lib/active_record/database_configurations/connection_url_resolver.rb +9 -2
- data/lib/active_record/database_configurations/database_config.rb +19 -4
- data/lib/active_record/database_configurations/hash_config.rb +38 -34
- data/lib/active_record/database_configurations/url_config.rb +20 -1
- data/lib/active_record/database_configurations.rb +1 -1
- data/lib/active_record/delegated_type.rb +42 -18
- data/lib/active_record/dynamic_matchers.rb +2 -2
- data/lib/active_record/encryption/encryptable_record.rb +4 -4
- data/lib/active_record/encryption/encrypted_attribute_type.rb +25 -5
- data/lib/active_record/encryption/encryptor.rb +35 -19
- data/lib/active_record/encryption/key_provider.rb +1 -1
- data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
- data/lib/active_record/encryption/message_serializer.rb +4 -0
- data/lib/active_record/encryption/null_encryptor.rb +4 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +4 -0
- data/lib/active_record/enum.rb +31 -13
- data/lib/active_record/errors.rb +49 -23
- data/lib/active_record/explain.rb +13 -24
- data/lib/active_record/fixture_set/table_row.rb +19 -2
- data/lib/active_record/fixtures.rb +37 -31
- data/lib/active_record/future_result.rb +8 -4
- data/lib/active_record/gem_version.rb +2 -2
- data/lib/active_record/inheritance.rb +4 -2
- data/lib/active_record/insert_all.rb +18 -15
- data/lib/active_record/integration.rb +4 -1
- data/lib/active_record/internal_metadata.rb +48 -34
- data/lib/active_record/locking/optimistic.rb +7 -6
- data/lib/active_record/log_subscriber.rb +0 -21
- data/lib/active_record/message_pack.rb +1 -1
- data/lib/active_record/migration/command_recorder.rb +2 -3
- data/lib/active_record/migration/compatibility.rb +5 -3
- data/lib/active_record/migration/default_strategy.rb +4 -5
- data/lib/active_record/migration/pending_migration_connection.rb +2 -2
- data/lib/active_record/migration.rb +87 -77
- data/lib/active_record/model_schema.rb +31 -68
- data/lib/active_record/nested_attributes.rb +11 -3
- data/lib/active_record/normalization.rb +3 -7
- data/lib/active_record/persistence.rb +30 -352
- data/lib/active_record/query_cache.rb +19 -8
- data/lib/active_record/query_logs.rb +19 -0
- data/lib/active_record/querying.rb +25 -13
- data/lib/active_record/railtie.rb +39 -57
- data/lib/active_record/railties/controller_runtime.rb +13 -4
- data/lib/active_record/railties/databases.rake +42 -44
- data/lib/active_record/reflection.rb +98 -36
- data/lib/active_record/relation/batches/batch_enumerator.rb +15 -2
- data/lib/active_record/relation/batches.rb +14 -8
- data/lib/active_record/relation/calculations.rb +127 -89
- data/lib/active_record/relation/delegation.rb +8 -11
- data/lib/active_record/relation/finder_methods.rb +26 -12
- data/lib/active_record/relation/merger.rb +4 -6
- data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +10 -2
- data/lib/active_record/relation/predicate_builder.rb +3 -3
- data/lib/active_record/relation/query_attribute.rb +1 -1
- data/lib/active_record/relation/query_methods.rb +238 -65
- data/lib/active_record/relation/record_fetch_warning.rb +3 -0
- data/lib/active_record/relation/spawn_methods.rb +2 -18
- data/lib/active_record/relation/where_clause.rb +15 -21
- data/lib/active_record/relation.rb +508 -74
- data/lib/active_record/result.rb +31 -44
- data/lib/active_record/runtime_registry.rb +39 -0
- data/lib/active_record/sanitization.rb +24 -19
- data/lib/active_record/schema.rb +8 -6
- data/lib/active_record/schema_dumper.rb +48 -20
- data/lib/active_record/schema_migration.rb +30 -14
- data/lib/active_record/scoping/named.rb +1 -0
- data/lib/active_record/secure_token.rb +3 -3
- data/lib/active_record/signed_id.rb +27 -7
- data/lib/active_record/statement_cache.rb +7 -7
- data/lib/active_record/table_metadata.rb +1 -10
- data/lib/active_record/tasks/database_tasks.rb +69 -41
- data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
- data/lib/active_record/tasks/postgresql_database_tasks.rb +8 -1
- data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -1
- data/lib/active_record/test_fixtures.rb +86 -89
- data/lib/active_record/testing/query_assertions.rb +121 -0
- data/lib/active_record/timestamp.rb +2 -2
- data/lib/active_record/token_for.rb +22 -12
- data/lib/active_record/touch_later.rb +1 -1
- data/lib/active_record/transaction.rb +132 -0
- data/lib/active_record/transactions.rb +73 -15
- data/lib/active_record/translation.rb +0 -2
- data/lib/active_record/type/serialized.rb +1 -3
- data/lib/active_record/type_caster/connection.rb +4 -4
- data/lib/active_record/validations/associated.rb +9 -3
- data/lib/active_record/validations/uniqueness.rb +15 -10
- data/lib/active_record/validations.rb +4 -1
- data/lib/active_record.rb +148 -39
- data/lib/arel/alias_predication.rb +1 -1
- data/lib/arel/collectors/bind.rb +3 -1
- data/lib/arel/collectors/composite.rb +7 -0
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +1 -1
- data/lib/arel/crud.rb +2 -0
- data/lib/arel/delete_manager.rb +5 -0
- data/lib/arel/nodes/binary.rb +0 -6
- data/lib/arel/nodes/bound_sql_literal.rb +9 -5
- data/lib/arel/nodes/delete_statement.rb +4 -2
- data/lib/arel/nodes/{and.rb → nary.rb} +5 -2
- data/lib/arel/nodes/node.rb +4 -3
- data/lib/arel/nodes/sql_literal.rb +7 -0
- data/lib/arel/nodes/update_statement.rb +4 -2
- data/lib/arel/nodes.rb +2 -2
- data/lib/arel/predications.rb +1 -1
- data/lib/arel/select_manager.rb +7 -3
- data/lib/arel/tree_manager.rb +3 -2
- data/lib/arel/update_manager.rb +7 -1
- data/lib/arel/visitors/dot.rb +3 -0
- data/lib/arel/visitors/mysql.rb +9 -4
- data/lib/arel/visitors/postgresql.rb +1 -12
- data/lib/arel/visitors/sqlite.rb +25 -0
- data/lib/arel/visitors/to_sql.rb +31 -16
- data/lib/arel.rb +7 -3
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +4 -1
- metadata +16 -10
|
@@ -11,6 +11,7 @@ module ActiveRecord
|
|
|
11
11
|
class_attribute :_reflections, instance_writer: false, default: {}
|
|
12
12
|
class_attribute :aggregate_reflections, instance_writer: false, default: {}
|
|
13
13
|
class_attribute :automatic_scope_inversing, instance_writer: false, default: false
|
|
14
|
+
class_attribute :automatically_invert_plural_associations, instance_writer: false, default: false
|
|
14
15
|
end
|
|
15
16
|
|
|
16
17
|
class << self
|
|
@@ -21,12 +22,12 @@ module ActiveRecord
|
|
|
21
22
|
|
|
22
23
|
def add_reflection(ar, name, reflection)
|
|
23
24
|
ar.clear_reflections_cache
|
|
24
|
-
name =
|
|
25
|
+
name = name.to_sym
|
|
25
26
|
ar._reflections = ar._reflections.except(name).merge!(name => reflection)
|
|
26
27
|
end
|
|
27
28
|
|
|
28
29
|
def add_aggregate_reflection(ar, name, reflection)
|
|
29
|
-
ar.aggregate_reflections = ar.aggregate_reflections.merge(
|
|
30
|
+
ar.aggregate_reflections = ar.aggregate_reflections.merge(name.to_sym => reflection)
|
|
30
31
|
end
|
|
31
32
|
|
|
32
33
|
private
|
|
@@ -67,7 +68,7 @@ module ActiveRecord
|
|
|
67
68
|
# Account.reflect_on_aggregation(:balance) # => the balance AggregateReflection
|
|
68
69
|
#
|
|
69
70
|
def reflect_on_aggregation(aggregation)
|
|
70
|
-
aggregate_reflections[aggregation.
|
|
71
|
+
aggregate_reflections[aggregation.to_sym]
|
|
71
72
|
end
|
|
72
73
|
|
|
73
74
|
# Returns a Hash of name of the reflection as the key and an AssociationReflection as the value.
|
|
@@ -75,6 +76,10 @@ module ActiveRecord
|
|
|
75
76
|
# Account.reflections # => {"balance" => AggregateReflection}
|
|
76
77
|
#
|
|
77
78
|
def reflections
|
|
79
|
+
normalized_reflections.stringify_keys
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def normalized_reflections # :nodoc:
|
|
78
83
|
@__reflections ||= begin
|
|
79
84
|
ref = {}
|
|
80
85
|
|
|
@@ -83,13 +88,13 @@ module ActiveRecord
|
|
|
83
88
|
|
|
84
89
|
if parent_reflection
|
|
85
90
|
parent_name = parent_reflection.name
|
|
86
|
-
ref[parent_name
|
|
91
|
+
ref[parent_name] = parent_reflection
|
|
87
92
|
else
|
|
88
93
|
ref[name] = reflection
|
|
89
94
|
end
|
|
90
95
|
end
|
|
91
96
|
|
|
92
|
-
ref
|
|
97
|
+
ref.freeze
|
|
93
98
|
end
|
|
94
99
|
end
|
|
95
100
|
|
|
@@ -104,7 +109,7 @@ module ActiveRecord
|
|
|
104
109
|
# Account.reflect_on_all_associations(:has_many) # returns an array of all has_many associations
|
|
105
110
|
#
|
|
106
111
|
def reflect_on_all_associations(macro = nil)
|
|
107
|
-
association_reflections =
|
|
112
|
+
association_reflections = normalized_reflections.values
|
|
108
113
|
association_reflections.select! { |reflection| reflection.macro == macro } if macro
|
|
109
114
|
association_reflections
|
|
110
115
|
end
|
|
@@ -115,16 +120,18 @@ module ActiveRecord
|
|
|
115
120
|
# Invoice.reflect_on_association(:line_items).macro # returns :has_many
|
|
116
121
|
#
|
|
117
122
|
def reflect_on_association(association)
|
|
118
|
-
|
|
123
|
+
normalized_reflections[association.to_sym]
|
|
119
124
|
end
|
|
120
125
|
|
|
121
126
|
def _reflect_on_association(association) # :nodoc:
|
|
122
|
-
_reflections[association.
|
|
127
|
+
_reflections[association.to_sym]
|
|
123
128
|
end
|
|
124
129
|
|
|
125
130
|
# Returns an array of AssociationReflection objects for all associations which have <tt>:autosave</tt> enabled.
|
|
126
131
|
def reflect_on_all_autosave_associations
|
|
127
|
-
reflections
|
|
132
|
+
reflections = normalized_reflections.values
|
|
133
|
+
reflections.select! { |reflection| reflection.options[:autosave] }
|
|
134
|
+
reflections
|
|
128
135
|
end
|
|
129
136
|
|
|
130
137
|
def clear_reflections_cache # :nodoc:
|
|
@@ -235,14 +242,16 @@ module ActiveRecord
|
|
|
235
242
|
end
|
|
236
243
|
|
|
237
244
|
def counter_cache_column
|
|
238
|
-
@counter_cache_column ||=
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
245
|
+
@counter_cache_column ||= begin
|
|
246
|
+
counter_cache = options[:counter_cache]
|
|
247
|
+
|
|
248
|
+
if belongs_to?
|
|
249
|
+
if counter_cache
|
|
250
|
+
counter_cache[:column] || -"#{active_record.name.demodulize.underscore.pluralize}_count"
|
|
251
|
+
end
|
|
252
|
+
else
|
|
253
|
+
-((counter_cache && -counter_cache[:column]) || "#{name}_count")
|
|
243
254
|
end
|
|
244
|
-
else
|
|
245
|
-
-(options[:counter_cache]&.to_s || "#{name}_count")
|
|
246
255
|
end
|
|
247
256
|
end
|
|
248
257
|
|
|
@@ -291,7 +300,7 @@ module ActiveRecord
|
|
|
291
300
|
inverse_of && inverse_which_updates_counter_cache == inverse_of
|
|
292
301
|
end
|
|
293
302
|
|
|
294
|
-
# Returns whether a counter cache
|
|
303
|
+
# Returns whether this association has a counter cache.
|
|
295
304
|
#
|
|
296
305
|
# The counter_cache option must be given on either the owner or inverse
|
|
297
306
|
# association, and the column must be present on the owner.
|
|
@@ -301,6 +310,17 @@ module ActiveRecord
|
|
|
301
310
|
active_record.has_attribute?(counter_cache_column)
|
|
302
311
|
end
|
|
303
312
|
|
|
313
|
+
# Returns whether this association has a counter cache and its column values were backfilled
|
|
314
|
+
# (and so it is used internally by methods like +size+/+any?+/etc).
|
|
315
|
+
def has_active_cached_counter?
|
|
316
|
+
return false unless has_cached_counter?
|
|
317
|
+
|
|
318
|
+
counter_cache = options[:counter_cache] ||
|
|
319
|
+
(inverse_which_updates_counter_cache && inverse_which_updates_counter_cache.options[:counter_cache])
|
|
320
|
+
|
|
321
|
+
counter_cache[:active] != false
|
|
322
|
+
end
|
|
323
|
+
|
|
304
324
|
def counter_must_be_updated_by_has_many?
|
|
305
325
|
!inverse_updates_counter_in_memory? && has_cached_counter?
|
|
306
326
|
end
|
|
@@ -377,12 +397,11 @@ module ActiveRecord
|
|
|
377
397
|
super()
|
|
378
398
|
@name = name
|
|
379
399
|
@scope = scope
|
|
380
|
-
@options = options
|
|
400
|
+
@options = normalize_options(options)
|
|
381
401
|
@active_record = active_record
|
|
382
402
|
@klass = options[:anonymous_class]
|
|
383
403
|
@plural_name = active_record.pluralize_table_names ?
|
|
384
404
|
name.to_s.pluralize : name.to_s
|
|
385
|
-
validate_reflection!
|
|
386
405
|
end
|
|
387
406
|
|
|
388
407
|
def autosave=(autosave)
|
|
@@ -409,7 +428,15 @@ module ActiveRecord
|
|
|
409
428
|
# a new association object. Use +build_association+ or +create_association+
|
|
410
429
|
# instead. This allows plugins to hook into association object creation.
|
|
411
430
|
def klass
|
|
412
|
-
@klass ||=
|
|
431
|
+
@klass ||= _klass(class_name)
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
def _klass(class_name) # :nodoc:
|
|
435
|
+
if active_record.name.demodulize == class_name
|
|
436
|
+
return compute_class("::#{class_name}") rescue NameError
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
compute_class(class_name)
|
|
413
440
|
end
|
|
414
441
|
|
|
415
442
|
def compute_class(name)
|
|
@@ -435,15 +462,24 @@ module ActiveRecord
|
|
|
435
462
|
name.to_s.camelize
|
|
436
463
|
end
|
|
437
464
|
|
|
438
|
-
def
|
|
439
|
-
|
|
465
|
+
def normalize_options(options)
|
|
466
|
+
counter_cache = options.delete(:counter_cache)
|
|
440
467
|
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
468
|
+
if counter_cache
|
|
469
|
+
active = true
|
|
470
|
+
|
|
471
|
+
case counter_cache
|
|
472
|
+
when String, Symbol
|
|
473
|
+
column = -counter_cache.to_s
|
|
474
|
+
when Hash
|
|
475
|
+
active = counter_cache.fetch(:active, true)
|
|
476
|
+
column = counter_cache[:column]&.to_s
|
|
477
|
+
end
|
|
478
|
+
|
|
479
|
+
options[:counter_cache] = { active: active, column: column }
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
options
|
|
447
483
|
end
|
|
448
484
|
end
|
|
449
485
|
|
|
@@ -494,6 +530,17 @@ module ActiveRecord
|
|
|
494
530
|
@foreign_key = nil
|
|
495
531
|
@association_foreign_key = nil
|
|
496
532
|
@association_primary_key = nil
|
|
533
|
+
if options[:query_constraints]
|
|
534
|
+
ActiveRecord.deprecator.warn <<~MSG.squish
|
|
535
|
+
Setting `query_constraints:` option on `#{active_record}.#{macro} :#{name}` is deprecated.
|
|
536
|
+
To maintain current behavior, use the `foreign_key` option instead.
|
|
537
|
+
MSG
|
|
538
|
+
end
|
|
539
|
+
|
|
540
|
+
# If the foreign key is an array, set query constraints options and don't use the foreign key
|
|
541
|
+
if options[:foreign_key].is_a?(Array)
|
|
542
|
+
options[:query_constraints] = options.delete(:foreign_key)
|
|
543
|
+
end
|
|
497
544
|
|
|
498
545
|
ensure_option_not_given_as_class!(:class_name)
|
|
499
546
|
end
|
|
@@ -503,7 +550,9 @@ module ActiveRecord
|
|
|
503
550
|
if polymorphic?
|
|
504
551
|
key = [key, owner._read_attribute(@foreign_type)]
|
|
505
552
|
end
|
|
506
|
-
klass.
|
|
553
|
+
klass.with_connection do |connection|
|
|
554
|
+
klass.cached_find_by_statement(connection, key, &block)
|
|
555
|
+
end
|
|
507
556
|
end
|
|
508
557
|
|
|
509
558
|
def join_table
|
|
@@ -511,10 +560,14 @@ module ActiveRecord
|
|
|
511
560
|
end
|
|
512
561
|
|
|
513
562
|
def foreign_key(infer_from_inverse_of: true)
|
|
514
|
-
@foreign_key ||= if options[:
|
|
563
|
+
@foreign_key ||= if options[:foreign_key]
|
|
564
|
+
if options[:foreign_key].is_a?(Array)
|
|
565
|
+
options[:foreign_key].map { |fk| fk.to_s.freeze }.freeze
|
|
566
|
+
else
|
|
567
|
+
options[:foreign_key].to_s.freeze
|
|
568
|
+
end
|
|
569
|
+
elsif options[:query_constraints]
|
|
515
570
|
options[:query_constraints].map { |fk| fk.to_s.freeze }.freeze
|
|
516
|
-
elsif options[:foreign_key]
|
|
517
|
-
options[:foreign_key].to_s
|
|
518
571
|
else
|
|
519
572
|
derived_fk = derive_foreign_key(infer_from_inverse_of: infer_from_inverse_of)
|
|
520
573
|
|
|
@@ -711,6 +764,10 @@ module ActiveRecord
|
|
|
711
764
|
|
|
712
765
|
begin
|
|
713
766
|
reflection = klass._reflect_on_association(inverse_name)
|
|
767
|
+
if !reflection && active_record.automatically_invert_plural_associations
|
|
768
|
+
plural_inverse_name = ActiveSupport::Inflector.pluralize(inverse_name)
|
|
769
|
+
reflection = klass._reflect_on_association(plural_inverse_name)
|
|
770
|
+
end
|
|
714
771
|
rescue NameError => error
|
|
715
772
|
raise unless error.name.to_s == class_name
|
|
716
773
|
|
|
@@ -720,7 +777,7 @@ module ActiveRecord
|
|
|
720
777
|
end
|
|
721
778
|
|
|
722
779
|
if valid_inverse_reflection?(reflection)
|
|
723
|
-
|
|
780
|
+
reflection.name
|
|
724
781
|
end
|
|
725
782
|
end
|
|
726
783
|
end
|
|
@@ -933,7 +990,7 @@ module ActiveRecord
|
|
|
933
990
|
end
|
|
934
991
|
|
|
935
992
|
def klass
|
|
936
|
-
@klass ||= delegate_reflection.
|
|
993
|
+
@klass ||= delegate_reflection._klass(class_name)
|
|
937
994
|
end
|
|
938
995
|
|
|
939
996
|
# Returns the source of the through reflection. It checks both a singularized
|
|
@@ -954,6 +1011,8 @@ module ActiveRecord
|
|
|
954
1011
|
# # => <ActiveRecord::Reflection::BelongsToReflection: @name=:tag, @active_record=Tagging, @plural_name="tags">
|
|
955
1012
|
#
|
|
956
1013
|
def source_reflection
|
|
1014
|
+
return unless source_reflection_name
|
|
1015
|
+
|
|
957
1016
|
through_reflection.klass._reflect_on_association(source_reflection_name)
|
|
958
1017
|
end
|
|
959
1018
|
|
|
@@ -1111,7 +1170,7 @@ module ActiveRecord
|
|
|
1111
1170
|
end
|
|
1112
1171
|
|
|
1113
1172
|
if parent_reflection.nil?
|
|
1114
|
-
reflections = active_record.
|
|
1173
|
+
reflections = active_record.normalized_reflections.keys
|
|
1115
1174
|
|
|
1116
1175
|
if reflections.index(through_reflection.name) > reflections.index(name)
|
|
1117
1176
|
raise HasManyThroughOrderError.new(active_record.name, self, through_reflection)
|
|
@@ -1180,7 +1239,10 @@ module ActiveRecord
|
|
|
1180
1239
|
end
|
|
1181
1240
|
|
|
1182
1241
|
def join_scopes(table, predicate_builder, klass = self.klass, record = nil) # :nodoc:
|
|
1183
|
-
scopes =
|
|
1242
|
+
scopes = super
|
|
1243
|
+
unless @previous_reflection.through_reflection?
|
|
1244
|
+
scopes += @previous_reflection.join_scopes(table, predicate_builder, klass, record)
|
|
1245
|
+
end
|
|
1184
1246
|
scopes << build_scope(table, predicate_builder, klass).instance_exec(record, &source_type_scope)
|
|
1185
1247
|
end
|
|
1186
1248
|
|
|
@@ -77,13 +77,26 @@ module ActiveRecord
|
|
|
77
77
|
end
|
|
78
78
|
end
|
|
79
79
|
|
|
80
|
-
#
|
|
80
|
+
# Touches records in batches. Returns the total number of rows affected.
|
|
81
|
+
#
|
|
82
|
+
# Person.in_batches.touch_all
|
|
83
|
+
#
|
|
84
|
+
# See Relation#touch_all for details of how each batch is touched.
|
|
85
|
+
def touch_all(...)
|
|
86
|
+
sum do |relation|
|
|
87
|
+
relation.touch_all(...)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Destroys records in batches. Returns the total number of rows affected.
|
|
81
92
|
#
|
|
82
93
|
# Person.where("age < 10").in_batches.destroy_all
|
|
83
94
|
#
|
|
84
95
|
# See Relation#destroy_all for details of how each batch is destroyed.
|
|
85
96
|
def destroy_all
|
|
86
|
-
|
|
97
|
+
sum do |relation|
|
|
98
|
+
relation.destroy_all.count(&:destroyed?)
|
|
99
|
+
end
|
|
87
100
|
end
|
|
88
101
|
|
|
89
102
|
# Yields an ActiveRecord::Relation object for each batch of records.
|
|
@@ -241,14 +241,14 @@ module ActiveRecord
|
|
|
241
241
|
raise ArgumentError, ":order must be :asc or :desc or an array consisting of :asc or :desc, got #{order.inspect}"
|
|
242
242
|
end
|
|
243
243
|
|
|
244
|
-
unless block
|
|
245
|
-
return BatchEnumerator.new(of: of, start: start, finish: finish, relation: self, order: order, use_ranges: use_ranges)
|
|
246
|
-
end
|
|
247
|
-
|
|
248
244
|
if arel.orders.present?
|
|
249
245
|
act_on_ignored_order(error_on_ignore)
|
|
250
246
|
end
|
|
251
247
|
|
|
248
|
+
unless block
|
|
249
|
+
return BatchEnumerator.new(of: of, start: start, finish: finish, relation: self, order: order, use_ranges: use_ranges)
|
|
250
|
+
end
|
|
251
|
+
|
|
252
252
|
batch_limit = of
|
|
253
253
|
|
|
254
254
|
if limit_value
|
|
@@ -341,19 +341,25 @@ module ActiveRecord
|
|
|
341
341
|
|
|
342
342
|
if start || finish
|
|
343
343
|
records = records.filter do |record|
|
|
344
|
-
|
|
344
|
+
id = record.id
|
|
345
|
+
|
|
346
|
+
if order == :asc
|
|
347
|
+
(start.nil? || id >= start) && (finish.nil? || id <= finish)
|
|
348
|
+
else
|
|
349
|
+
(start.nil? || id <= start) && (finish.nil? || id >= finish)
|
|
350
|
+
end
|
|
345
351
|
end
|
|
346
352
|
end
|
|
347
353
|
|
|
348
|
-
records
|
|
354
|
+
records.sort_by!(&:id)
|
|
349
355
|
|
|
350
356
|
if order == :desc
|
|
351
357
|
records.reverse!
|
|
352
358
|
end
|
|
353
359
|
|
|
354
|
-
|
|
360
|
+
records.each_slice(batch_limit) do |subrecords|
|
|
355
361
|
subrelation = relation.spawn
|
|
356
|
-
subrelation.load_records(
|
|
362
|
+
subrelation.load_records(subrecords)
|
|
357
363
|
|
|
358
364
|
yield subrelation
|
|
359
365
|
end
|