activerecord 6.0.3.4 → 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 +799 -713
- data/MIT-LICENSE +1 -1
- data/README.rdoc +2 -2
- data/lib/active_record.rb +7 -14
- data/lib/active_record/aggregations.rb +1 -1
- data/lib/active_record/association_relation.rb +22 -14
- data/lib/active_record/associations.rb +114 -11
- data/lib/active_record/associations/alias_tracker.rb +19 -15
- data/lib/active_record/associations/association.rb +44 -28
- 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 -1
- 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 +19 -6
- data/lib/active_record/associations/collection_proxy.rb +13 -5
- data/lib/active_record/associations/foreign_association.rb +13 -0
- data/lib/active_record/associations/has_many_association.rb +24 -2
- 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.rb +72 -50
- 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/preloader.rb +11 -5
- 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/singular_association.rb +1 -1
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/attribute_assignment.rb +10 -8
- data/lib/active_record/attribute_methods.rb +64 -54
- data/lib/active_record/attribute_methods/before_type_cast.rb +13 -9
- data/lib/active_record/attribute_methods/dirty.rb +1 -11
- data/lib/active_record/attribute_methods/primary_key.rb +6 -2
- data/lib/active_record/attribute_methods/query.rb +3 -6
- data/lib/active_record/attribute_methods/read.rb +8 -11
- data/lib/active_record/attribute_methods/serialization.rb +11 -5
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -13
- data/lib/active_record/attribute_methods/write.rb +12 -20
- data/lib/active_record/attributes.rb +32 -7
- data/lib/active_record/autosave_association.rb +57 -40
- data/lib/active_record/base.rb +2 -14
- data/lib/active_record/callbacks.rb +152 -22
- data/lib/active_record/coders/yaml_column.rb +1 -1
- data/lib/active_record/connection_adapters.rb +50 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +191 -134
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -44
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +65 -22
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -7
- 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 +153 -116
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +112 -27
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +224 -85
- data/lib/active_record/connection_adapters/abstract/transaction.rb +80 -32
- data/lib/active_record/connection_adapters/abstract_adapter.rb +54 -71
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +129 -88
- 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/database_statements.rb +23 -25
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +32 -6
- 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 +11 -7
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +31 -12
- 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 +13 -54
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- 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/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +24 -5
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +11 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +5 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +61 -29
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +72 -55
- 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 +31 -6
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +37 -4
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +49 -50
- data/lib/active_record/connection_handling.rb +210 -71
- data/lib/active_record/core.rb +229 -63
- data/lib/active_record/database_configurations.rb +124 -85
- 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 -40
- data/lib/active_record/delegated_type.rb +209 -0
- data/lib/active_record/destroy_association_async_job.rb +36 -0
- data/lib/active_record/enum.rb +40 -16
- data/lib/active_record/errors.rb +47 -12
- data/lib/active_record/explain.rb +9 -4
- 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 -2
- data/lib/active_record/fixtures.rb +54 -8
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +40 -18
- data/lib/active_record/insert_all.rb +35 -6
- 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 -16
- data/lib/active_record/locking/pessimistic.rb +6 -2
- data/lib/active_record/log_subscriber.rb +26 -8
- data/lib/active_record/middleware/database_selector.rb +4 -1
- data/lib/active_record/middleware/database_selector/resolver.rb +5 -0
- data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
- data/lib/active_record/migration.rb +113 -83
- data/lib/active_record/migration/command_recorder.rb +47 -27
- data/lib/active_record/migration/compatibility.rb +67 -17
- data/lib/active_record/model_schema.rb +117 -13
- data/lib/active_record/nested_attributes.rb +2 -3
- data/lib/active_record/no_touching.rb +1 -1
- data/lib/active_record/persistence.rb +50 -45
- data/lib/active_record/query_cache.rb +15 -5
- data/lib/active_record/querying.rb +11 -6
- data/lib/active_record/railtie.rb +64 -44
- data/lib/active_record/railties/databases.rake +266 -95
- data/lib/active_record/readonly_attributes.rb +4 -0
- data/lib/active_record/reflection.rb +71 -57
- data/lib/active_record/relation.rb +96 -67
- data/lib/active_record/relation/batches.rb +38 -31
- data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
- data/lib/active_record/relation/calculations.rb +101 -44
- data/lib/active_record/relation/delegation.rb +2 -1
- data/lib/active_record/relation/finder_methods.rb +45 -15
- data/lib/active_record/relation/from_clause.rb +1 -1
- data/lib/active_record/relation/merger.rb +27 -25
- data/lib/active_record/relation/predicate_builder.rb +57 -33
- 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/query_methods.rb +330 -195
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +8 -7
- data/lib/active_record/relation/where_clause.rb +104 -57
- data/lib/active_record/result.rb +41 -33
- 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/named.rb +6 -17
- 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 +2 -2
- data/lib/active_record/suppressor.rb +2 -2
- data/lib/active_record/table_metadata.rb +39 -51
- data/lib/active_record/tasks/database_tasks.rb +139 -113
- data/lib/active_record/tasks/mysql_database_tasks.rb +34 -35
- data/lib/active_record/tasks/postgresql_database_tasks.rb +24 -26
- data/lib/active_record/tasks/sqlite_database_tasks.rb +13 -9
- data/lib/active_record/test_databases.rb +5 -4
- data/lib/active_record/test_fixtures.rb +37 -16
- data/lib/active_record/timestamp.rb +4 -6
- data/lib/active_record/touch_later.rb +21 -21
- data/lib/active_record/transactions.rb +15 -64
- data/lib/active_record/type.rb +8 -1
- data/lib/active_record/type/serialized.rb +6 -2
- data/lib/active_record/type/time.rb +10 -0
- 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.rb +1 -0
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/uniqueness.rb +24 -4
- data/lib/arel.rb +5 -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.rb +3 -1
- 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/predications.rb +12 -18
- data/lib/arel/select_manager.rb +1 -2
- data/lib/arel/table.rb +13 -5
- data/lib/arel/visitors.rb +0 -7
- data/lib/arel/visitors/dot.rb +14 -2
- data/lib/arel/visitors/mysql.rb +11 -1
- data/lib/arel/visitors/postgresql.rb +15 -4
- data/lib/arel/visitors/to_sql.rb +89 -78
- data/lib/rails/generators/active_record/migration.rb +6 -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 +3 -3
- data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- metadata +27 -28
- data/lib/active_record/advisory_lock_base.rb +0 -18
- data/lib/active_record/attribute_decorators.rb +0 -88
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -296
- 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 -203
- data/lib/arel/visitors/ibm_db.rb +0 -34
- data/lib/arel/visitors/informix.rb +0 -62
- data/lib/arel/visitors/mssql.rb +0 -156
- data/lib/arel/visitors/oracle.rb +0 -158
- data/lib/arel/visitors/oracle12.rb +0 -65
- data/lib/arel/visitors/where_sql.rb +0 -22
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "active_support/core_ext/string/filters"
|
4
|
-
require "concurrent/map"
|
5
4
|
|
6
5
|
module ActiveRecord
|
7
6
|
# = Active Record Reflection
|
@@ -163,13 +162,7 @@ module ActiveRecord
|
|
163
162
|
# <tt>composed_of :balance, class_name: 'Money'</tt> returns <tt>'Money'</tt>
|
164
163
|
# <tt>has_many :clients</tt> returns <tt>'Client'</tt>
|
165
164
|
def class_name
|
166
|
-
@class_name ||= (options[:class_name] || derive_class_name)
|
167
|
-
end
|
168
|
-
|
169
|
-
JoinKeys = Struct.new(:key, :foreign_key) # :nodoc:
|
170
|
-
|
171
|
-
def join_keys
|
172
|
-
@join_keys ||= get_join_keys(klass)
|
165
|
+
@class_name ||= -(options[:class_name]&.to_s || derive_class_name)
|
173
166
|
end
|
174
167
|
|
175
168
|
# Returns a list of scopes that should be applied for this Reflection
|
@@ -189,10 +182,10 @@ module ActiveRecord
|
|
189
182
|
|
190
183
|
scope_chain_items.inject(klass_scope, &:merge!)
|
191
184
|
|
192
|
-
|
193
|
-
foreign_key =
|
185
|
+
primary_key = join_primary_key
|
186
|
+
foreign_key = join_foreign_key
|
194
187
|
|
195
|
-
klass_scope.where!(table[
|
188
|
+
klass_scope.where!(table[primary_key].eq(foreign_table[foreign_key]))
|
196
189
|
|
197
190
|
if klass.finder_needs_type_condition?
|
198
191
|
klass_scope.where!(klass.send(:type_condition, table))
|
@@ -201,9 +194,9 @@ module ActiveRecord
|
|
201
194
|
klass_scope
|
202
195
|
end
|
203
196
|
|
204
|
-
def join_scopes(table, predicate_builder) # :nodoc:
|
197
|
+
def join_scopes(table, predicate_builder, klass = self.klass) # :nodoc:
|
205
198
|
if scope
|
206
|
-
[scope_for(build_scope(table, predicate_builder))]
|
199
|
+
[scope_for(build_scope(table, predicate_builder, klass))]
|
207
200
|
else
|
208
201
|
[]
|
209
202
|
end
|
@@ -219,14 +212,14 @@ module ActiveRecord
|
|
219
212
|
end
|
220
213
|
|
221
214
|
def counter_cache_column
|
222
|
-
if belongs_to?
|
215
|
+
@counter_cache_column ||= if belongs_to?
|
223
216
|
if options[:counter_cache] == true
|
224
|
-
"#{active_record.name.demodulize.underscore.pluralize}_count"
|
217
|
+
-"#{active_record.name.demodulize.underscore.pluralize}_count"
|
225
218
|
elsif options[:counter_cache]
|
226
|
-
options[:counter_cache].to_s
|
219
|
+
-options[:counter_cache].to_s
|
227
220
|
end
|
228
221
|
else
|
229
|
-
options[:counter_cache]
|
222
|
+
-(options[:counter_cache]&.to_s || "#{name}_count")
|
230
223
|
end
|
231
224
|
end
|
232
225
|
|
@@ -273,7 +266,7 @@ module ActiveRecord
|
|
273
266
|
def has_cached_counter?
|
274
267
|
options[:counter_cache] ||
|
275
268
|
inverse_which_updates_counter_cache && inverse_which_updates_counter_cache.options[:counter_cache] &&
|
276
|
-
|
269
|
+
active_record.has_attribute?(counter_cache_column)
|
277
270
|
end
|
278
271
|
|
279
272
|
def counter_must_be_updated_by_has_many?
|
@@ -288,11 +281,7 @@ module ActiveRecord
|
|
288
281
|
collect_join_chain
|
289
282
|
end
|
290
283
|
|
291
|
-
def
|
292
|
-
JoinKeys.new(join_primary_key(association_klass), join_foreign_key)
|
293
|
-
end
|
294
|
-
|
295
|
-
def build_scope(table, predicate_builder = predicate_builder(table))
|
284
|
+
def build_scope(table, predicate_builder = predicate_builder(table), klass = self.klass)
|
296
285
|
Relation.create(
|
297
286
|
klass,
|
298
287
|
table: table,
|
@@ -300,12 +289,8 @@ module ActiveRecord
|
|
300
289
|
)
|
301
290
|
end
|
302
291
|
|
303
|
-
def
|
304
|
-
|
305
|
-
end
|
306
|
-
|
307
|
-
def join_foreign_key
|
308
|
-
active_record_primary_key
|
292
|
+
def strict_loading?
|
293
|
+
options[:strict_loading]
|
309
294
|
end
|
310
295
|
|
311
296
|
protected
|
@@ -429,22 +414,21 @@ module ActiveRecord
|
|
429
414
|
|
430
415
|
def initialize(name, scope, options, active_record)
|
431
416
|
super
|
432
|
-
@type
|
433
|
-
@foreign_type =
|
417
|
+
@type = -(options[:foreign_type]&.to_s || "#{options[:as]}_type") if options[:as]
|
418
|
+
@foreign_type = -(options[:foreign_type]&.to_s || "#{name}_type") if options[:polymorphic]
|
434
419
|
@constructable = calculate_constructable(macro, options)
|
435
|
-
@association_scope_cache = Concurrent::Map.new
|
436
420
|
|
437
421
|
if options[:class_name] && options[:class_name].class == Class
|
438
422
|
raise ArgumentError, "A class was passed to `:class_name` but we are expecting a string."
|
439
423
|
end
|
440
424
|
end
|
441
425
|
|
442
|
-
def association_scope_cache(
|
443
|
-
key =
|
426
|
+
def association_scope_cache(klass, owner, &block)
|
427
|
+
key = self
|
444
428
|
if polymorphic?
|
445
429
|
key = [key, owner._read_attribute(@foreign_type)]
|
446
430
|
end
|
447
|
-
|
431
|
+
klass.cached_find_by_statement(key, &block)
|
448
432
|
end
|
449
433
|
|
450
434
|
def constructable? # :nodoc:
|
@@ -452,24 +436,31 @@ module ActiveRecord
|
|
452
436
|
end
|
453
437
|
|
454
438
|
def join_table
|
455
|
-
@join_table ||= options[:join_table] || derive_join_table
|
439
|
+
@join_table ||= -(options[:join_table]&.to_s || derive_join_table)
|
456
440
|
end
|
457
441
|
|
458
442
|
def foreign_key
|
459
|
-
@foreign_key ||= options[:foreign_key] || derive_foreign_key
|
443
|
+
@foreign_key ||= -(options[:foreign_key]&.to_s || derive_foreign_key)
|
460
444
|
end
|
461
445
|
|
462
446
|
def association_foreign_key
|
463
|
-
@association_foreign_key ||= options[:association_foreign_key] || class_name.foreign_key
|
447
|
+
@association_foreign_key ||= -(options[:association_foreign_key]&.to_s || class_name.foreign_key)
|
464
448
|
end
|
465
449
|
|
466
|
-
# klass option is necessary to support loading polymorphic associations
|
467
450
|
def association_primary_key(klass = nil)
|
468
|
-
|
451
|
+
primary_key(klass || self.klass)
|
469
452
|
end
|
470
453
|
|
471
454
|
def active_record_primary_key
|
472
|
-
@active_record_primary_key ||= options[:primary_key] || primary_key(active_record)
|
455
|
+
@active_record_primary_key ||= -(options[:primary_key]&.to_s || primary_key(active_record))
|
456
|
+
end
|
457
|
+
|
458
|
+
def join_primary_key(klass = nil)
|
459
|
+
foreign_key
|
460
|
+
end
|
461
|
+
|
462
|
+
def join_foreign_key
|
463
|
+
active_record_primary_key
|
473
464
|
end
|
474
465
|
|
475
466
|
def check_validity!
|
@@ -510,7 +501,7 @@ module ActiveRecord
|
|
510
501
|
# This is for clearing cache on the reflection. Useful for tests that need to compare
|
511
502
|
# SQL queries on associations.
|
512
503
|
def clear_association_scope_cache # :nodoc:
|
513
|
-
|
504
|
+
klass.initialize_find_by_cache
|
514
505
|
end
|
515
506
|
|
516
507
|
def nested?
|
@@ -632,6 +623,7 @@ module ActiveRecord
|
|
632
623
|
# with the current reflection's klass name.
|
633
624
|
def valid_inverse_reflection?(reflection)
|
634
625
|
reflection &&
|
626
|
+
foreign_key == reflection.foreign_key &&
|
635
627
|
klass <= reflection.active_record &&
|
636
628
|
can_find_inverse_of_automatically?(reflection)
|
637
629
|
end
|
@@ -685,10 +677,6 @@ module ActiveRecord
|
|
685
677
|
Associations::HasManyAssociation
|
686
678
|
end
|
687
679
|
end
|
688
|
-
|
689
|
-
def association_primary_key(klass = nil)
|
690
|
-
primary_key(klass || self.klass)
|
691
|
-
end
|
692
680
|
end
|
693
681
|
|
694
682
|
class HasOneReflection < AssociationReflection # :nodoc:
|
@@ -723,6 +711,15 @@ module ActiveRecord
|
|
723
711
|
end
|
724
712
|
end
|
725
713
|
|
714
|
+
# klass option is necessary to support loading polymorphic associations
|
715
|
+
def association_primary_key(klass = nil)
|
716
|
+
if primary_key = options[:primary_key]
|
717
|
+
@association_primary_key ||= -primary_key.to_s
|
718
|
+
else
|
719
|
+
primary_key(klass || self.klass)
|
720
|
+
end
|
721
|
+
end
|
722
|
+
|
726
723
|
def join_primary_key(klass = nil)
|
727
724
|
polymorphic? ? association_primary_key(klass) : association_primary_key
|
728
725
|
end
|
@@ -731,6 +728,10 @@ module ActiveRecord
|
|
731
728
|
foreign_key
|
732
729
|
end
|
733
730
|
|
731
|
+
def join_foreign_type
|
732
|
+
foreign_type
|
733
|
+
end
|
734
|
+
|
734
735
|
private
|
735
736
|
def can_find_inverse_of_automatically?(_)
|
736
737
|
!polymorphic? && super
|
@@ -752,8 +753,8 @@ module ActiveRecord
|
|
752
753
|
# Holds all the metadata about a :through association as it was specified
|
753
754
|
# in the Active Record class.
|
754
755
|
class ThroughReflection < AbstractReflection #:nodoc:
|
755
|
-
delegate :foreign_key, :foreign_type, :association_foreign_key, :join_id_for,
|
756
|
-
:active_record_primary_key, :
|
756
|
+
delegate :foreign_key, :foreign_type, :association_foreign_key, :join_id_for, :type,
|
757
|
+
:active_record_primary_key, :join_foreign_key, to: :source_reflection
|
757
758
|
|
758
759
|
def initialize(delegate_reflection)
|
759
760
|
@delegate_reflection = delegate_reflection
|
@@ -839,8 +840,8 @@ module ActiveRecord
|
|
839
840
|
source_reflection.scopes + super
|
840
841
|
end
|
841
842
|
|
842
|
-
def join_scopes(table, predicate_builder) # :nodoc:
|
843
|
-
source_reflection.join_scopes(table, predicate_builder) + super
|
843
|
+
def join_scopes(table, predicate_builder, klass = self.klass) # :nodoc:
|
844
|
+
source_reflection.join_scopes(table, predicate_builder, klass) + super
|
844
845
|
end
|
845
846
|
|
846
847
|
def has_scope?
|
@@ -860,7 +861,15 @@ module ActiveRecord
|
|
860
861
|
def association_primary_key(klass = nil)
|
861
862
|
# Get the "actual" source reflection if the immediate source reflection has a
|
862
863
|
# source reflection itself
|
863
|
-
actual_source_reflection.options[:primary_key]
|
864
|
+
if primary_key = actual_source_reflection.options[:primary_key]
|
865
|
+
@association_primary_key ||= -primary_key.to_s
|
866
|
+
else
|
867
|
+
primary_key(klass || self.klass)
|
868
|
+
end
|
869
|
+
end
|
870
|
+
|
871
|
+
def join_primary_key(klass = self.klass)
|
872
|
+
source_reflection.join_primary_key(klass)
|
864
873
|
end
|
865
874
|
|
866
875
|
# Gets an array of possible <tt>:through</tt> source reflection names in both singular and plural form.
|
@@ -909,7 +918,7 @@ module ActiveRecord
|
|
909
918
|
|
910
919
|
def check_validity!
|
911
920
|
if through_reflection.nil?
|
912
|
-
raise HasManyThroughAssociationNotFoundError.new(active_record
|
921
|
+
raise HasManyThroughAssociationNotFoundError.new(active_record, self)
|
913
922
|
end
|
914
923
|
|
915
924
|
if through_reflection.polymorphic?
|
@@ -996,16 +1005,17 @@ module ActiveRecord
|
|
996
1005
|
end
|
997
1006
|
|
998
1007
|
class PolymorphicReflection < AbstractReflection # :nodoc:
|
999
|
-
delegate :klass, :scope, :plural_name, :type, :
|
1008
|
+
delegate :klass, :scope, :plural_name, :type, :join_primary_key, :join_foreign_key,
|
1009
|
+
:name, :scope_for, to: :@reflection
|
1000
1010
|
|
1001
1011
|
def initialize(reflection, previous_reflection)
|
1002
1012
|
@reflection = reflection
|
1003
1013
|
@previous_reflection = previous_reflection
|
1004
1014
|
end
|
1005
1015
|
|
1006
|
-
def join_scopes(table, predicate_builder) # :nodoc:
|
1016
|
+
def join_scopes(table, predicate_builder, klass = self.klass) # :nodoc:
|
1007
1017
|
scopes = @previous_reflection.join_scopes(table, predicate_builder) + super
|
1008
|
-
scopes << build_scope(table, predicate_builder).instance_exec(nil, &source_type_scope)
|
1018
|
+
scopes << build_scope(table, predicate_builder, klass).instance_exec(nil, &source_type_scope)
|
1009
1019
|
end
|
1010
1020
|
|
1011
1021
|
def constraints
|
@@ -1021,7 +1031,7 @@ module ActiveRecord
|
|
1021
1031
|
end
|
1022
1032
|
|
1023
1033
|
class RuntimeReflection < AbstractReflection # :nodoc:
|
1024
|
-
delegate :scope, :type, :constraints, :
|
1034
|
+
delegate :scope, :type, :constraints, :join_foreign_key, to: :@reflection
|
1025
1035
|
|
1026
1036
|
def initialize(reflection, association)
|
1027
1037
|
@reflection = reflection
|
@@ -1033,7 +1043,11 @@ module ActiveRecord
|
|
1033
1043
|
end
|
1034
1044
|
|
1035
1045
|
def aliased_table
|
1036
|
-
|
1046
|
+
klass.arel_table
|
1047
|
+
end
|
1048
|
+
|
1049
|
+
def join_primary_key(klass = self.klass)
|
1050
|
+
@reflection.join_primary_key(klass)
|
1037
1051
|
end
|
1038
1052
|
|
1039
1053
|
def all_includes; yield; end
|
@@ -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
|
@@ -407,9 +406,9 @@ module ActiveRecord
|
|
407
406
|
already_in_scope? ? yield : _scoping(self) { yield }
|
408
407
|
end
|
409
408
|
|
410
|
-
def _exec_scope(
|
409
|
+
def _exec_scope(*args, &block) # :nodoc:
|
411
410
|
@delegate_to_klass = true
|
412
|
-
_scoping(
|
411
|
+
_scoping(nil) { instance_exec(*args, &block) || self }
|
413
412
|
ensure
|
414
413
|
@delegate_to_klass = false
|
415
414
|
end
|
@@ -417,7 +416,7 @@ module ActiveRecord
|
|
417
416
|
# Updates all records in the current relation with details given. This method constructs a single SQL UPDATE
|
418
417
|
# statement and sends it straight to the database. It does not instantiate the involved models and it does not
|
419
418
|
# trigger Active Record callbacks or validations. However, values passed to #update_all will still go through
|
420
|
-
# Active Record's normal type casting and serialization.
|
419
|
+
# Active Record's normal type casting and serialization. Returns the number of rows affected.
|
421
420
|
#
|
422
421
|
# Note: As Active Record callbacks are not triggered, this method will not automatically update +updated_at+/+updated_on+ columns.
|
423
422
|
#
|
@@ -448,7 +447,7 @@ module ActiveRecord
|
|
448
447
|
|
449
448
|
stmt = Arel::UpdateManager.new
|
450
449
|
stmt.table(arel.join_sources.empty? ? table : arel.source)
|
451
|
-
stmt.key =
|
450
|
+
stmt.key = table[primary_key]
|
452
451
|
stmt.take(arel.limit)
|
453
452
|
stmt.offset(arel.offset)
|
454
453
|
stmt.order(*arel.orders)
|
@@ -458,7 +457,7 @@ module ActiveRecord
|
|
458
457
|
if klass.locking_enabled? &&
|
459
458
|
!updates.key?(klass.locking_column) &&
|
460
459
|
!updates.key?(klass.locking_column.to_sym)
|
461
|
-
attr =
|
460
|
+
attr = table[klass.locking_column]
|
462
461
|
updates[attr.name] = _increment_attribute(attr)
|
463
462
|
end
|
464
463
|
stmt.set _substitute_values(updates)
|
@@ -477,12 +476,24 @@ module ActiveRecord
|
|
477
476
|
end
|
478
477
|
end
|
479
478
|
|
480
|
-
|
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)
|
481
492
|
touch = counters.delete(:touch)
|
482
493
|
|
483
494
|
updates = {}
|
484
495
|
counters.each do |counter_name, value|
|
485
|
-
attr =
|
496
|
+
attr = table[counter_name]
|
486
497
|
updates[attr.name] = _increment_attribute(attr, value)
|
487
498
|
end
|
488
499
|
|
@@ -497,8 +508,8 @@ module ActiveRecord
|
|
497
508
|
update_all updates
|
498
509
|
end
|
499
510
|
|
500
|
-
# Touches all records in the current relation
|
501
|
-
#
|
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.
|
502
513
|
# This method can be passed attribute names and an optional time argument.
|
503
514
|
# If attribute names are passed, they are updated along with +updated_at+/+updated_on+ attributes.
|
504
515
|
# If no time argument is passed, the current time is used as default.
|
@@ -578,7 +589,7 @@ module ActiveRecord
|
|
578
589
|
|
579
590
|
stmt = Arel::DeleteManager.new
|
580
591
|
stmt.from(arel.join_sources.empty? ? table : arel.source)
|
581
|
-
stmt.key =
|
592
|
+
stmt.key = table[primary_key]
|
582
593
|
stmt.take(arel.limit)
|
583
594
|
stmt.offset(arel.offset)
|
584
595
|
stmt.order(*arel.orders)
|
@@ -623,7 +634,10 @@ module ActiveRecord
|
|
623
634
|
#
|
624
635
|
# Post.where(published: true).load # => #<ActiveRecord::Relation>
|
625
636
|
def load(&block)
|
626
|
-
|
637
|
+
unless loaded?
|
638
|
+
@records = exec_queries(&block)
|
639
|
+
@loaded = true
|
640
|
+
end
|
627
641
|
|
628
642
|
self
|
629
643
|
end
|
@@ -636,11 +650,9 @@ module ActiveRecord
|
|
636
650
|
|
637
651
|
def reset
|
638
652
|
@delegate_to_klass = false
|
639
|
-
@_deprecated_scope_source = nil
|
640
653
|
@to_sql = @arel = @loaded = @should_eager_load = nil
|
654
|
+
@offsets = @take = nil
|
641
655
|
@records = [].freeze
|
642
|
-
@offsets = {}
|
643
|
-
@take = nil
|
644
656
|
self
|
645
657
|
end
|
646
658
|
|
@@ -671,7 +683,10 @@ module ActiveRecord
|
|
671
683
|
end
|
672
684
|
|
673
685
|
def scope_for_create
|
674
|
-
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
|
675
690
|
end
|
676
691
|
|
677
692
|
# Returns true if relation needs eager loading.
|
@@ -715,7 +730,7 @@ module ActiveRecord
|
|
715
730
|
end
|
716
731
|
|
717
732
|
def inspect
|
718
|
-
subject = loaded? ? records :
|
733
|
+
subject = loaded? ? records : annotate("loading for inspect")
|
719
734
|
entries = subject.take([limit_value, 11].compact.min).map!(&:inspect)
|
720
735
|
|
721
736
|
entries[10] = "..." if entries.size == 11
|
@@ -732,25 +747,31 @@ module ActiveRecord
|
|
732
747
|
end
|
733
748
|
|
734
749
|
def alias_tracker(joins = [], aliases = nil) # :nodoc:
|
735
|
-
|
736
|
-
|
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
|
737
761
|
end
|
738
762
|
|
739
763
|
def preload_associations(records) # :nodoc:
|
740
764
|
preload = preload_values
|
741
765
|
preload += includes_values unless eager_loading?
|
742
766
|
preloader = nil
|
767
|
+
scope = strict_loading_value ? StrictLoadingScope : nil
|
743
768
|
preload.each do |associations|
|
744
769
|
preloader ||= build_preloader
|
745
|
-
preloader.preload records, associations
|
770
|
+
preloader.preload records, associations, scope
|
746
771
|
end
|
747
772
|
end
|
748
773
|
|
749
|
-
attr_reader :_deprecated_scope_source # :nodoc:
|
750
|
-
|
751
774
|
protected
|
752
|
-
attr_writer :_deprecated_scope_source # :nodoc:
|
753
|
-
|
754
775
|
def load_records(records)
|
755
776
|
@records = records.freeze
|
756
777
|
@loaded = true
|
@@ -762,23 +783,29 @@ module ActiveRecord
|
|
762
783
|
|
763
784
|
private
|
764
785
|
def already_in_scope?
|
765
|
-
@delegate_to_klass &&
|
766
|
-
scope = klass.current_scope(true)
|
767
|
-
scope && !scope._deprecated_scope_source
|
768
|
-
end
|
769
|
-
end
|
770
|
-
|
771
|
-
def _deprecated_spawn(name)
|
772
|
-
spawn.tap { |scope| scope._deprecated_scope_source = name }
|
786
|
+
@delegate_to_klass && klass.current_scope(true)
|
773
787
|
end
|
774
788
|
|
775
|
-
def
|
789
|
+
def current_scope_restoring_block(&block)
|
790
|
+
current_scope = klass.current_scope(true)
|
776
791
|
-> record do
|
777
|
-
klass.current_scope =
|
792
|
+
klass.current_scope = current_scope
|
778
793
|
yield record if block_given?
|
779
794
|
end
|
780
795
|
end
|
781
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
|
+
|
782
809
|
def _scoping(scope)
|
783
810
|
previous, klass.current_scope = klass.current_scope(true), scope
|
784
811
|
yield
|
@@ -788,7 +815,7 @@ module ActiveRecord
|
|
788
815
|
|
789
816
|
def _substitute_values(values)
|
790
817
|
values.map do |name, value|
|
791
|
-
attr =
|
818
|
+
attr = table[name]
|
792
819
|
unless Arel.arel_node?(value)
|
793
820
|
type = klass.type_for_attribute(attr.name)
|
794
821
|
value = predicate_builder.build_bind_attribute(attr.name, type.cast(value))
|
@@ -806,27 +833,29 @@ module ActiveRecord
|
|
806
833
|
|
807
834
|
def exec_queries(&block)
|
808
835
|
skip_query_cache_if_necessary do
|
809
|
-
|
810
|
-
if
|
836
|
+
records =
|
837
|
+
if where_clause.contradiction?
|
838
|
+
[]
|
839
|
+
elsif eager_loading?
|
811
840
|
apply_join_dependency do |relation, join_dependency|
|
812
841
|
if relation.null_relation?
|
813
842
|
[]
|
814
843
|
else
|
815
844
|
relation = join_dependency.apply_column_aliases(relation)
|
816
845
|
rows = connection.select_all(relation.arel, "SQL")
|
817
|
-
join_dependency.instantiate(rows, &block)
|
846
|
+
join_dependency.instantiate(rows, strict_loading_value, &block)
|
818
847
|
end.freeze
|
819
848
|
end
|
820
849
|
else
|
821
850
|
klass.find_by_sql(arel, &block).freeze
|
822
851
|
end
|
823
852
|
|
824
|
-
preload_associations(
|
853
|
+
preload_associations(records) unless skip_preloading_value
|
825
854
|
|
826
|
-
|
855
|
+
records.each(&:readonly!) if readonly_value
|
856
|
+
records.each(&:strict_loading!) if strict_loading_value
|
827
857
|
|
828
|
-
|
829
|
-
@records
|
858
|
+
records
|
830
859
|
end
|
831
860
|
end
|
832
861
|
|
@@ -845,27 +874,27 @@ module ActiveRecord
|
|
845
874
|
end
|
846
875
|
|
847
876
|
def references_eager_loaded_tables?
|
848
|
-
joined_tables =
|
877
|
+
joined_tables = build_joins([]).flat_map do |join|
|
849
878
|
if join.is_a?(Arel::Nodes::StringJoin)
|
850
879
|
tables_in_string(join.left)
|
851
880
|
else
|
852
|
-
|
881
|
+
join.left.name
|
853
882
|
end
|
854
883
|
end
|
855
884
|
|
856
|
-
joined_tables
|
885
|
+
joined_tables << table.name
|
857
886
|
|
858
887
|
# always convert table names to downcase as in Oracle quoted table names are in uppercase
|
859
|
-
joined_tables
|
888
|
+
joined_tables.map!(&:downcase)
|
860
889
|
|
861
|
-
(references_values - joined_tables).
|
890
|
+
!(references_values.map(&:to_s) - joined_tables).empty?
|
862
891
|
end
|
863
892
|
|
864
893
|
def tables_in_string(string)
|
865
894
|
return [] if string.blank?
|
866
895
|
# always convert table names to downcase as in Oracle quoted table names are in uppercase
|
867
896
|
# ignore raw_sql_ that is used by Oracle adapter as alias for limit/offset subqueries
|
868
|
-
string.scan(/
|
897
|
+
string.scan(/[a-zA-Z_][.\w]+(?=.?\.)/).map!(&:downcase) - ["raw_sql_"]
|
869
898
|
end
|
870
899
|
end
|
871
900
|
end
|