activerecord 6.0.3 → 6.1.3
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 +968 -682
- data/MIT-LICENSE +1 -1
- data/README.rdoc +3 -3
- data/lib/active_record.rb +7 -14
- data/lib/active_record/aggregations.rb +5 -5
- data/lib/active_record/association_relation.rb +30 -12
- data/lib/active_record/associations.rb +118 -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 +19 -15
- data/lib/active_record/associations/belongs_to_association.rb +22 -8
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -3
- data/lib/active_record/associations/builder/association.rb +32 -5
- 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 +39 -16
- 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 +33 -8
- 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 +66 -23
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +3 -8
- 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 +116 -27
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +228 -83
- data/lib/active_record/connection_adapters/abstract/transaction.rb +80 -32
- data/lib/active_record/connection_adapters/abstract_adapter.rb +54 -72
- 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 +18 -3
- 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 +5 -2
- 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 +73 -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/money.rb +2 -2
- 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 +74 -63
- 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 +218 -71
- data/lib/active_record/core.rb +245 -61
- 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 +82 -38
- 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 +58 -9
- data/lib/active_record/gem_version.rb +1 -1
- 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 +33 -17
- data/lib/active_record/locking/pessimistic.rb +6 -2
- data/lib/active_record/log_subscriber.rb +27 -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 +114 -84
- data/lib/active_record/migration/command_recorder.rb +47 -27
- data/lib/active_record/migration/compatibility.rb +68 -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/console_sandbox.rb +2 -4
- data/lib/active_record/railties/databases.rake +276 -99
- data/lib/active_record/readonly_attributes.rb +4 -0
- data/lib/active_record/reflection.rb +71 -57
- data/lib/active_record/relation.rb +95 -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 +61 -38
- 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 +10 -6
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/query_methods.rb +333 -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 +107 -60
- 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 +42 -51
- data/lib/active_record/tasks/database_tasks.rb +140 -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 +19 -66
- 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 +28 -29
- 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)
|
@@ -289,8 +271,10 @@ module ActiveRecord
|
|
289
271
|
if options[:on]
|
290
272
|
fire_on = Array(options[:on])
|
291
273
|
assert_valid_transaction_action(fire_on)
|
292
|
-
options[:if] =
|
293
|
-
|
274
|
+
options[:if] = [
|
275
|
+
-> { transaction_include_any_action?(fire_on) },
|
276
|
+
*options[:if]
|
277
|
+
]
|
294
278
|
end
|
295
279
|
end
|
296
280
|
|
@@ -302,7 +286,7 @@ module ActiveRecord
|
|
302
286
|
end
|
303
287
|
|
304
288
|
# See ActiveRecord::Transactions::ClassMethods for detailed documentation.
|
305
|
-
def transaction(options
|
289
|
+
def transaction(**options, &block)
|
306
290
|
self.class.transaction(**options, &block)
|
307
291
|
end
|
308
292
|
|
@@ -310,11 +294,11 @@ module ActiveRecord
|
|
310
294
|
with_transaction_returning_status { super }
|
311
295
|
end
|
312
296
|
|
313
|
-
def save(
|
297
|
+
def save(**) #:nodoc:
|
314
298
|
with_transaction_returning_status { super }
|
315
299
|
end
|
316
300
|
|
317
|
-
def save!(
|
301
|
+
def save!(**) #:nodoc:
|
318
302
|
with_transaction_returning_status { super }
|
319
303
|
end
|
320
304
|
|
@@ -323,7 +307,6 @@ module ActiveRecord
|
|
323
307
|
end
|
324
308
|
|
325
309
|
def before_committed! # :nodoc:
|
326
|
-
_run_before_commit_without_transaction_enrollment_callbacks
|
327
310
|
_run_before_commit_callbacks
|
328
311
|
end
|
329
312
|
|
@@ -335,7 +318,6 @@ module ActiveRecord
|
|
335
318
|
force_clear_transaction_record_state
|
336
319
|
if should_run_callbacks
|
337
320
|
@_committed_already_called = true
|
338
|
-
_run_commit_without_transaction_enrollment_callbacks
|
339
321
|
_run_commit_callbacks
|
340
322
|
end
|
341
323
|
ensure
|
@@ -347,7 +329,6 @@ module ActiveRecord
|
|
347
329
|
def rolledback!(force_restore_state: false, should_run_callbacks: true) #:nodoc:
|
348
330
|
if should_run_callbacks
|
349
331
|
_run_rollback_callbacks
|
350
|
-
_run_rollback_without_transaction_enrollment_callbacks
|
351
332
|
end
|
352
333
|
ensure
|
353
334
|
restore_transaction_record_state(force_restore_state)
|
@@ -363,13 +344,11 @@ module ActiveRecord
|
|
363
344
|
# instance.
|
364
345
|
def with_transaction_returning_status
|
365
346
|
status = nil
|
366
|
-
self.class.
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
@transaction_state = self.class.connection.transaction_state
|
372
|
-
end
|
347
|
+
connection = self.class.connection
|
348
|
+
ensure_finalize = !connection.transaction_open?
|
349
|
+
|
350
|
+
connection.transaction do
|
351
|
+
add_to_transaction(ensure_finalize || has_transactional_callbacks?)
|
373
352
|
remember_transaction_record_state
|
374
353
|
|
375
354
|
status = yield
|
@@ -391,6 +370,7 @@ module ActiveRecord
|
|
391
370
|
@_start_transaction_state ||= {
|
392
371
|
id: id,
|
393
372
|
new_record: @new_record,
|
373
|
+
previously_new_record: @previously_new_record,
|
394
374
|
destroyed: @destroyed,
|
395
375
|
attributes: @attributes,
|
396
376
|
frozen?: frozen?,
|
@@ -415,7 +395,6 @@ module ActiveRecord
|
|
415
395
|
# Force to clear the transaction record state.
|
416
396
|
def force_clear_transaction_record_state
|
417
397
|
@_start_transaction_state = nil
|
418
|
-
@transaction_state = nil
|
419
398
|
end
|
420
399
|
|
421
400
|
# Restore the new record state and id of a record that was previously saved by a call to save_record_state.
|
@@ -423,6 +402,7 @@ module ActiveRecord
|
|
423
402
|
if restore_state = @_start_transaction_state
|
424
403
|
if force_restore_state || restore_state[:level] <= 1
|
425
404
|
@new_record = restore_state[:new_record]
|
405
|
+
@previously_new_record = restore_state[:previously_new_record]
|
426
406
|
@destroyed = restore_state[:destroyed]
|
427
407
|
@attributes = restore_state[:attributes].map do |attr|
|
428
408
|
value = @attributes.fetch_value(attr.name)
|
@@ -455,39 +435,12 @@ module ActiveRecord
|
|
455
435
|
|
456
436
|
# Add the record to the current transaction so that the #after_rollback and #after_commit
|
457
437
|
# callbacks can be called.
|
458
|
-
def add_to_transaction
|
459
|
-
self.class.connection.add_transaction_record(self)
|
438
|
+
def add_to_transaction(ensure_finalize = true)
|
439
|
+
self.class.connection.add_transaction_record(self, ensure_finalize)
|
460
440
|
end
|
461
441
|
|
462
442
|
def has_transactional_callbacks?
|
463
443
|
!_rollback_callbacks.empty? || !_commit_callbacks.empty? || !_before_commit_callbacks.empty?
|
464
444
|
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
445
|
end
|
493
446
|
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)
|
@@ -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
|
@@ -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
|
@@ -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/arel.rb
CHANGED
@@ -12,7 +12,7 @@ require "arel/math"
|
|
12
12
|
require "arel/alias_predication"
|
13
13
|
require "arel/order_predications"
|
14
14
|
require "arel/table"
|
15
|
-
require "arel/attributes"
|
15
|
+
require "arel/attributes/attribute"
|
16
16
|
|
17
17
|
require "arel/visitors"
|
18
18
|
require "arel/collectors/sql_string"
|
@@ -43,20 +43,12 @@ module Arel
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def self.arel_node?(value) # :nodoc:
|
46
|
-
value.is_a?(Arel::Node) || value.is_a?(Arel::Attribute) || value.is_a?(Arel::Nodes::SqlLiteral)
|
46
|
+
value.is_a?(Arel::Nodes::Node) || value.is_a?(Arel::Attribute) || value.is_a?(Arel::Nodes::SqlLiteral)
|
47
47
|
end
|
48
48
|
|
49
|
-
def self.fetch_attribute(value) # :nodoc:
|
50
|
-
|
51
|
-
|
52
|
-
if value.left.is_a?(Arel::Attributes::Attribute)
|
53
|
-
yield value.left
|
54
|
-
elsif value.right.is_a?(Arel::Attributes::Attribute)
|
55
|
-
yield value.right
|
56
|
-
end
|
49
|
+
def self.fetch_attribute(value, &block) # :nodoc:
|
50
|
+
unless String === value
|
51
|
+
value.fetch_attribute(&block)
|
57
52
|
end
|
58
53
|
end
|
59
|
-
|
60
|
-
## Convenience Alias
|
61
|
-
Node = Arel::Nodes::Node # :nodoc:
|
62
54
|
end
|