activerecord 6.0.5.1 → 6.1.0.rc1
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 +764 -916
- data/MIT-LICENSE +1 -1
- data/README.rdoc +3 -3
- data/lib/active_record/aggregations.rb +1 -1
- data/lib/active_record/association_relation.rb +22 -14
- data/lib/active_record/associations/alias_tracker.rb +19 -15
- data/lib/active_record/associations/association.rb +39 -27
- data/lib/active_record/associations/association_scope.rb +11 -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 -13
- data/lib/active_record/associations/collection_proxy.rb +12 -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/join_association.rb +29 -14
- data/lib/active_record/associations/join_dependency/join_part.rb +1 -1
- data/lib/active_record/associations/join_dependency.rb +63 -49
- data/lib/active_record/associations/preloader/association.rb +13 -5
- data/lib/active_record/associations/preloader/through_association.rb +1 -1
- data/lib/active_record/associations/preloader.rb +5 -3
- data/lib/active_record/associations/singular_association.rb +1 -1
- data/lib/active_record/associations.rb +114 -11
- data/lib/active_record/attribute_assignment.rb +10 -8
- 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 +4 -4
- 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/attribute_methods.rb +52 -48
- data/lib/active_record/attributes.rb +27 -7
- data/lib/active_record/autosave_association.rb +47 -30
- data/lib/active_record/base.rb +2 -14
- data/lib/active_record/callbacks.rb +32 -22
- data/lib/active_record/coders/yaml_column.rb +2 -14
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +180 -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 +110 -30
- 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 +66 -24
- data/lib/active_record/connection_adapters/abstract_adapter.rb +31 -70
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +123 -87
- 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 +22 -24
- 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 +33 -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 +3 -3
- 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 +12 -53
- 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 +2 -10
- 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/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +11 -1
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +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 +30 -5
- 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 +36 -3
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +48 -50
- data/lib/active_record/connection_adapters.rb +50 -0
- data/lib/active_record/connection_handling.rb +210 -71
- data/lib/active_record/core.rb +214 -58
- 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/database_configurations.rb +124 -85
- data/lib/active_record/delegated_type.rb +209 -0
- data/lib/active_record/destroy_association_async_job.rb +36 -0
- data/lib/active_record/enum.rb +33 -23
- 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 +32 -5
- data/lib/active_record/integration.rb +3 -5
- data/lib/active_record/internal_metadata.rb +15 -4
- data/lib/active_record/legacy_yaml_adapter.rb +7 -3
- data/lib/active_record/locking/optimistic.rb +13 -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/resolver/session.rb +3 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +5 -0
- data/lib/active_record/middleware/database_selector.rb +4 -1
- data/lib/active_record/migration/command_recorder.rb +47 -27
- data/lib/active_record/migration/compatibility.rb +67 -17
- data/lib/active_record/migration.rb +113 -83
- data/lib/active_record/model_schema.rb +88 -42
- 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 +61 -59
- data/lib/active_record/railties/databases.rake +253 -98
- data/lib/active_record/readonly_attributes.rb +4 -0
- data/lib/active_record/reflection.rb +59 -44
- data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
- data/lib/active_record/relation/batches.rb +38 -31
- data/lib/active_record/relation/calculations.rb +100 -43
- data/lib/active_record/relation/finder_methods.rb +44 -14
- data/lib/active_record/relation/from_clause.rb +1 -1
- data/lib/active_record/relation/merger.rb +20 -23
- data/lib/active_record/relation/predicate_builder/array_handler.rb +8 -9
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +2 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +3 -3
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/predicate_builder.rb +57 -33
- data/lib/active_record/relation/query_methods.rb +319 -196
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +6 -5
- data/lib/active_record/relation/where_clause.rb +104 -57
- data/lib/active_record/relation.rb +90 -64
- 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 +0 -4
- data/lib/active_record/scoping/named.rb +1 -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 +36 -52
- 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 +36 -33
- 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/serialized.rb +6 -2
- data/lib/active_record/type.rb +8 -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/associated.rb +1 -1
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/uniqueness.rb +24 -4
- data/lib/active_record/validations.rb +1 -0
- data/lib/active_record.rb +7 -14
- data/lib/arel/attributes/attribute.rb +4 -0
- data/lib/arel/collectors/bind.rb +5 -0
- data/lib/arel/collectors/composite.rb +8 -0
- data/lib/arel/collectors/sql_string.rb +7 -0
- data/lib/arel/collectors/substitute_binds.rb +7 -0
- data/lib/arel/nodes/binary.rb +82 -8
- data/lib/arel/nodes/bind_param.rb +8 -0
- data/lib/arel/nodes/casted.rb +21 -9
- data/lib/arel/nodes/equality.rb +6 -9
- data/lib/arel/nodes/grouping.rb +3 -0
- data/lib/arel/nodes/homogeneous_in.rb +72 -0
- data/lib/arel/nodes/in.rb +8 -1
- data/lib/arel/nodes/infix_operation.rb +13 -1
- data/lib/arel/nodes/join_source.rb +1 -1
- data/lib/arel/nodes/node.rb +7 -6
- data/lib/arel/nodes/ordering.rb +27 -0
- data/lib/arel/nodes/sql_literal.rb +3 -0
- data/lib/arel/nodes/table_alias.rb +7 -3
- data/lib/arel/nodes/unary.rb +0 -1
- data/lib/arel/nodes.rb +3 -1
- data/lib/arel/predications.rb +12 -18
- data/lib/arel/select_manager.rb +1 -2
- data/lib/arel/table.rb +13 -5
- 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/arel/visitors.rb +0 -7
- data/lib/arel.rb +5 -13
- 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/migration.rb +6 -1
- 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 +30 -32
- 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
@@ -10,9 +10,6 @@ module ActiveRecord
|
|
10
10
|
included do
|
11
11
|
define_callbacks :commit, :rollback,
|
12
12
|
:before_commit,
|
13
|
-
:before_commit_without_transaction_enrollment,
|
14
|
-
:commit_without_transaction_enrollment,
|
15
|
-
:rollback_without_transaction_enrollment,
|
16
13
|
scope: [:kind, :name]
|
17
14
|
end
|
18
15
|
|
@@ -164,13 +161,13 @@ module ActiveRecord
|
|
164
161
|
# end
|
165
162
|
# end
|
166
163
|
#
|
167
|
-
# only "Kotori" is created.
|
164
|
+
# only "Kotori" is created.
|
168
165
|
#
|
169
166
|
# Most databases don't support true nested transactions. At the time of
|
170
167
|
# writing, the only database that we're aware of that supports true nested
|
171
168
|
# transactions, is MS-SQL. Because of this, Active Record emulates nested
|
172
|
-
# transactions by using savepoints
|
173
|
-
# https://dev.mysql.com/doc/refman/
|
169
|
+
# transactions by using savepoints. See
|
170
|
+
# https://dev.mysql.com/doc/refman/en/savepoint.html
|
174
171
|
# for more information about savepoints.
|
175
172
|
#
|
176
173
|
# === \Callbacks
|
@@ -266,21 +263,6 @@ module ActiveRecord
|
|
266
263
|
set_callback(:rollback, :after, *args, &block)
|
267
264
|
end
|
268
265
|
|
269
|
-
def before_commit_without_transaction_enrollment(*args, &block) # :nodoc:
|
270
|
-
set_options_for_callbacks!(args)
|
271
|
-
set_callback(:before_commit_without_transaction_enrollment, :before, *args, &block)
|
272
|
-
end
|
273
|
-
|
274
|
-
def after_commit_without_transaction_enrollment(*args, &block) # :nodoc:
|
275
|
-
set_options_for_callbacks!(args)
|
276
|
-
set_callback(:commit_without_transaction_enrollment, :after, *args, &block)
|
277
|
-
end
|
278
|
-
|
279
|
-
def after_rollback_without_transaction_enrollment(*args, &block) # :nodoc:
|
280
|
-
set_options_for_callbacks!(args)
|
281
|
-
set_callback(:rollback_without_transaction_enrollment, :after, *args, &block)
|
282
|
-
end
|
283
|
-
|
284
266
|
private
|
285
267
|
def set_options_for_callbacks!(args, enforced_options = {})
|
286
268
|
options = args.extract_options!.merge!(enforced_options)
|
@@ -302,7 +284,7 @@ module ActiveRecord
|
|
302
284
|
end
|
303
285
|
|
304
286
|
# See ActiveRecord::Transactions::ClassMethods for detailed documentation.
|
305
|
-
def transaction(options
|
287
|
+
def transaction(**options, &block)
|
306
288
|
self.class.transaction(**options, &block)
|
307
289
|
end
|
308
290
|
|
@@ -310,11 +292,11 @@ module ActiveRecord
|
|
310
292
|
with_transaction_returning_status { super }
|
311
293
|
end
|
312
294
|
|
313
|
-
def save(
|
295
|
+
def save(**) #:nodoc:
|
314
296
|
with_transaction_returning_status { super }
|
315
297
|
end
|
316
298
|
|
317
|
-
def save!(
|
299
|
+
def save!(**) #:nodoc:
|
318
300
|
with_transaction_returning_status { super }
|
319
301
|
end
|
320
302
|
|
@@ -323,7 +305,6 @@ module ActiveRecord
|
|
323
305
|
end
|
324
306
|
|
325
307
|
def before_committed! # :nodoc:
|
326
|
-
_run_before_commit_without_transaction_enrollment_callbacks
|
327
308
|
_run_before_commit_callbacks
|
328
309
|
end
|
329
310
|
|
@@ -335,7 +316,6 @@ module ActiveRecord
|
|
335
316
|
force_clear_transaction_record_state
|
336
317
|
if should_run_callbacks
|
337
318
|
@_committed_already_called = true
|
338
|
-
_run_commit_without_transaction_enrollment_callbacks
|
339
319
|
_run_commit_callbacks
|
340
320
|
end
|
341
321
|
ensure
|
@@ -347,7 +327,6 @@ module ActiveRecord
|
|
347
327
|
def rolledback!(force_restore_state: false, should_run_callbacks: true) #:nodoc:
|
348
328
|
if should_run_callbacks
|
349
329
|
_run_rollback_callbacks
|
350
|
-
_run_rollback_without_transaction_enrollment_callbacks
|
351
330
|
end
|
352
331
|
ensure
|
353
332
|
restore_transaction_record_state(force_restore_state)
|
@@ -363,13 +342,11 @@ module ActiveRecord
|
|
363
342
|
# instance.
|
364
343
|
def with_transaction_returning_status
|
365
344
|
status = nil
|
366
|
-
self.class.
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
@transaction_state = self.class.connection.transaction_state
|
372
|
-
end
|
345
|
+
connection = self.class.connection
|
346
|
+
ensure_finalize = !connection.transaction_open?
|
347
|
+
|
348
|
+
connection.transaction do
|
349
|
+
add_to_transaction(ensure_finalize || has_transactional_callbacks?)
|
373
350
|
remember_transaction_record_state
|
374
351
|
|
375
352
|
status = yield
|
@@ -391,6 +368,7 @@ module ActiveRecord
|
|
391
368
|
@_start_transaction_state ||= {
|
392
369
|
id: id,
|
393
370
|
new_record: @new_record,
|
371
|
+
previously_new_record: @previously_new_record,
|
394
372
|
destroyed: @destroyed,
|
395
373
|
attributes: @attributes,
|
396
374
|
frozen?: frozen?,
|
@@ -415,7 +393,6 @@ module ActiveRecord
|
|
415
393
|
# Force to clear the transaction record state.
|
416
394
|
def force_clear_transaction_record_state
|
417
395
|
@_start_transaction_state = nil
|
418
|
-
@transaction_state = nil
|
419
396
|
end
|
420
397
|
|
421
398
|
# Restore the new record state and id of a record that was previously saved by a call to save_record_state.
|
@@ -423,6 +400,7 @@ module ActiveRecord
|
|
423
400
|
if restore_state = @_start_transaction_state
|
424
401
|
if force_restore_state || restore_state[:level] <= 1
|
425
402
|
@new_record = restore_state[:new_record]
|
403
|
+
@previously_new_record = restore_state[:previously_new_record]
|
426
404
|
@destroyed = restore_state[:destroyed]
|
427
405
|
@attributes = restore_state[:attributes].map do |attr|
|
428
406
|
value = @attributes.fetch_value(attr.name)
|
@@ -455,39 +433,12 @@ module ActiveRecord
|
|
455
433
|
|
456
434
|
# Add the record to the current transaction so that the #after_rollback and #after_commit
|
457
435
|
# callbacks can be called.
|
458
|
-
def add_to_transaction
|
459
|
-
self.class.connection.add_transaction_record(self)
|
436
|
+
def add_to_transaction(ensure_finalize = true)
|
437
|
+
self.class.connection.add_transaction_record(self, ensure_finalize)
|
460
438
|
end
|
461
439
|
|
462
440
|
def has_transactional_callbacks?
|
463
441
|
!_rollback_callbacks.empty? || !_commit_callbacks.empty? || !_before_commit_callbacks.empty?
|
464
442
|
end
|
465
|
-
|
466
|
-
# Updates the attributes on this particular Active Record object so that
|
467
|
-
# if it's associated with a transaction, then the state of the Active Record
|
468
|
-
# object will be updated to reflect the current state of the transaction.
|
469
|
-
#
|
470
|
-
# The <tt>@transaction_state</tt> variable stores the states of the associated
|
471
|
-
# transaction. This relies on the fact that a transaction can only be in
|
472
|
-
# one rollback or commit (otherwise a list of states would be required).
|
473
|
-
# Each Active Record object inside of a transaction carries that transaction's
|
474
|
-
# TransactionState.
|
475
|
-
#
|
476
|
-
# This method checks to see if the ActiveRecord object's state reflects
|
477
|
-
# the TransactionState, and rolls back or commits the Active Record object
|
478
|
-
# as appropriate.
|
479
|
-
def sync_with_transaction_state
|
480
|
-
if transaction_state = @transaction_state
|
481
|
-
if transaction_state.fully_committed?
|
482
|
-
force_clear_transaction_record_state
|
483
|
-
elsif transaction_state.committed?
|
484
|
-
clear_transaction_record_state
|
485
|
-
elsif transaction_state.rolledback?
|
486
|
-
force_restore_state = transaction_state.fully_rolledback?
|
487
|
-
restore_transaction_record_state(force_restore_state)
|
488
|
-
clear_transaction_record_state
|
489
|
-
end
|
490
|
-
end
|
491
|
-
end
|
492
443
|
end
|
493
444
|
end
|
@@ -61,9 +61,13 @@ module ActiveRecord
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def encoded(value)
|
64
|
-
|
65
|
-
|
64
|
+
return if default_value?(value)
|
65
|
+
payload = coder.dump(value)
|
66
|
+
if payload && binary? && payload.encoding != Encoding::BINARY
|
67
|
+
payload = payload.dup if payload.frozen?
|
68
|
+
payload.force_encoding(Encoding::BINARY)
|
66
69
|
end
|
70
|
+
payload
|
67
71
|
end
|
68
72
|
end
|
69
73
|
end
|
data/lib/active_record/type.rb
CHANGED
@@ -46,9 +46,14 @@ module ActiveRecord
|
|
46
46
|
@default_value ||= Value.new
|
47
47
|
end
|
48
48
|
|
49
|
+
def adapter_name_from(model) # :nodoc:
|
50
|
+
# TODO: this shouldn't depend on a connection to the database
|
51
|
+
model.connection.adapter_name.downcase.to_sym
|
52
|
+
end
|
53
|
+
|
49
54
|
private
|
50
55
|
def current_adapter_name
|
51
|
-
ActiveRecord::Base
|
56
|
+
adapter_name_from(ActiveRecord::Base)
|
52
57
|
end
|
53
58
|
end
|
54
59
|
|
@@ -58,6 +63,7 @@ module ActiveRecord
|
|
58
63
|
Decimal = ActiveModel::Type::Decimal
|
59
64
|
Float = ActiveModel::Type::Float
|
60
65
|
Integer = ActiveModel::Type::Integer
|
66
|
+
ImmutableString = ActiveModel::Type::ImmutableString
|
61
67
|
String = ActiveModel::Type::String
|
62
68
|
Value = ActiveModel::Type::Value
|
63
69
|
|
@@ -69,6 +75,7 @@ module ActiveRecord
|
|
69
75
|
register(:decimal, Type::Decimal, override: false)
|
70
76
|
register(:float, Type::Float, override: false)
|
71
77
|
register(:integer, Type::Integer, override: false)
|
78
|
+
register(:immutable_string, Type::ImmutableString, override: false)
|
72
79
|
register(:json, Type::Json, override: false)
|
73
80
|
register(:string, Type::String, override: false)
|
74
81
|
register(:text, Type::Text, override: false)
|
@@ -3,18 +3,21 @@
|
|
3
3
|
module ActiveRecord
|
4
4
|
module TypeCaster
|
5
5
|
class Map # :nodoc:
|
6
|
-
def initialize(
|
7
|
-
@
|
6
|
+
def initialize(klass)
|
7
|
+
@klass = klass
|
8
8
|
end
|
9
9
|
|
10
10
|
def type_cast_for_database(attr_name, value)
|
11
|
-
|
12
|
-
type = types.type_for_attribute(attr_name)
|
11
|
+
type = type_for_attribute(attr_name)
|
13
12
|
type.serialize(value)
|
14
13
|
end
|
15
14
|
|
15
|
+
def type_for_attribute(name)
|
16
|
+
klass.type_for_attribute(name)
|
17
|
+
end
|
18
|
+
|
16
19
|
private
|
17
|
-
attr_reader :
|
20
|
+
attr_reader :klass
|
18
21
|
end
|
19
22
|
end
|
20
23
|
end
|
@@ -5,7 +5,7 @@ module ActiveRecord
|
|
5
5
|
class AssociatedValidator < ActiveModel::EachValidator #:nodoc:
|
6
6
|
def validate_each(record, attribute, value)
|
7
7
|
if Array(value).reject { |r| valid_object?(r) }.any?
|
8
|
-
record.errors.add(attribute, :invalid, options.merge(value: value))
|
8
|
+
record.errors.add(attribute, :invalid, **options.merge(value: value))
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module Validations
|
5
|
+
class NumericalityValidator < ActiveModel::Validations::NumericalityValidator # :nodoc:
|
6
|
+
def validate_each(record, attribute, value, precision: nil, scale: nil)
|
7
|
+
precision = [column_precision_for(record, attribute) || BigDecimal.double_fig, BigDecimal.double_fig].min
|
8
|
+
scale = column_scale_for(record, attribute)
|
9
|
+
super(record, attribute, value, precision: precision, scale: scale)
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
def column_precision_for(record, attribute)
|
14
|
+
record.class.type_for_attribute(attribute.to_s)&.precision
|
15
|
+
end
|
16
|
+
|
17
|
+
def column_scale_for(record, attribute)
|
18
|
+
record.class.type_for_attribute(attribute.to_s)&.scale
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
module ClassMethods
|
23
|
+
# Validates whether the value of the specified attribute is numeric by
|
24
|
+
# trying to convert it to a float with Kernel.Float (if <tt>only_integer</tt>
|
25
|
+
# is +false+) or applying it to the regular expression <tt>/\A[\+\-]?\d+\z/</tt>
|
26
|
+
# (if <tt>only_integer</tt> is set to +true+). Kernel.Float precision
|
27
|
+
# defaults to the column's precision value or 15.
|
28
|
+
#
|
29
|
+
# See ActiveModel::Validations::HelperMethods.validates_numericality_of for more information.
|
30
|
+
def validates_numericality_of(*attr_names)
|
31
|
+
validates_with NumericalityValidator, _merge_attributes(attr_names)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -29,13 +29,22 @@ module ActiveRecord
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
relation = scope_relation(record, relation)
|
32
|
-
|
32
|
+
|
33
|
+
if options[:conditions]
|
34
|
+
conditions = options[:conditions]
|
35
|
+
|
36
|
+
relation = if conditions.arity.zero?
|
37
|
+
relation.instance_exec(&conditions)
|
38
|
+
else
|
39
|
+
relation.instance_exec(record, &conditions)
|
40
|
+
end
|
41
|
+
end
|
33
42
|
|
34
43
|
if relation.exists?
|
35
44
|
error_options = options.except(:case_sensitive, :scope, :conditions)
|
36
45
|
error_options[:value] = value
|
37
46
|
|
38
|
-
record.errors.add(attribute, :taken, error_options)
|
47
|
+
record.errors.add(attribute, :taken, **error_options)
|
39
48
|
end
|
40
49
|
end
|
41
50
|
|
@@ -61,7 +70,7 @@ module ActiveRecord
|
|
61
70
|
return relation.none! if bind.unboundable?
|
62
71
|
|
63
72
|
if !options.key?(:case_sensitive) || bind.nil?
|
64
|
-
klass.connection.default_uniqueness_comparison(attr, bind
|
73
|
+
klass.connection.default_uniqueness_comparison(attr, bind)
|
65
74
|
elsif options[:case_sensitive]
|
66
75
|
klass.connection.case_sensitive_comparison(attr, bind)
|
67
76
|
else
|
@@ -78,7 +87,7 @@ module ActiveRecord
|
|
78
87
|
scope_value = if record.class._reflect_on_association(scope_item)
|
79
88
|
record.association(scope_item).reader
|
80
89
|
else
|
81
|
-
record.
|
90
|
+
record.read_attribute(scope_item)
|
82
91
|
end
|
83
92
|
relation = relation.where(scope_item => scope_value)
|
84
93
|
end
|
@@ -126,6 +135,17 @@ module ActiveRecord
|
|
126
135
|
# validates_uniqueness_of :title, conditions: -> { where.not(status: 'archived') }
|
127
136
|
# end
|
128
137
|
#
|
138
|
+
# To build conditions based on the record's state, define the conditions
|
139
|
+
# callable with a parameter, which will be the record itself. This
|
140
|
+
# example validates the title is unique for the year of publication:
|
141
|
+
#
|
142
|
+
# class Article < ActiveRecord::Base
|
143
|
+
# validates_uniqueness_of :title, conditions: ->(article) {
|
144
|
+
# published_at = article.published_at
|
145
|
+
# where(published_at: published_at.beginning_of_year..published_at.end_of_year)
|
146
|
+
# }
|
147
|
+
# end
|
148
|
+
#
|
129
149
|
# When the record is created, a check is performed to make sure that no
|
130
150
|
# record exists in the database with the given value for the specified
|
131
151
|
# attribute (that maps to a column). When the record is updated,
|
data/lib/active_record.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
#--
|
4
|
-
# Copyright (c) 2004-
|
4
|
+
# Copyright (c) 2004-2020 David Heinemeier Hansson
|
5
5
|
#
|
6
6
|
# Permission is hereby granted, free of charge, to any person obtaining
|
7
7
|
# a copy of this software and associated documentation files (the
|
@@ -31,17 +31,18 @@ require "yaml"
|
|
31
31
|
|
32
32
|
require "active_record/version"
|
33
33
|
require "active_model/attribute_set"
|
34
|
+
require "active_record/errors"
|
34
35
|
|
35
36
|
module ActiveRecord
|
36
37
|
extend ActiveSupport::Autoload
|
37
38
|
|
38
|
-
autoload :AdvisoryLockBase
|
39
39
|
autoload :Base
|
40
40
|
autoload :Callbacks
|
41
41
|
autoload :Core
|
42
42
|
autoload :ConnectionHandling
|
43
43
|
autoload :CounterCache
|
44
44
|
autoload :DynamicMatchers
|
45
|
+
autoload :DelegatedType
|
45
46
|
autoload :Enum
|
46
47
|
autoload :InternalMetadata
|
47
48
|
autoload :Explain
|
@@ -68,18 +69,17 @@ module ActiveRecord
|
|
68
69
|
autoload :Serialization
|
69
70
|
autoload :StatementCache
|
70
71
|
autoload :Store
|
72
|
+
autoload :SignedId
|
71
73
|
autoload :Suppressor
|
72
74
|
autoload :Timestamp
|
73
75
|
autoload :Transactions
|
74
76
|
autoload :Translation
|
75
77
|
autoload :Validations
|
76
78
|
autoload :SecureToken
|
77
|
-
autoload :
|
79
|
+
autoload :DestroyAssociationAsyncJob
|
78
80
|
|
79
81
|
eager_autoload do
|
80
|
-
autoload :
|
81
|
-
autoload :ConnectionNotEstablished, "active_record/errors"
|
82
|
-
autoload :ConnectionAdapters, "active_record/connection_adapters/abstract_adapter"
|
82
|
+
autoload :ConnectionAdapters
|
83
83
|
|
84
84
|
autoload :Aggregations
|
85
85
|
autoload :Associations
|
@@ -137,14 +137,6 @@ module ActiveRecord
|
|
137
137
|
end
|
138
138
|
end
|
139
139
|
|
140
|
-
module ConnectionAdapters
|
141
|
-
extend ActiveSupport::Autoload
|
142
|
-
|
143
|
-
eager_autoload do
|
144
|
-
autoload :AbstractAdapter
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
140
|
module Scoping
|
149
141
|
extend ActiveSupport::Autoload
|
150
142
|
|
@@ -194,3 +186,4 @@ end
|
|
194
186
|
YAML.load_tags["!ruby/object:ActiveRecord::AttributeSet"] = "ActiveModel::AttributeSet"
|
195
187
|
YAML.load_tags["!ruby/object:ActiveRecord::Attribute::FromDatabase"] = "ActiveModel::Attribute::FromDatabase"
|
196
188
|
YAML.load_tags["!ruby/object:ActiveRecord::LazyAttributeHash"] = "ActiveModel::LazyAttributeHash"
|
189
|
+
YAML.load_tags["!ruby/object:ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter::MysqlString"] = "ActiveRecord::Type::String"
|
data/lib/arel/collectors/bind.rb
CHANGED
@@ -3,6 +3,8 @@
|
|
3
3
|
module Arel # :nodoc: all
|
4
4
|
module Collectors
|
5
5
|
class Composite
|
6
|
+
attr_accessor :preparable
|
7
|
+
|
6
8
|
def initialize(left, right)
|
7
9
|
@left = left
|
8
10
|
@right = right
|
@@ -20,6 +22,12 @@ module Arel # :nodoc: all
|
|
20
22
|
self
|
21
23
|
end
|
22
24
|
|
25
|
+
def add_binds(binds, &block)
|
26
|
+
left.add_binds(binds, &block)
|
27
|
+
right.add_binds(binds, &block)
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
23
31
|
def value
|
24
32
|
[left.value, right.value]
|
25
33
|
end
|
@@ -5,6 +5,8 @@ require "arel/collectors/plain_string"
|
|
5
5
|
module Arel # :nodoc: all
|
6
6
|
module Collectors
|
7
7
|
class SQLString < PlainString
|
8
|
+
attr_accessor :preparable
|
9
|
+
|
8
10
|
def initialize(*)
|
9
11
|
super
|
10
12
|
@bind_index = 1
|
@@ -15,6 +17,11 @@ module Arel # :nodoc: all
|
|
15
17
|
@bind_index += 1
|
16
18
|
self
|
17
19
|
end
|
20
|
+
|
21
|
+
def add_binds(binds, &block)
|
22
|
+
self << (@bind_index...@bind_index += binds.size).map(&block).join(", ")
|
23
|
+
self
|
24
|
+
end
|
18
25
|
end
|
19
26
|
end
|
20
27
|
end
|
@@ -3,6 +3,8 @@
|
|
3
3
|
module Arel # :nodoc: all
|
4
4
|
module Collectors
|
5
5
|
class SubstituteBinds
|
6
|
+
attr_accessor :preparable
|
7
|
+
|
6
8
|
def initialize(quoter, delegate_collector)
|
7
9
|
@quoter = quoter
|
8
10
|
@delegate = delegate_collector
|
@@ -14,9 +16,14 @@ module Arel # :nodoc: all
|
|
14
16
|
end
|
15
17
|
|
16
18
|
def add_bind(bind)
|
19
|
+
bind = bind.value_for_database if bind.respond_to?(:value_for_database)
|
17
20
|
self << quoter.quote(bind)
|
18
21
|
end
|
19
22
|
|
23
|
+
def add_binds(binds)
|
24
|
+
self << binds.map { |bind| quoter.quote(bind) }.join(", ")
|
25
|
+
end
|
26
|
+
|
20
27
|
def value
|
21
28
|
delegate.value
|
22
29
|
end
|
data/lib/arel/nodes/binary.rb
CHANGED
@@ -29,18 +29,92 @@ module Arel # :nodoc: all
|
|
29
29
|
alias :== :eql?
|
30
30
|
end
|
31
31
|
|
32
|
+
module FetchAttribute
|
33
|
+
def fetch_attribute
|
34
|
+
if left.is_a?(Arel::Attributes::Attribute)
|
35
|
+
yield left
|
36
|
+
elsif right.is_a?(Arel::Attributes::Attribute)
|
37
|
+
yield right
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class Between < Binary; include FetchAttribute; end
|
43
|
+
|
44
|
+
class GreaterThan < Binary
|
45
|
+
include FetchAttribute
|
46
|
+
|
47
|
+
def invert
|
48
|
+
Arel::Nodes::LessThanOrEqual.new(left, right)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class GreaterThanOrEqual < Binary
|
53
|
+
include FetchAttribute
|
54
|
+
|
55
|
+
def invert
|
56
|
+
Arel::Nodes::LessThan.new(left, right)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
class LessThan < Binary
|
61
|
+
include FetchAttribute
|
62
|
+
|
63
|
+
def invert
|
64
|
+
Arel::Nodes::GreaterThanOrEqual.new(left, right)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
class LessThanOrEqual < Binary
|
69
|
+
include FetchAttribute
|
70
|
+
|
71
|
+
def invert
|
72
|
+
Arel::Nodes::GreaterThan.new(left, right)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
class IsDistinctFrom < Binary
|
77
|
+
include FetchAttribute
|
78
|
+
|
79
|
+
def invert
|
80
|
+
Arel::Nodes::IsNotDistinctFrom.new(left, right)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
class IsNotDistinctFrom < Binary
|
85
|
+
include FetchAttribute
|
86
|
+
|
87
|
+
def invert
|
88
|
+
Arel::Nodes::IsDistinctFrom.new(left, right)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
class NotEqual < Binary
|
93
|
+
include FetchAttribute
|
94
|
+
|
95
|
+
def invert
|
96
|
+
Arel::Nodes::Equality.new(left, right)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
class NotIn < Binary
|
101
|
+
include FetchAttribute
|
102
|
+
|
103
|
+
def invert
|
104
|
+
Arel::Nodes::In.new(left, right)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
class Or < Binary
|
109
|
+
def fetch_attribute(&block)
|
110
|
+
left.fetch_attribute(&block) && right.fetch_attribute(&block)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
32
114
|
%w{
|
33
115
|
As
|
34
116
|
Assignment
|
35
|
-
Between
|
36
|
-
GreaterThan
|
37
|
-
GreaterThanOrEqual
|
38
117
|
Join
|
39
|
-
LessThan
|
40
|
-
LessThanOrEqual
|
41
|
-
NotEqual
|
42
|
-
NotIn
|
43
|
-
Or
|
44
118
|
Union
|
45
119
|
UnionAll
|
46
120
|
Intersect
|
@@ -24,6 +24,14 @@ module Arel # :nodoc: all
|
|
24
24
|
value.nil?
|
25
25
|
end
|
26
26
|
|
27
|
+
def value_before_type_cast
|
28
|
+
if value.respond_to?(:value_before_type_cast)
|
29
|
+
value.value_before_type_cast
|
30
|
+
else
|
31
|
+
value
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
27
35
|
def infinite?
|
28
36
|
value.respond_to?(:infinite?) && value.infinite?
|
29
37
|
end
|