activerecord 6.0.0 → 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 +872 -582
- data/MIT-LICENSE +1 -1
- data/README.rdoc +3 -3
- data/lib/active_record.rb +7 -13
- data/lib/active_record/aggregations.rb +1 -2
- data/lib/active_record/association_relation.rb +22 -12
- data/lib/active_record/associations.rb +116 -13
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +49 -29
- data/lib/active_record/associations/association_scope.rb +17 -15
- data/lib/active_record/associations/belongs_to_association.rb +15 -5
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +1 -1
- data/lib/active_record/associations/builder/association.rb +9 -3
- data/lib/active_record/associations/builder/belongs_to.rb +10 -7
- data/lib/active_record/associations/builder/collection_association.rb +5 -4
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +0 -3
- data/lib/active_record/associations/builder/has_many.rb +6 -2
- data/lib/active_record/associations/builder/has_one.rb +11 -14
- data/lib/active_record/associations/builder/singular_association.rb +1 -1
- data/lib/active_record/associations/collection_association.rb +25 -8
- data/lib/active_record/associations/collection_proxy.rb +14 -7
- data/lib/active_record/associations/foreign_association.rb +13 -0
- data/lib/active_record/associations/has_many_association.rb +24 -3
- data/lib/active_record/associations/has_many_through_association.rb +10 -4
- data/lib/active_record/associations/has_one_association.rb +15 -1
- data/lib/active_record/associations/join_dependency.rb +77 -42
- 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 +13 -8
- 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 -9
- data/lib/active_record/attribute_methods.rb +64 -54
- data/lib/active_record/attribute_methods/before_type_cast.rb +13 -10
- data/lib/active_record/attribute_methods/dirty.rb +3 -13
- data/lib/active_record/attribute_methods/primary_key.rb +6 -4
- data/lib/active_record/attribute_methods/query.rb +3 -6
- data/lib/active_record/attribute_methods/read.rb +8 -12
- data/lib/active_record/attribute_methods/serialization.rb +11 -6
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -15
- data/lib/active_record/attribute_methods/write.rb +12 -21
- data/lib/active_record/attributes.rb +32 -8
- data/lib/active_record/autosave_association.rb +63 -44
- data/lib/active_record/base.rb +2 -14
- data/lib/active_record/callbacks.rb +153 -24
- data/lib/active_record/coders/yaml_column.rb +1 -2
- data/lib/active_record/connection_adapters.rb +50 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +202 -138
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -44
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +86 -37
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +4 -9
- data/lib/active_record/connection_adapters/abstract/quoting.rb +34 -34
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +152 -116
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +137 -52
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +263 -107
- data/lib/active_record/connection_adapters/abstract/transaction.rb +82 -35
- data/lib/active_record/connection_adapters/abstract_adapter.rb +74 -76
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +149 -115
- data/lib/active_record/connection_adapters/column.rb +15 -1
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +31 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +30 -36
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
- data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +32 -7
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +8 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +17 -13
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +31 -13
- data/lib/active_record/connection_adapters/pool_config.rb +63 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +43 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +24 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +21 -56
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +10 -2
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -3
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -3
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +24 -6
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +11 -2
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +7 -3
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +72 -54
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +81 -57
- data/lib/active_record/connection_adapters/schema_cache.rb +98 -15
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +10 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +38 -12
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +1 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +38 -5
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +61 -57
- data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
- data/lib/active_record/connection_handling.rb +211 -81
- data/lib/active_record/core.rb +237 -69
- data/lib/active_record/counter_cache.rb +4 -1
- 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 -41
- data/lib/active_record/delegated_type.rb +209 -0
- data/lib/active_record/destroy_association_async_job.rb +36 -0
- data/lib/active_record/dynamic_matchers.rb +2 -3
- data/lib/active_record/enum.rb +40 -16
- data/lib/active_record/errors.rb +47 -12
- data/lib/active_record/explain.rb +9 -5
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +10 -17
- data/lib/active_record/fixture_set/model_metadata.rb +1 -2
- data/lib/active_record/fixture_set/render_context.rb +1 -1
- data/lib/active_record/fixture_set/table_row.rb +2 -3
- data/lib/active_record/fixture_set/table_rows.rb +0 -1
- data/lib/active_record/fixtures.rb +54 -11
- data/lib/active_record/gem_version.rb +1 -1
- data/lib/active_record/inheritance.rb +40 -21
- data/lib/active_record/insert_all.rb +39 -10
- data/lib/active_record/integration.rb +3 -5
- data/lib/active_record/internal_metadata.rb +16 -7
- data/lib/active_record/legacy_yaml_adapter.rb +7 -3
- data/lib/active_record/locking/optimistic.rb +22 -17
- data/lib/active_record/locking/pessimistic.rb +6 -2
- data/lib/active_record/log_subscriber.rb +27 -9
- data/lib/active_record/middleware/database_selector.rb +4 -2
- data/lib/active_record/middleware/database_selector/resolver.rb +14 -14
- data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
- data/lib/active_record/migration.rb +114 -84
- data/lib/active_record/migration/command_recorder.rb +53 -45
- data/lib/active_record/migration/compatibility.rb +70 -20
- data/lib/active_record/migration/join_table.rb +0 -1
- data/lib/active_record/model_schema.rb +120 -15
- data/lib/active_record/nested_attributes.rb +2 -5
- data/lib/active_record/no_touching.rb +1 -1
- data/lib/active_record/null_relation.rb +0 -1
- data/lib/active_record/persistence.rb +50 -46
- data/lib/active_record/query_cache.rb +15 -5
- data/lib/active_record/querying.rb +12 -7
- data/lib/active_record/railtie.rb +65 -45
- data/lib/active_record/railties/databases.rake +267 -93
- data/lib/active_record/readonly_attributes.rb +4 -0
- data/lib/active_record/reflection.rb +77 -63
- data/lib/active_record/relation.rb +108 -67
- data/lib/active_record/relation/batches.rb +38 -32
- data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
- data/lib/active_record/relation/calculations.rb +102 -45
- data/lib/active_record/relation/delegation.rb +9 -7
- data/lib/active_record/relation/finder_methods.rb +55 -17
- data/lib/active_record/relation/from_clause.rb +5 -1
- data/lib/active_record/relation/merger.rb +27 -26
- data/lib/active_record/relation/predicate_builder.rb +55 -35
- 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 +340 -180
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +8 -8
- data/lib/active_record/relation/where_clause.rb +104 -58
- data/lib/active_record/result.rb +41 -34
- data/lib/active_record/runtime_registry.rb +2 -2
- data/lib/active_record/sanitization.rb +6 -17
- data/lib/active_record/schema_dumper.rb +34 -4
- data/lib/active_record/schema_migration.rb +2 -8
- data/lib/active_record/scoping.rb +0 -1
- data/lib/active_record/scoping/default.rb +0 -1
- data/lib/active_record/scoping/named.rb +7 -18
- data/lib/active_record/secure_token.rb +16 -8
- data/lib/active_record/serialization.rb +5 -3
- data/lib/active_record/signed_id.rb +116 -0
- data/lib/active_record/statement_cache.rb +20 -4
- data/lib/active_record/store.rb +3 -3
- data/lib/active_record/suppressor.rb +2 -2
- data/lib/active_record/table_metadata.rb +39 -36
- data/lib/active_record/tasks/database_tasks.rb +139 -113
- data/lib/active_record/tasks/mysql_database_tasks.rb +34 -36
- data/lib/active_record/tasks/postgresql_database_tasks.rb +24 -27
- data/lib/active_record/tasks/sqlite_database_tasks.rb +13 -10
- data/lib/active_record/test_databases.rb +5 -4
- data/lib/active_record/test_fixtures.rb +38 -16
- data/lib/active_record/timestamp.rb +4 -7
- data/lib/active_record/touch_later.rb +20 -21
- data/lib/active_record/transactions.rb +22 -71
- data/lib/active_record/type.rb +8 -2
- data/lib/active_record/type/adapter_specific_registry.rb +2 -5
- data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
- data/lib/active_record/type/serialized.rb +6 -3
- data/lib/active_record/type/time.rb +10 -0
- data/lib/active_record/type/type_map.rb +0 -1
- data/lib/active_record/type/unsigned_integer.rb +0 -1
- data/lib/active_record/type_caster/connection.rb +0 -1
- data/lib/active_record/type_caster/map.rb +8 -5
- data/lib/active_record/validations.rb +3 -3
- data/lib/active_record/validations/associated.rb +1 -2
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/uniqueness.rb +24 -4
- data/lib/arel.rb +15 -12
- 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 +17 -24
- 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 -3
- data/lib/arel/visitors/mysql.rb +11 -1
- data/lib/arel/visitors/postgresql.rb +15 -5
- data/lib/arel/visitors/sqlite.rb +0 -1
- data/lib/arel/visitors/to_sql.rb +89 -79
- data/lib/arel/visitors/visitor.rb +0 -1
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
- data/lib/rails/generators/active_record/migration.rb +6 -2
- data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +2 -0
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -4
- data/lib/rails/generators/active_record/model/model_generator.rb +38 -2
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- metadata +27 -24
- data/lib/active_record/attribute_decorators.rb +0 -90
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -297
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
- data/lib/active_record/define_callbacks.rb +0 -22
- data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
- data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
- data/lib/active_record/relation/where_clause_factory.rb +0 -33
- data/lib/arel/attributes.rb +0 -22
- data/lib/arel/visitors/depth_first.rb +0 -204
- data/lib/arel/visitors/ibm_db.rb +0 -34
- data/lib/arel/visitors/informix.rb +0 -62
- data/lib/arel/visitors/mssql.rb +0 -157
- data/lib/arel/visitors/oracle.rb +0 -159
- data/lib/arel/visitors/oracle12.rb +0 -66
- data/lib/arel/visitors/where_sql.rb +0 -23
@@ -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
|
@@ -183,25 +176,27 @@ module ActiveRecord
|
|
183
176
|
scope_chain_items = join_scopes(table, predicate_builder)
|
184
177
|
klass_scope = klass_join_scope(table, predicate_builder)
|
185
178
|
|
186
|
-
key = join_keys.key
|
187
|
-
foreign_key = join_keys.foreign_key
|
188
|
-
|
189
|
-
klass_scope.where!(table[key].eq(foreign_table[foreign_key]))
|
190
|
-
|
191
179
|
if type
|
192
180
|
klass_scope.where!(type => foreign_klass.polymorphic_name)
|
193
181
|
end
|
194
182
|
|
183
|
+
scope_chain_items.inject(klass_scope, &:merge!)
|
184
|
+
|
185
|
+
primary_key = join_primary_key
|
186
|
+
foreign_key = join_foreign_key
|
187
|
+
|
188
|
+
klass_scope.where!(table[primary_key].eq(foreign_table[foreign_key]))
|
189
|
+
|
195
190
|
if klass.finder_needs_type_condition?
|
196
191
|
klass_scope.where!(klass.send(:type_condition, table))
|
197
192
|
end
|
198
193
|
|
199
|
-
|
194
|
+
klass_scope
|
200
195
|
end
|
201
196
|
|
202
|
-
def join_scopes(table, predicate_builder) # :nodoc:
|
197
|
+
def join_scopes(table, predicate_builder, klass = self.klass) # :nodoc:
|
203
198
|
if scope
|
204
|
-
[scope_for(build_scope(table, predicate_builder))]
|
199
|
+
[scope_for(build_scope(table, predicate_builder, klass))]
|
205
200
|
else
|
206
201
|
[]
|
207
202
|
end
|
@@ -217,14 +212,14 @@ module ActiveRecord
|
|
217
212
|
end
|
218
213
|
|
219
214
|
def counter_cache_column
|
220
|
-
if belongs_to?
|
215
|
+
@counter_cache_column ||= if belongs_to?
|
221
216
|
if options[:counter_cache] == true
|
222
|
-
"#{active_record.name.demodulize.underscore.pluralize}_count"
|
217
|
+
-"#{active_record.name.demodulize.underscore.pluralize}_count"
|
223
218
|
elsif options[:counter_cache]
|
224
|
-
options[:counter_cache].to_s
|
219
|
+
-options[:counter_cache].to_s
|
225
220
|
end
|
226
221
|
else
|
227
|
-
options[:counter_cache]
|
222
|
+
-(options[:counter_cache]&.to_s || "#{name}_count")
|
228
223
|
end
|
229
224
|
end
|
230
225
|
|
@@ -271,7 +266,7 @@ module ActiveRecord
|
|
271
266
|
def has_cached_counter?
|
272
267
|
options[:counter_cache] ||
|
273
268
|
inverse_which_updates_counter_cache && inverse_which_updates_counter_cache.options[:counter_cache] &&
|
274
|
-
|
269
|
+
active_record.has_attribute?(counter_cache_column)
|
275
270
|
end
|
276
271
|
|
277
272
|
def counter_must_be_updated_by_has_many?
|
@@ -286,11 +281,7 @@ module ActiveRecord
|
|
286
281
|
collect_join_chain
|
287
282
|
end
|
288
283
|
|
289
|
-
def
|
290
|
-
JoinKeys.new(join_primary_key(association_klass), join_foreign_key)
|
291
|
-
end
|
292
|
-
|
293
|
-
def build_scope(table, predicate_builder = predicate_builder(table))
|
284
|
+
def build_scope(table, predicate_builder = predicate_builder(table), klass = self.klass)
|
294
285
|
Relation.create(
|
295
286
|
klass,
|
296
287
|
table: table,
|
@@ -298,12 +289,8 @@ module ActiveRecord
|
|
298
289
|
)
|
299
290
|
end
|
300
291
|
|
301
|
-
def
|
302
|
-
|
303
|
-
end
|
304
|
-
|
305
|
-
def join_foreign_key
|
306
|
-
active_record_primary_key
|
292
|
+
def strict_loading?
|
293
|
+
options[:strict_loading]
|
307
294
|
end
|
308
295
|
|
309
296
|
protected
|
@@ -427,22 +414,21 @@ module ActiveRecord
|
|
427
414
|
|
428
415
|
def initialize(name, scope, options, active_record)
|
429
416
|
super
|
430
|
-
@type
|
431
|
-
@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]
|
432
419
|
@constructable = calculate_constructable(macro, options)
|
433
|
-
@association_scope_cache = Concurrent::Map.new
|
434
420
|
|
435
421
|
if options[:class_name] && options[:class_name].class == Class
|
436
422
|
raise ArgumentError, "A class was passed to `:class_name` but we are expecting a string."
|
437
423
|
end
|
438
424
|
end
|
439
425
|
|
440
|
-
def association_scope_cache(
|
441
|
-
key =
|
426
|
+
def association_scope_cache(klass, owner, &block)
|
427
|
+
key = self
|
442
428
|
if polymorphic?
|
443
429
|
key = [key, owner._read_attribute(@foreign_type)]
|
444
430
|
end
|
445
|
-
|
431
|
+
klass.cached_find_by_statement(key, &block)
|
446
432
|
end
|
447
433
|
|
448
434
|
def constructable? # :nodoc:
|
@@ -450,24 +436,31 @@ module ActiveRecord
|
|
450
436
|
end
|
451
437
|
|
452
438
|
def join_table
|
453
|
-
@join_table ||= options[:join_table] || derive_join_table
|
439
|
+
@join_table ||= -(options[:join_table]&.to_s || derive_join_table)
|
454
440
|
end
|
455
441
|
|
456
442
|
def foreign_key
|
457
|
-
@foreign_key ||= options[:foreign_key] || derive_foreign_key
|
443
|
+
@foreign_key ||= -(options[:foreign_key]&.to_s || derive_foreign_key)
|
458
444
|
end
|
459
445
|
|
460
446
|
def association_foreign_key
|
461
|
-
@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)
|
462
448
|
end
|
463
449
|
|
464
|
-
# klass option is necessary to support loading polymorphic associations
|
465
450
|
def association_primary_key(klass = nil)
|
466
|
-
|
451
|
+
primary_key(klass || self.klass)
|
467
452
|
end
|
468
453
|
|
469
454
|
def active_record_primary_key
|
470
|
-
@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
|
471
464
|
end
|
472
465
|
|
473
466
|
def check_validity!
|
@@ -508,7 +501,7 @@ module ActiveRecord
|
|
508
501
|
# This is for clearing cache on the reflection. Useful for tests that need to compare
|
509
502
|
# SQL queries on associations.
|
510
503
|
def clear_association_scope_cache # :nodoc:
|
511
|
-
|
504
|
+
klass.initialize_find_by_cache
|
512
505
|
end
|
513
506
|
|
514
507
|
def nested?
|
@@ -590,7 +583,6 @@ module ActiveRecord
|
|
590
583
|
end
|
591
584
|
|
592
585
|
private
|
593
|
-
|
594
586
|
def calculate_constructable(macro, options)
|
595
587
|
true
|
596
588
|
end
|
@@ -620,7 +612,7 @@ module ActiveRecord
|
|
620
612
|
end
|
621
613
|
|
622
614
|
if valid_inverse_reflection?(reflection)
|
623
|
-
|
615
|
+
inverse_name
|
624
616
|
end
|
625
617
|
end
|
626
618
|
end
|
@@ -631,6 +623,7 @@ module ActiveRecord
|
|
631
623
|
# with the current reflection's klass name.
|
632
624
|
def valid_inverse_reflection?(reflection)
|
633
625
|
reflection &&
|
626
|
+
foreign_key == reflection.foreign_key &&
|
634
627
|
klass <= reflection.active_record &&
|
635
628
|
can_find_inverse_of_automatically?(reflection)
|
636
629
|
end
|
@@ -684,10 +677,6 @@ module ActiveRecord
|
|
684
677
|
Associations::HasManyAssociation
|
685
678
|
end
|
686
679
|
end
|
687
|
-
|
688
|
-
def association_primary_key(klass = nil)
|
689
|
-
primary_key(klass || self.klass)
|
690
|
-
end
|
691
680
|
end
|
692
681
|
|
693
682
|
class HasOneReflection < AssociationReflection # :nodoc:
|
@@ -704,7 +693,6 @@ module ActiveRecord
|
|
704
693
|
end
|
705
694
|
|
706
695
|
private
|
707
|
-
|
708
696
|
def calculate_constructable(macro, options)
|
709
697
|
!options[:through]
|
710
698
|
end
|
@@ -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
|
@@ -385,6 +384,15 @@ module ActiveRecord
|
|
385
384
|
end
|
386
385
|
private :compute_cache_version
|
387
386
|
|
387
|
+
# Returns a cache key along with the version.
|
388
|
+
def cache_key_with_version
|
389
|
+
if version = cache_version
|
390
|
+
"#{cache_key}-#{version}"
|
391
|
+
else
|
392
|
+
cache_key
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
388
396
|
# Scope all queries to the current scope.
|
389
397
|
#
|
390
398
|
# Comment.where(post_id: 1).scoping do
|
@@ -398,9 +406,9 @@ module ActiveRecord
|
|
398
406
|
already_in_scope? ? yield : _scoping(self) { yield }
|
399
407
|
end
|
400
408
|
|
401
|
-
def _exec_scope(
|
409
|
+
def _exec_scope(*args, &block) # :nodoc:
|
402
410
|
@delegate_to_klass = true
|
403
|
-
_scoping(
|
411
|
+
_scoping(nil) { instance_exec(*args, &block) || self }
|
404
412
|
ensure
|
405
413
|
@delegate_to_klass = false
|
406
414
|
end
|
@@ -408,7 +416,7 @@ module ActiveRecord
|
|
408
416
|
# Updates all records in the current relation with details given. This method constructs a single SQL UPDATE
|
409
417
|
# statement and sends it straight to the database. It does not instantiate the involved models and it does not
|
410
418
|
# trigger Active Record callbacks or validations. However, values passed to #update_all will still go through
|
411
|
-
# Active Record's normal type casting and serialization.
|
419
|
+
# Active Record's normal type casting and serialization. Returns the number of rows affected.
|
412
420
|
#
|
413
421
|
# Note: As Active Record callbacks are not triggered, this method will not automatically update +updated_at+/+updated_on+ columns.
|
414
422
|
#
|
@@ -439,7 +447,7 @@ module ActiveRecord
|
|
439
447
|
|
440
448
|
stmt = Arel::UpdateManager.new
|
441
449
|
stmt.table(arel.join_sources.empty? ? table : arel.source)
|
442
|
-
stmt.key =
|
450
|
+
stmt.key = table[primary_key]
|
443
451
|
stmt.take(arel.limit)
|
444
452
|
stmt.offset(arel.offset)
|
445
453
|
stmt.order(*arel.orders)
|
@@ -449,7 +457,7 @@ module ActiveRecord
|
|
449
457
|
if klass.locking_enabled? &&
|
450
458
|
!updates.key?(klass.locking_column) &&
|
451
459
|
!updates.key?(klass.locking_column.to_sym)
|
452
|
-
attr =
|
460
|
+
attr = table[klass.locking_column]
|
453
461
|
updates[attr.name] = _increment_attribute(attr)
|
454
462
|
end
|
455
463
|
stmt.set _substitute_values(updates)
|
@@ -468,26 +476,40 @@ module ActiveRecord
|
|
468
476
|
end
|
469
477
|
end
|
470
478
|
|
471
|
-
|
479
|
+
# Updates the counters of the records in the current relation.
|
480
|
+
#
|
481
|
+
# ==== Parameters
|
482
|
+
#
|
483
|
+
# * +counter+ - A Hash containing the names of the fields to update as keys and the amount to update as values.
|
484
|
+
# * <tt>:touch</tt> option - Touch the timestamp columns when updating.
|
485
|
+
# * If attributes names are passed, they are updated along with update_at/on attributes.
|
486
|
+
#
|
487
|
+
# ==== Examples
|
488
|
+
#
|
489
|
+
# # For Posts by a given author increment the comment_count by 1.
|
490
|
+
# Post.where(author_id: author.id).update_counters(comment_count: 1)
|
491
|
+
def update_counters(counters)
|
472
492
|
touch = counters.delete(:touch)
|
473
493
|
|
474
494
|
updates = {}
|
475
495
|
counters.each do |counter_name, value|
|
476
|
-
attr =
|
496
|
+
attr = table[counter_name]
|
477
497
|
updates[attr.name] = _increment_attribute(attr, value)
|
478
498
|
end
|
479
499
|
|
480
500
|
if touch
|
481
501
|
names = touch if touch != true
|
482
|
-
|
502
|
+
names = Array.wrap(names)
|
503
|
+
options = names.extract_options!
|
504
|
+
touch_updates = klass.touch_attributes_with_time(*names, **options)
|
483
505
|
updates.merge!(touch_updates) unless touch_updates.empty?
|
484
506
|
end
|
485
507
|
|
486
508
|
update_all updates
|
487
509
|
end
|
488
510
|
|
489
|
-
# Touches all records in the current relation
|
490
|
-
#
|
511
|
+
# Touches all records in the current relation, setting the +updated_at+/+updated_on+ attributes to the current time or the time specified.
|
512
|
+
# It does not instantiate the involved models, and it does not trigger Active Record callbacks or validations.
|
491
513
|
# This method can be passed attribute names and an optional time argument.
|
492
514
|
# If attribute names are passed, they are updated along with +updated_at+/+updated_on+ attributes.
|
493
515
|
# If no time argument is passed, the current time is used as default.
|
@@ -567,7 +589,7 @@ module ActiveRecord
|
|
567
589
|
|
568
590
|
stmt = Arel::DeleteManager.new
|
569
591
|
stmt.from(arel.join_sources.empty? ? table : arel.source)
|
570
|
-
stmt.key =
|
592
|
+
stmt.key = table[primary_key]
|
571
593
|
stmt.take(arel.limit)
|
572
594
|
stmt.offset(arel.offset)
|
573
595
|
stmt.order(*arel.orders)
|
@@ -612,7 +634,10 @@ module ActiveRecord
|
|
612
634
|
#
|
613
635
|
# Post.where(published: true).load # => #<ActiveRecord::Relation>
|
614
636
|
def load(&block)
|
615
|
-
|
637
|
+
unless loaded?
|
638
|
+
@records = exec_queries(&block)
|
639
|
+
@loaded = true
|
640
|
+
end
|
616
641
|
|
617
642
|
self
|
618
643
|
end
|
@@ -625,10 +650,9 @@ module ActiveRecord
|
|
625
650
|
|
626
651
|
def reset
|
627
652
|
@delegate_to_klass = false
|
628
|
-
@_deprecated_scope_source = nil
|
629
653
|
@to_sql = @arel = @loaded = @should_eager_load = nil
|
654
|
+
@offsets = @take = nil
|
630
655
|
@records = [].freeze
|
631
|
-
@offsets = {}
|
632
656
|
self
|
633
657
|
end
|
634
658
|
|
@@ -659,7 +683,10 @@ module ActiveRecord
|
|
659
683
|
end
|
660
684
|
|
661
685
|
def scope_for_create
|
662
|
-
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
|
663
690
|
end
|
664
691
|
|
665
692
|
# Returns true if relation needs eager loading.
|
@@ -703,7 +730,7 @@ module ActiveRecord
|
|
703
730
|
end
|
704
731
|
|
705
732
|
def inspect
|
706
|
-
subject = loaded? ? records :
|
733
|
+
subject = loaded? ? records : annotate("loading for inspect")
|
707
734
|
entries = subject.take([limit_value, 11].compact.min).map!(&:inspect)
|
708
735
|
|
709
736
|
entries[10] = "..." if entries.size == 11
|
@@ -720,25 +747,31 @@ module ActiveRecord
|
|
720
747
|
end
|
721
748
|
|
722
749
|
def alias_tracker(joins = [], aliases = nil) # :nodoc:
|
723
|
-
|
724
|
-
|
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
|
725
761
|
end
|
726
762
|
|
727
763
|
def preload_associations(records) # :nodoc:
|
728
764
|
preload = preload_values
|
729
765
|
preload += includes_values unless eager_loading?
|
730
766
|
preloader = nil
|
767
|
+
scope = strict_loading_value ? StrictLoadingScope : nil
|
731
768
|
preload.each do |associations|
|
732
769
|
preloader ||= build_preloader
|
733
|
-
preloader.preload records, associations
|
770
|
+
preloader.preload records, associations, scope
|
734
771
|
end
|
735
772
|
end
|
736
773
|
|
737
|
-
attr_reader :_deprecated_scope_source # :nodoc:
|
738
|
-
|
739
774
|
protected
|
740
|
-
attr_writer :_deprecated_scope_source # :nodoc:
|
741
|
-
|
742
775
|
def load_records(records)
|
743
776
|
@records = records.freeze
|
744
777
|
@loaded = true
|
@@ -750,23 +783,29 @@ module ActiveRecord
|
|
750
783
|
|
751
784
|
private
|
752
785
|
def already_in_scope?
|
753
|
-
@delegate_to_klass &&
|
754
|
-
scope = klass.current_scope(true)
|
755
|
-
scope && !scope._deprecated_scope_source
|
756
|
-
end
|
786
|
+
@delegate_to_klass && klass.current_scope(true)
|
757
787
|
end
|
758
788
|
|
759
|
-
def
|
760
|
-
|
761
|
-
end
|
762
|
-
|
763
|
-
def _deprecated_scope_block(name, &block)
|
789
|
+
def current_scope_restoring_block(&block)
|
790
|
+
current_scope = klass.current_scope(true)
|
764
791
|
-> record do
|
765
|
-
klass.current_scope =
|
792
|
+
klass.current_scope = current_scope
|
766
793
|
yield record if block_given?
|
767
794
|
end
|
768
795
|
end
|
769
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
|
+
|
770
809
|
def _scoping(scope)
|
771
810
|
previous, klass.current_scope = klass.current_scope(true), scope
|
772
811
|
yield
|
@@ -776,7 +815,7 @@ module ActiveRecord
|
|
776
815
|
|
777
816
|
def _substitute_values(values)
|
778
817
|
values.map do |name, value|
|
779
|
-
attr =
|
818
|
+
attr = table[name]
|
780
819
|
unless Arel.arel_node?(value)
|
781
820
|
type = klass.type_for_attribute(attr.name)
|
782
821
|
value = predicate_builder.build_bind_attribute(attr.name, type.cast(value))
|
@@ -794,27 +833,29 @@ module ActiveRecord
|
|
794
833
|
|
795
834
|
def exec_queries(&block)
|
796
835
|
skip_query_cache_if_necessary do
|
797
|
-
|
798
|
-
if
|
836
|
+
records =
|
837
|
+
if where_clause.contradiction?
|
838
|
+
[]
|
839
|
+
elsif eager_loading?
|
799
840
|
apply_join_dependency do |relation, join_dependency|
|
800
841
|
if relation.null_relation?
|
801
842
|
[]
|
802
843
|
else
|
803
844
|
relation = join_dependency.apply_column_aliases(relation)
|
804
845
|
rows = connection.select_all(relation.arel, "SQL")
|
805
|
-
join_dependency.instantiate(rows, &block)
|
846
|
+
join_dependency.instantiate(rows, strict_loading_value, &block)
|
806
847
|
end.freeze
|
807
848
|
end
|
808
849
|
else
|
809
850
|
klass.find_by_sql(arel, &block).freeze
|
810
851
|
end
|
811
852
|
|
812
|
-
preload_associations(
|
853
|
+
preload_associations(records) unless skip_preloading_value
|
813
854
|
|
814
|
-
|
855
|
+
records.each(&:readonly!) if readonly_value
|
856
|
+
records.each(&:strict_loading!) if strict_loading_value
|
815
857
|
|
816
|
-
|
817
|
-
@records
|
858
|
+
records
|
818
859
|
end
|
819
860
|
end
|
820
861
|
|
@@ -833,27 +874,27 @@ module ActiveRecord
|
|
833
874
|
end
|
834
875
|
|
835
876
|
def references_eager_loaded_tables?
|
836
|
-
joined_tables =
|
877
|
+
joined_tables = build_joins([]).flat_map do |join|
|
837
878
|
if join.is_a?(Arel::Nodes::StringJoin)
|
838
879
|
tables_in_string(join.left)
|
839
880
|
else
|
840
|
-
|
881
|
+
join.left.name
|
841
882
|
end
|
842
883
|
end
|
843
884
|
|
844
|
-
joined_tables
|
885
|
+
joined_tables << table.name
|
845
886
|
|
846
887
|
# always convert table names to downcase as in Oracle quoted table names are in uppercase
|
847
|
-
joined_tables
|
888
|
+
joined_tables.map!(&:downcase)
|
848
889
|
|
849
|
-
(references_values - joined_tables).
|
890
|
+
!(references_values.map(&:to_s) - joined_tables).empty?
|
850
891
|
end
|
851
892
|
|
852
893
|
def tables_in_string(string)
|
853
894
|
return [] if string.blank?
|
854
895
|
# always convert table names to downcase as in Oracle quoted table names are in uppercase
|
855
896
|
# ignore raw_sql_ that is used by Oracle adapter as alias for limit/offset subqueries
|
856
|
-
string.scan(/
|
897
|
+
string.scan(/[a-zA-Z_][.\w]+(?=.?\.)/).map!(&:downcase) - ["raw_sql_"]
|
857
898
|
end
|
858
899
|
end
|
859
900
|
end
|