activerecord 5.2.4.2 → 6.0.2.2
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 +715 -566
- data/MIT-LICENSE +3 -1
- data/README.rdoc +4 -2
- data/examples/performance.rb +1 -1
- data/lib/active_record.rb +9 -2
- data/lib/active_record/aggregations.rb +4 -2
- data/lib/active_record/association_relation.rb +15 -6
- data/lib/active_record/associations.rb +20 -15
- data/lib/active_record/associations/association.rb +61 -20
- data/lib/active_record/associations/association_scope.rb +4 -6
- data/lib/active_record/associations/belongs_to_association.rb +36 -42
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +0 -4
- data/lib/active_record/associations/builder/association.rb +14 -18
- data/lib/active_record/associations/builder/belongs_to.rb +19 -52
- data/lib/active_record/associations/builder/collection_association.rb +3 -13
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -38
- data/lib/active_record/associations/builder/has_many.rb +2 -0
- data/lib/active_record/associations/builder/has_one.rb +35 -1
- data/lib/active_record/associations/builder/singular_association.rb +2 -0
- data/lib/active_record/associations/collection_association.rb +12 -23
- data/lib/active_record/associations/collection_proxy.rb +12 -15
- data/lib/active_record/associations/foreign_association.rb +7 -0
- data/lib/active_record/associations/has_many_association.rb +2 -10
- data/lib/active_record/associations/has_many_through_association.rb +14 -14
- data/lib/active_record/associations/has_one_association.rb +28 -30
- data/lib/active_record/associations/has_one_through_association.rb +5 -5
- data/lib/active_record/associations/join_dependency.rb +28 -28
- data/lib/active_record/associations/join_dependency/join_association.rb +9 -10
- data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
- data/lib/active_record/associations/preloader.rb +39 -31
- data/lib/active_record/associations/preloader/association.rb +38 -36
- data/lib/active_record/associations/preloader/through_association.rb +48 -39
- data/lib/active_record/associations/singular_association.rb +2 -16
- data/lib/active_record/attribute_assignment.rb +7 -10
- data/lib/active_record/attribute_methods.rb +28 -100
- data/lib/active_record/attribute_methods/before_type_cast.rb +4 -1
- data/lib/active_record/attribute_methods/dirty.rb +111 -40
- data/lib/active_record/attribute_methods/primary_key.rb +15 -22
- data/lib/active_record/attribute_methods/query.rb +2 -3
- data/lib/active_record/attribute_methods/read.rb +15 -53
- data/lib/active_record/attribute_methods/serialization.rb +1 -1
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +1 -1
- data/lib/active_record/attribute_methods/write.rb +17 -24
- data/lib/active_record/attributes.rb +13 -0
- data/lib/active_record/autosave_association.rb +2 -2
- data/lib/active_record/base.rb +2 -3
- data/lib/active_record/callbacks.rb +5 -19
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +104 -16
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -4
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +99 -123
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +18 -8
- data/lib/active_record/connection_adapters/abstract/quoting.rb +68 -17
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +19 -12
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +76 -48
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +1 -3
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +132 -53
- data/lib/active_record/connection_adapters/abstract/transaction.rb +96 -56
- data/lib/active_record/connection_adapters/abstract_adapter.rb +187 -43
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +138 -195
- data/lib/active_record/connection_adapters/column.rb +17 -13
- data/lib/active_record/connection_adapters/connection_specification.rb +53 -43
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +6 -10
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +75 -13
- data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -7
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +3 -4
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +40 -32
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +14 -6
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +129 -13
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +6 -10
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +26 -9
- data/lib/active_record/connection_adapters/postgresql/column.rb +17 -31
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +22 -1
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +6 -3
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +44 -7
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +12 -1
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -91
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +55 -53
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +24 -27
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +164 -74
- data/lib/active_record/connection_adapters/schema_cache.rb +37 -14
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +11 -8
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +120 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +42 -6
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +42 -11
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +129 -141
- data/lib/active_record/connection_handling.rb +155 -26
- data/lib/active_record/core.rb +103 -59
- data/lib/active_record/counter_cache.rb +4 -29
- data/lib/active_record/database_configurations.rb +233 -0
- data/lib/active_record/database_configurations/database_config.rb +37 -0
- data/lib/active_record/database_configurations/hash_config.rb +50 -0
- data/lib/active_record/database_configurations/url_config.rb +79 -0
- data/lib/active_record/dynamic_matchers.rb +1 -1
- data/lib/active_record/enum.rb +37 -7
- data/lib/active_record/errors.rb +15 -7
- data/lib/active_record/explain.rb +1 -1
- data/lib/active_record/fixture_set/model_metadata.rb +33 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +153 -0
- data/lib/active_record/fixture_set/table_rows.rb +47 -0
- data/lib/active_record/fixtures.rb +145 -472
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +13 -3
- data/lib/active_record/insert_all.rb +179 -0
- data/lib/active_record/integration.rb +68 -16
- data/lib/active_record/internal_metadata.rb +10 -2
- data/lib/active_record/locking/optimistic.rb +5 -6
- data/lib/active_record/locking/pessimistic.rb +3 -3
- data/lib/active_record/log_subscriber.rb +7 -26
- data/lib/active_record/middleware/database_selector.rb +75 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +88 -0
- data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
- data/lib/active_record/migration.rb +100 -81
- data/lib/active_record/migration/command_recorder.rb +50 -6
- data/lib/active_record/migration/compatibility.rb +76 -49
- data/lib/active_record/model_schema.rb +33 -9
- data/lib/active_record/nested_attributes.rb +2 -2
- data/lib/active_record/no_touching.rb +7 -0
- data/lib/active_record/persistence.rb +228 -24
- data/lib/active_record/query_cache.rb +11 -4
- data/lib/active_record/querying.rb +32 -20
- data/lib/active_record/railtie.rb +80 -43
- data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
- data/lib/active_record/railties/controller_runtime.rb +30 -35
- data/lib/active_record/railties/databases.rake +199 -46
- data/lib/active_record/reflection.rb +32 -30
- data/lib/active_record/relation.rb +311 -80
- data/lib/active_record/relation/batches.rb +13 -10
- data/lib/active_record/relation/calculations.rb +53 -47
- data/lib/active_record/relation/delegation.rb +26 -43
- data/lib/active_record/relation/finder_methods.rb +23 -27
- data/lib/active_record/relation/merger.rb +11 -20
- data/lib/active_record/relation/predicate_builder.rb +4 -6
- data/lib/active_record/relation/predicate_builder/array_handler.rb +5 -4
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +1 -4
- data/lib/active_record/relation/predicate_builder/base_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -4
- data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
- data/lib/active_record/relation/query_attribute.rb +13 -8
- data/lib/active_record/relation/query_methods.rb +213 -64
- data/lib/active_record/relation/spawn_methods.rb +1 -1
- data/lib/active_record/relation/where_clause.rb +14 -10
- data/lib/active_record/relation/where_clause_factory.rb +1 -2
- data/lib/active_record/result.rb +30 -11
- data/lib/active_record/sanitization.rb +32 -40
- data/lib/active_record/schema.rb +2 -11
- data/lib/active_record/schema_dumper.rb +22 -7
- data/lib/active_record/schema_migration.rb +5 -1
- data/lib/active_record/scoping.rb +8 -8
- data/lib/active_record/scoping/default.rb +4 -5
- data/lib/active_record/scoping/named.rb +20 -15
- data/lib/active_record/statement_cache.rb +30 -3
- data/lib/active_record/store.rb +87 -8
- data/lib/active_record/table_metadata.rb +10 -17
- data/lib/active_record/tasks/database_tasks.rb +194 -25
- data/lib/active_record/tasks/mysql_database_tasks.rb +5 -5
- data/lib/active_record/tasks/postgresql_database_tasks.rb +5 -7
- data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -8
- data/lib/active_record/test_databases.rb +23 -0
- data/lib/active_record/test_fixtures.rb +225 -0
- data/lib/active_record/timestamp.rb +39 -25
- data/lib/active_record/touch_later.rb +4 -2
- data/lib/active_record/transactions.rb +56 -65
- data/lib/active_record/translation.rb +1 -1
- data/lib/active_record/type.rb +3 -4
- data/lib/active_record/type/adapter_specific_registry.rb +1 -8
- data/lib/active_record/type_caster/connection.rb +15 -14
- data/lib/active_record/type_caster/map.rb +1 -4
- data/lib/active_record/validations.rb +1 -0
- data/lib/active_record/validations/uniqueness.rb +15 -27
- data/lib/arel.rb +58 -0
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes.rb +22 -0
- data/lib/arel/attributes/attribute.rb +37 -0
- data/lib/arel/collectors/bind.rb +24 -0
- data/lib/arel/collectors/composite.rb +31 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +20 -0
- data/lib/arel/collectors/substitute_binds.rb +28 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/insert_manager.rb +49 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes.rb +68 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +52 -0
- data/lib/arel/nodes/bind_param.rb +36 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +50 -0
- data/lib/arel/nodes/comment.rb +29 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +45 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +18 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +8 -0
- data/lib/arel/nodes/in.rb +8 -0
- data/lib/arel/nodes/infix_operation.rb +80 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +50 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +67 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +16 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +27 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +45 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +41 -0
- data/lib/arel/nodes/values_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +257 -0
- data/lib/arel/select_manager.rb +271 -0
- data/lib/arel/table.rb +110 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors.rb +20 -0
- data/lib/arel/visitors/depth_first.rb +204 -0
- data/lib/arel/visitors/dot.rb +297 -0
- data/lib/arel/visitors/ibm_db.rb +34 -0
- data/lib/arel/visitors/informix.rb +62 -0
- data/lib/arel/visitors/mssql.rb +157 -0
- data/lib/arel/visitors/mysql.rb +83 -0
- data/lib/arel/visitors/oracle.rb +159 -0
- data/lib/arel/visitors/oracle12.rb +66 -0
- data/lib/arel/visitors/postgresql.rb +110 -0
- data/lib/arel/visitors/sqlite.rb +39 -0
- data/lib/arel/visitors/to_sql.rb +889 -0
- data/lib/arel/visitors/visitor.rb +46 -0
- data/lib/arel/visitors/where_sql.rb +23 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/rails/generators/active_record/migration.rb +14 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +2 -5
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +1 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +1 -0
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
- metadata +109 -24
- data/lib/active_record/collection_cache_key.rb +0 -53
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
# = Active Record Touch Later
|
5
|
-
module TouchLater
|
5
|
+
module TouchLater # :nodoc:
|
6
6
|
extend ActiveSupport::Concern
|
7
7
|
|
8
8
|
included do
|
@@ -22,7 +22,8 @@ module ActiveRecord
|
|
22
22
|
@_touch_time = current_time_from_proper_timezone
|
23
23
|
|
24
24
|
surreptitiously_touch @_defer_touch_attrs
|
25
|
-
|
25
|
+
add_to_transaction
|
26
|
+
@_new_record_before_last_commit ||= false
|
26
27
|
|
27
28
|
# touch the parents as we are not calling the after_save callbacks
|
28
29
|
self.class.reflect_on_all_associations(:belongs_to).each do |r|
|
@@ -48,6 +49,7 @@ module ActiveRecord
|
|
48
49
|
|
49
50
|
def touch_deferred_attributes
|
50
51
|
if has_defer_touch_attrs? && persisted?
|
52
|
+
@_skip_dirty_tracking = true
|
51
53
|
touch(*@_defer_touch_attrs, time: @_touch_time)
|
52
54
|
@_defer_touch_attrs, @_touch_time = nil, nil
|
53
55
|
end
|
@@ -234,6 +234,12 @@ module ActiveRecord
|
|
234
234
|
set_callback(:commit, :after, *args, &block)
|
235
235
|
end
|
236
236
|
|
237
|
+
# Shortcut for <tt>after_commit :hook, on: [ :create, :update ]</tt>.
|
238
|
+
def after_save_commit(*args, &block)
|
239
|
+
set_options_for_callbacks!(args, on: [ :create, :update ])
|
240
|
+
set_callback(:commit, :after, *args, &block)
|
241
|
+
end
|
242
|
+
|
237
243
|
# Shortcut for <tt>after_commit :hook, on: :create</tt>.
|
238
244
|
def after_create_commit(*args, &block)
|
239
245
|
set_options_for_callbacks!(args, on: :create)
|
@@ -306,9 +312,7 @@ module ActiveRecord
|
|
306
312
|
end
|
307
313
|
|
308
314
|
def save(*) #:nodoc:
|
309
|
-
|
310
|
-
with_transaction_returning_status { super }
|
311
|
-
end
|
315
|
+
with_transaction_returning_status { super }
|
312
316
|
end
|
313
317
|
|
314
318
|
def save!(*) #:nodoc:
|
@@ -319,17 +323,6 @@ module ActiveRecord
|
|
319
323
|
with_transaction_returning_status { super }
|
320
324
|
end
|
321
325
|
|
322
|
-
# Reset id and @new_record if the transaction rolls back.
|
323
|
-
def rollback_active_record_state!
|
324
|
-
remember_transaction_record_state
|
325
|
-
yield
|
326
|
-
rescue Exception
|
327
|
-
restore_transaction_record_state
|
328
|
-
raise
|
329
|
-
ensure
|
330
|
-
clear_transaction_record_state
|
331
|
-
end
|
332
|
-
|
333
326
|
def before_committed! # :nodoc:
|
334
327
|
_run_before_commit_without_transaction_enrollment_callbacks
|
335
328
|
_run_before_commit_callbacks
|
@@ -341,7 +334,7 @@ module ActiveRecord
|
|
341
334
|
# but call it after the commit of a destroyed object.
|
342
335
|
def committed!(should_run_callbacks: true) #:nodoc:
|
343
336
|
force_clear_transaction_record_state
|
344
|
-
if should_run_callbacks
|
337
|
+
if should_run_callbacks
|
345
338
|
@_committed_already_called = true
|
346
339
|
_run_commit_without_transaction_enrollment_callbacks
|
347
340
|
_run_commit_callbacks
|
@@ -362,18 +355,6 @@ module ActiveRecord
|
|
362
355
|
clear_transaction_record_state
|
363
356
|
end
|
364
357
|
|
365
|
-
# Add the record to the current transaction so that the #after_rollback and #after_commit callbacks
|
366
|
-
# can be called.
|
367
|
-
def add_to_transaction
|
368
|
-
if has_transactional_callbacks?
|
369
|
-
self.class.connection.add_transaction_record(self)
|
370
|
-
else
|
371
|
-
sync_with_transaction_state
|
372
|
-
set_transaction_state(self.class.connection.transaction_state)
|
373
|
-
end
|
374
|
-
remember_transaction_record_state
|
375
|
-
end
|
376
|
-
|
377
358
|
# Executes +method+ within a transaction and captures its return value as a
|
378
359
|
# status flag. If the status is true the transaction is committed, otherwise
|
379
360
|
# a ROLLBACK is issued. In any case the status flag is returned.
|
@@ -383,35 +364,40 @@ module ActiveRecord
|
|
383
364
|
def with_transaction_returning_status
|
384
365
|
status = nil
|
385
366
|
self.class.transaction do
|
386
|
-
|
367
|
+
if has_transactional_callbacks?
|
368
|
+
add_to_transaction
|
369
|
+
else
|
370
|
+
sync_with_transaction_state if @transaction_state&.finalized?
|
371
|
+
@transaction_state = self.class.connection.transaction_state
|
372
|
+
end
|
373
|
+
remember_transaction_record_state
|
374
|
+
|
387
375
|
status = yield
|
388
376
|
raise ActiveRecord::Rollback unless status
|
389
377
|
end
|
390
378
|
status
|
391
|
-
ensure
|
392
|
-
if @transaction_state && @transaction_state.committed?
|
393
|
-
clear_transaction_record_state
|
394
|
-
end
|
395
379
|
end
|
396
380
|
|
397
|
-
|
398
|
-
|
381
|
+
def trigger_transactional_callbacks? # :nodoc:
|
382
|
+
(@_new_record_before_last_commit || _trigger_update_callback) && persisted? ||
|
383
|
+
_trigger_destroy_callback && destroyed?
|
384
|
+
end
|
399
385
|
|
400
386
|
private
|
387
|
+
attr_reader :_committed_already_called, :_trigger_update_callback, :_trigger_destroy_callback
|
401
388
|
|
402
389
|
# Save the new record state and id of a record so it can be restored later if a transaction fails.
|
403
390
|
def remember_transaction_record_state
|
404
|
-
@_start_transaction_state
|
391
|
+
@_start_transaction_state ||= {
|
405
392
|
id: id,
|
406
393
|
new_record: @new_record,
|
407
394
|
destroyed: @destroyed,
|
395
|
+
attributes: @attributes,
|
408
396
|
frozen?: frozen?,
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
end
|
397
|
+
level: 0
|
398
|
+
}
|
399
|
+
@_start_transaction_state[:level] += 1
|
413
400
|
|
414
|
-
def remember_new_record_before_last_commit
|
415
401
|
if _committed_already_called
|
416
402
|
@_new_record_before_last_commit = false
|
417
403
|
else
|
@@ -421,27 +407,32 @@ module ActiveRecord
|
|
421
407
|
|
422
408
|
# Clear the new record state and id of a record.
|
423
409
|
def clear_transaction_record_state
|
424
|
-
|
410
|
+
return unless @_start_transaction_state
|
411
|
+
@_start_transaction_state[:level] -= 1
|
425
412
|
force_clear_transaction_record_state if @_start_transaction_state[:level] < 1
|
426
413
|
end
|
427
414
|
|
428
415
|
# Force to clear the transaction record state.
|
429
416
|
def force_clear_transaction_record_state
|
430
|
-
@_start_transaction_state
|
417
|
+
@_start_transaction_state = nil
|
418
|
+
@transaction_state = nil
|
431
419
|
end
|
432
420
|
|
433
421
|
# Restore the new record state and id of a record that was previously saved by a call to save_record_state.
|
434
|
-
def restore_transaction_record_state(
|
435
|
-
|
436
|
-
|
437
|
-
if transaction_level < 1 || force
|
438
|
-
restore_state = @_start_transaction_state
|
439
|
-
thaw
|
422
|
+
def restore_transaction_record_state(force_restore_state = false)
|
423
|
+
if restore_state = @_start_transaction_state
|
424
|
+
if force_restore_state || restore_state[:level] <= 1
|
440
425
|
@new_record = restore_state[:new_record]
|
441
426
|
@destroyed = restore_state[:destroyed]
|
442
|
-
|
443
|
-
|
444
|
-
|
427
|
+
@attributes = restore_state[:attributes].map do |attr|
|
428
|
+
value = @attributes.fetch_value(attr.name)
|
429
|
+
attr = attr.with_value_from_user(value) if attr.value != value
|
430
|
+
attr
|
431
|
+
end
|
432
|
+
@mutations_from_database = nil
|
433
|
+
@mutations_before_last_save = nil
|
434
|
+
if @attributes.fetch_value(@primary_key) != restore_state[:id]
|
435
|
+
@attributes.write_from_user(@primary_key, restore_state[:id])
|
445
436
|
end
|
446
437
|
freeze if restore_state[:frozen?]
|
447
438
|
end
|
@@ -462,8 +453,10 @@ module ActiveRecord
|
|
462
453
|
end
|
463
454
|
end
|
464
455
|
|
465
|
-
|
466
|
-
|
456
|
+
# Add the record to the current transaction so that the #after_rollback and #after_commit
|
457
|
+
# callbacks can be called.
|
458
|
+
def add_to_transaction
|
459
|
+
self.class.connection.add_transaction_record(self)
|
467
460
|
end
|
468
461
|
|
469
462
|
def has_transactional_callbacks?
|
@@ -483,19 +476,17 @@ module ActiveRecord
|
|
483
476
|
# This method checks to see if the ActiveRecord object's state reflects
|
484
477
|
# the TransactionState, and rolls back or commits the Active Record object
|
485
478
|
# as appropriate.
|
486
|
-
#
|
487
|
-
# Since Active Record objects can be inside multiple transactions, this
|
488
|
-
# method recursively goes through the parent of the TransactionState and
|
489
|
-
# checks if the Active Record object reflects the state of the object.
|
490
479
|
def sync_with_transaction_state
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
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
|
499
490
|
end
|
500
491
|
end
|
501
492
|
end
|
data/lib/active_record/type.rb
CHANGED
@@ -48,12 +48,11 @@ module ActiveRecord
|
|
48
48
|
|
49
49
|
private
|
50
50
|
|
51
|
-
|
52
|
-
|
53
|
-
|
51
|
+
def current_adapter_name
|
52
|
+
ActiveRecord::Base.connection.adapter_name.downcase.to_sym
|
53
|
+
end
|
54
54
|
end
|
55
55
|
|
56
|
-
Helpers = ActiveModel::Type::Helpers
|
57
56
|
BigInteger = ActiveModel::Type::BigInteger
|
58
57
|
Binary = ActiveModel::Type::Binary
|
59
58
|
Boolean = ActiveModel::Type::Boolean
|
@@ -52,8 +52,6 @@ module ActiveRecord
|
|
52
52
|
priority <=> other.priority
|
53
53
|
end
|
54
54
|
|
55
|
-
# TODO Change this to private once we've dropped Ruby 2.2 support.
|
56
|
-
# Workaround for Ruby 2.2 "private attribute?" warning.
|
57
55
|
protected
|
58
56
|
|
59
57
|
attr_reader :name, :block, :adapter, :override
|
@@ -114,13 +112,8 @@ module ActiveRecord
|
|
114
112
|
super | 4
|
115
113
|
end
|
116
114
|
|
117
|
-
# TODO Change this to private once we've dropped Ruby 2.2 support.
|
118
|
-
# Workaround for Ruby 2.2 "private attribute?" warning.
|
119
|
-
protected
|
120
|
-
|
121
|
-
attr_reader :options, :klass
|
122
|
-
|
123
115
|
private
|
116
|
+
attr_reader :options, :klass
|
124
117
|
|
125
118
|
def matches_options?(**kwargs)
|
126
119
|
options.all? do |key, value|
|
@@ -8,26 +8,27 @@ module ActiveRecord
|
|
8
8
|
@table_name = table_name
|
9
9
|
end
|
10
10
|
|
11
|
-
def type_cast_for_database(
|
11
|
+
def type_cast_for_database(attr_name, value)
|
12
12
|
return value if value.is_a?(Arel::Nodes::BindParam)
|
13
|
-
|
14
|
-
|
13
|
+
type = type_for_attribute(attr_name)
|
14
|
+
type.serialize(value)
|
15
15
|
end
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
protected
|
17
|
+
def type_for_attribute(attr_name)
|
18
|
+
schema_cache = connection.schema_cache
|
20
19
|
|
21
|
-
|
22
|
-
|
20
|
+
if schema_cache.data_source_exists?(table_name)
|
21
|
+
column = schema_cache.columns_hash(table_name)[attr_name.to_s]
|
22
|
+
type = connection.lookup_cast_type_from_column(column) if column
|
23
|
+
end
|
23
24
|
|
24
|
-
|
25
|
+
type || Type.default_value
|
26
|
+
end
|
25
27
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
end
|
28
|
+
delegate :connection, to: :@klass, private: true
|
29
|
+
|
30
|
+
private
|
31
|
+
attr_reader :table_name
|
31
32
|
end
|
32
33
|
end
|
33
34
|
end
|
@@ -40,6 +40,7 @@ module ActiveRecord
|
|
40
40
|
include ActiveModel::Validations
|
41
41
|
|
42
42
|
# The validation process on save can be skipped by passing <tt>validate: false</tt>.
|
43
|
+
# The validation context can be changed by passing <tt>context: context</tt>.
|
43
44
|
# The regular {ActiveRecord::Base#save}[rdoc-ref:Persistence#save] method is replaced
|
44
45
|
# with this when the validations module is mixed in, which it is by default.
|
45
46
|
def save(options = {})
|
@@ -12,7 +12,7 @@ module ActiveRecord
|
|
12
12
|
raise ArgumentError, "#{options[:scope]} is not supported format for :scope option. " \
|
13
13
|
"Pass a symbol or an array of symbols instead: `scope: :user_id`"
|
14
14
|
end
|
15
|
-
super
|
15
|
+
super
|
16
16
|
@klass = options[:class]
|
17
17
|
end
|
18
18
|
|
@@ -25,7 +25,7 @@ module ActiveRecord
|
|
25
25
|
if finder_class.primary_key
|
26
26
|
relation = relation.where.not(finder_class.primary_key => record.id_in_database)
|
27
27
|
else
|
28
|
-
raise UnknownPrimaryKey.new(finder_class, "
|
28
|
+
raise UnknownPrimaryKey.new(finder_class, "Cannot validate uniqueness for persisted record without primary key.")
|
29
29
|
end
|
30
30
|
end
|
31
31
|
relation = scope_relation(record, relation)
|
@@ -56,33 +56,21 @@ module ActiveRecord
|
|
56
56
|
end
|
57
57
|
|
58
58
|
def build_relation(klass, attribute, value)
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
59
|
+
relation = klass.unscoped
|
60
|
+
comparison = relation.bind_attribute(attribute, value) do |attr, bind|
|
61
|
+
return relation.none! if bind.unboundable?
|
62
|
+
|
63
|
+
if !options.key?(:case_sensitive) || bind.nil?
|
64
|
+
klass.connection.default_uniqueness_comparison(attr, bind, klass)
|
65
|
+
elsif options[:case_sensitive]
|
66
|
+
klass.connection.case_sensitive_comparison(attr, bind)
|
67
|
+
else
|
68
|
+
# will use SQL LOWER function before comparison, unless it detects a case insensitive collation
|
69
|
+
klass.connection.case_insensitive_comparison(attr, bind)
|
70
|
+
end
|
71
71
|
end
|
72
72
|
|
73
|
-
|
74
|
-
value = klass.predicate_builder.build_bind_attribute(attribute_name, value)
|
75
|
-
|
76
|
-
table = klass.arel_table
|
77
|
-
column = klass.columns_hash[attribute_name]
|
78
|
-
|
79
|
-
comparison = if !options[:case_sensitive]
|
80
|
-
# will use SQL LOWER function before comparison, unless it detects a case insensitive collation
|
81
|
-
klass.connection.case_insensitive_comparison(table, attribute, column, value)
|
82
|
-
else
|
83
|
-
klass.connection.case_sensitive_comparison(table, attribute, column, value)
|
84
|
-
end
|
85
|
-
klass.unscoped.where!(comparison)
|
73
|
+
relation.where!(comparison)
|
86
74
|
end
|
87
75
|
|
88
76
|
def scope_relation(record, relation)
|
data/lib/arel.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "arel/errors"
|
4
|
+
|
5
|
+
require "arel/crud"
|
6
|
+
require "arel/factory_methods"
|
7
|
+
|
8
|
+
require "arel/expressions"
|
9
|
+
require "arel/predications"
|
10
|
+
require "arel/window_predications"
|
11
|
+
require "arel/math"
|
12
|
+
require "arel/alias_predication"
|
13
|
+
require "arel/order_predications"
|
14
|
+
require "arel/table"
|
15
|
+
require "arel/attributes"
|
16
|
+
|
17
|
+
require "arel/visitors"
|
18
|
+
require "arel/collectors/sql_string"
|
19
|
+
|
20
|
+
require "arel/tree_manager"
|
21
|
+
require "arel/insert_manager"
|
22
|
+
require "arel/select_manager"
|
23
|
+
require "arel/update_manager"
|
24
|
+
require "arel/delete_manager"
|
25
|
+
require "arel/nodes"
|
26
|
+
|
27
|
+
module Arel
|
28
|
+
VERSION = "10.0.0"
|
29
|
+
|
30
|
+
# Wrap a known-safe SQL string for passing to query methods, e.g.
|
31
|
+
#
|
32
|
+
# Post.order(Arel.sql("length(title)")).last
|
33
|
+
#
|
34
|
+
# Great caution should be taken to avoid SQL injection vulnerabilities.
|
35
|
+
# This method should not be used with unsafe values such as request
|
36
|
+
# parameters or model attributes.
|
37
|
+
def self.sql(raw_sql)
|
38
|
+
Arel::Nodes::SqlLiteral.new raw_sql
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.star # :nodoc:
|
42
|
+
sql "*"
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.arel_node?(value) # :nodoc:
|
46
|
+
value.is_a?(Arel::Node) || value.is_a?(Arel::Attribute) || value.is_a?(Arel::Nodes::SqlLiteral)
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.fetch_attribute(value) # :nodoc:
|
50
|
+
case value
|
51
|
+
when Arel::Nodes::Between, Arel::Nodes::In, Arel::Nodes::NotIn, Arel::Nodes::Equality, Arel::Nodes::NotEqual, Arel::Nodes::LessThan, Arel::Nodes::LessThanOrEqual, Arel::Nodes::GreaterThan, Arel::Nodes::GreaterThanOrEqual
|
52
|
+
yield value.left.is_a?(Arel::Attributes::Attribute) ? value.left : value.right
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
## Convenience Alias
|
57
|
+
Node = Arel::Nodes::Node # :nodoc:
|
58
|
+
end
|