activerecord 5.0.7 → 5.1.7
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 +5 -5
- data/CHANGELOG.md +657 -2080
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/examples/performance.rb +28 -28
- data/examples/simple.rb +3 -3
- data/lib/active_record/aggregations.rb +244 -244
- data/lib/active_record/association_relation.rb +5 -5
- data/lib/active_record/associations/alias_tracker.rb +10 -11
- data/lib/active_record/associations/association.rb +23 -5
- data/lib/active_record/associations/association_scope.rb +95 -81
- data/lib/active_record/associations/belongs_to_association.rb +7 -4
- data/lib/active_record/associations/builder/belongs_to.rb +30 -16
- data/lib/active_record/associations/builder/collection_association.rb +1 -2
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +27 -27
- data/lib/active_record/associations/collection_association.rb +36 -205
- data/lib/active_record/associations/collection_proxy.rb +132 -63
- data/lib/active_record/associations/has_many_association.rb +10 -19
- data/lib/active_record/associations/has_many_through_association.rb +12 -4
- data/lib/active_record/associations/has_one_association.rb +24 -28
- data/lib/active_record/associations/has_one_through_association.rb +5 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +4 -28
- data/lib/active_record/associations/join_dependency/join_base.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_part.rb +1 -1
- data/lib/active_record/associations/join_dependency.rb +121 -118
- data/lib/active_record/associations/preloader/association.rb +64 -64
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -2
- data/lib/active_record/associations/preloader/collection_association.rb +6 -6
- data/lib/active_record/associations/preloader/has_many.rb +0 -2
- data/lib/active_record/associations/preloader/singular_association.rb +6 -8
- data/lib/active_record/associations/preloader/through_association.rb +41 -41
- data/lib/active_record/associations/preloader.rb +94 -94
- data/lib/active_record/associations/singular_association.rb +8 -25
- data/lib/active_record/associations/through_association.rb +2 -5
- data/lib/active_record/associations.rb +1591 -1562
- data/lib/active_record/attribute/user_provided_default.rb +4 -2
- data/lib/active_record/attribute.rb +98 -71
- data/lib/active_record/attribute_assignment.rb +61 -61
- data/lib/active_record/attribute_decorators.rb +35 -13
- data/lib/active_record/attribute_methods/before_type_cast.rb +7 -7
- data/lib/active_record/attribute_methods/dirty.rb +229 -46
- data/lib/active_record/attribute_methods/primary_key.rb +74 -73
- data/lib/active_record/attribute_methods/read.rb +39 -35
- data/lib/active_record/attribute_methods/serialization.rb +7 -7
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +35 -58
- data/lib/active_record/attribute_methods/write.rb +30 -33
- data/lib/active_record/attribute_methods.rb +56 -65
- data/lib/active_record/attribute_mutation_tracker.rb +63 -11
- data/lib/active_record/attribute_set/builder.rb +27 -33
- data/lib/active_record/attribute_set/yaml_encoder.rb +41 -0
- data/lib/active_record/attribute_set.rb +9 -6
- data/lib/active_record/attributes.rb +22 -22
- data/lib/active_record/autosave_association.rb +18 -13
- data/lib/active_record/base.rb +24 -22
- data/lib/active_record/callbacks.rb +56 -14
- data/lib/active_record/coders/yaml_column.rb +9 -11
- data/lib/active_record/collection_cache_key.rb +3 -4
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +330 -284
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +1 -3
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +39 -37
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +32 -27
- data/lib/active_record/connection_adapters/abstract/quoting.rb +62 -51
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +10 -20
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +74 -79
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +53 -41
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +120 -100
- data/lib/active_record/connection_adapters/abstract/transaction.rb +49 -43
- data/lib/active_record/connection_adapters/abstract_adapter.rb +165 -135
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +404 -424
- data/lib/active_record/connection_adapters/column.rb +26 -4
- data/lib/active_record/connection_adapters/connection_specification.rb +128 -118
- data/lib/active_record/connection_adapters/mysql/column.rb +6 -31
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +36 -49
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +22 -22
- data/lib/active_record/connection_adapters/mysql/quoting.rb +6 -12
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +49 -45
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +16 -19
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -28
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +43 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +7 -6
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +23 -27
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +32 -53
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +16 -16
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +0 -10
- data/lib/active_record/connection_adapters/postgresql/oid/{rails_5_1_point.rb → legacy_point.rb} +9 -16
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +28 -8
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +32 -30
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +51 -51
- data/lib/active_record/connection_adapters/postgresql/oid.rb +22 -21
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +40 -35
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +37 -24
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +19 -23
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +182 -222
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +6 -4
- data/lib/active_record/connection_adapters/postgresql/utils.rb +7 -5
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +198 -167
- data/lib/active_record/connection_adapters/schema_cache.rb +16 -7
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +3 -3
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +1 -1
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +16 -19
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +1 -8
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +28 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +17 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +32 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +184 -167
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -7
- data/lib/active_record/connection_handling.rb +14 -26
- data/lib/active_record/core.rb +109 -93
- data/lib/active_record/counter_cache.rb +60 -13
- data/lib/active_record/define_callbacks.rb +20 -0
- data/lib/active_record/dynamic_matchers.rb +80 -79
- data/lib/active_record/enum.rb +8 -6
- data/lib/active_record/errors.rb +64 -15
- data/lib/active_record/explain.rb +1 -2
- data/lib/active_record/explain_registry.rb +1 -1
- data/lib/active_record/explain_subscriber.rb +7 -4
- data/lib/active_record/fixture_set/file.rb +11 -8
- data/lib/active_record/fixtures.rb +66 -53
- data/lib/active_record/gem_version.rb +1 -1
- data/lib/active_record/inheritance.rb +93 -79
- data/lib/active_record/integration.rb +7 -7
- data/lib/active_record/internal_metadata.rb +3 -16
- data/lib/active_record/legacy_yaml_adapter.rb +1 -1
- data/lib/active_record/locking/optimistic.rb +69 -74
- data/lib/active_record/locking/pessimistic.rb +10 -1
- data/lib/active_record/log_subscriber.rb +23 -28
- data/lib/active_record/migration/command_recorder.rb +94 -94
- data/lib/active_record/migration/compatibility.rb +100 -47
- data/lib/active_record/migration/join_table.rb +6 -6
- data/lib/active_record/migration.rb +153 -155
- data/lib/active_record/model_schema.rb +94 -107
- data/lib/active_record/nested_attributes.rb +200 -199
- data/lib/active_record/null_relation.rb +11 -34
- data/lib/active_record/persistence.rb +65 -50
- data/lib/active_record/query_cache.rb +2 -6
- data/lib/active_record/querying.rb +3 -4
- data/lib/active_record/railtie.rb +16 -17
- data/lib/active_record/railties/controller_runtime.rb +6 -2
- data/lib/active_record/railties/databases.rake +105 -133
- data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
- data/lib/active_record/readonly_attributes.rb +2 -2
- data/lib/active_record/reflection.rb +154 -108
- data/lib/active_record/relation/batches/batch_enumerator.rb +1 -1
- data/lib/active_record/relation/batches.rb +80 -51
- data/lib/active_record/relation/calculations.rb +169 -162
- data/lib/active_record/relation/delegation.rb +32 -31
- data/lib/active_record/relation/finder_methods.rb +197 -231
- data/lib/active_record/relation/merger.rb +58 -62
- data/lib/active_record/relation/predicate_builder/array_handler.rb +7 -5
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +23 -23
- data/lib/active_record/relation/predicate_builder/base_handler.rb +3 -1
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +0 -8
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +12 -10
- data/lib/active_record/relation/predicate_builder/range_handler.rb +0 -8
- data/lib/active_record/relation/predicate_builder.rb +92 -89
- data/lib/active_record/relation/query_attribute.rb +1 -1
- data/lib/active_record/relation/query_methods.rb +255 -293
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +4 -5
- data/lib/active_record/relation/where_clause.rb +80 -65
- data/lib/active_record/relation/where_clause_factory.rb +47 -8
- data/lib/active_record/relation.rb +93 -119
- data/lib/active_record/result.rb +41 -32
- data/lib/active_record/runtime_registry.rb +3 -3
- data/lib/active_record/sanitization.rb +176 -192
- data/lib/active_record/schema.rb +3 -3
- data/lib/active_record/schema_dumper.rb +15 -38
- data/lib/active_record/schema_migration.rb +8 -4
- data/lib/active_record/scoping/default.rb +90 -90
- data/lib/active_record/scoping/named.rb +11 -11
- data/lib/active_record/scoping.rb +6 -6
- data/lib/active_record/secure_token.rb +2 -2
- data/lib/active_record/statement_cache.rb +13 -15
- data/lib/active_record/store.rb +31 -32
- data/lib/active_record/suppressor.rb +2 -1
- data/lib/active_record/table_metadata.rb +9 -5
- data/lib/active_record/tasks/database_tasks.rb +65 -55
- data/lib/active_record/tasks/mysql_database_tasks.rb +76 -73
- data/lib/active_record/tasks/postgresql_database_tasks.rb +72 -47
- data/lib/active_record/tasks/sqlite_database_tasks.rb +18 -16
- data/lib/active_record/timestamp.rb +46 -25
- data/lib/active_record/touch_later.rb +1 -2
- data/lib/active_record/transactions.rb +97 -109
- data/lib/active_record/type/adapter_specific_registry.rb +46 -42
- data/lib/active_record/type/decimal_without_scale.rb +13 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +3 -3
- data/lib/active_record/type/internal/abstract_json.rb +4 -0
- data/lib/active_record/type/serialized.rb +14 -8
- data/lib/active_record/type/text.rb +9 -0
- data/lib/active_record/type/time.rb +0 -1
- data/lib/active_record/type/type_map.rb +11 -15
- data/lib/active_record/type/unsigned_integer.rb +15 -0
- data/lib/active_record/type.rb +17 -13
- data/lib/active_record/type_caster/connection.rb +8 -6
- data/lib/active_record/type_caster/map.rb +3 -1
- data/lib/active_record/type_caster.rb +2 -2
- data/lib/active_record/validations/associated.rb +1 -1
- data/lib/active_record/validations/presence.rb +2 -2
- data/lib/active_record/validations/uniqueness.rb +8 -39
- data/lib/active_record/validations.rb +4 -4
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +20 -20
- data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -34
- data/lib/rails/generators/active_record/migration.rb +1 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +9 -9
- data/lib/rails/generators/active_record.rb +4 -4
- metadata +24 -13
- data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
@@ -8,20 +8,20 @@ module ActiveRecord
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def create
|
11
|
-
raise DatabaseAlreadyExists if File.exist?(configuration[
|
11
|
+
raise DatabaseAlreadyExists if File.exist?(configuration["database"])
|
12
12
|
|
13
13
|
establish_connection configuration
|
14
14
|
connection
|
15
15
|
end
|
16
16
|
|
17
17
|
def drop
|
18
|
-
require
|
19
|
-
path = Pathname.new configuration[
|
18
|
+
require "pathname"
|
19
|
+
path = Pathname.new configuration["database"]
|
20
20
|
file = path.absolute? ? path.to_s : File.join(root, path)
|
21
21
|
|
22
22
|
FileUtils.rm(file)
|
23
23
|
rescue Errno::ENOENT => error
|
24
|
-
raise NoDatabaseError.new(error.message
|
24
|
+
raise NoDatabaseError.new(error.message)
|
25
25
|
end
|
26
26
|
|
27
27
|
def purge
|
@@ -35,25 +35,27 @@ module ActiveRecord
|
|
35
35
|
connection.encoding
|
36
36
|
end
|
37
37
|
|
38
|
-
def structure_dump(filename)
|
39
|
-
dbfile = configuration[
|
40
|
-
|
38
|
+
def structure_dump(filename, extra_flags)
|
39
|
+
dbfile = configuration["database"]
|
40
|
+
flags = extra_flags.join(" ") if extra_flags
|
41
|
+
`sqlite3 #{flags} #{dbfile} .schema > #{filename}`
|
41
42
|
end
|
42
43
|
|
43
|
-
def structure_load(filename)
|
44
|
-
dbfile = configuration[
|
45
|
-
|
44
|
+
def structure_load(filename, extra_flags)
|
45
|
+
dbfile = configuration["database"]
|
46
|
+
flags = extra_flags.join(" ") if extra_flags
|
47
|
+
`sqlite3 #{flags} #{dbfile} < "#{filename}"`
|
46
48
|
end
|
47
49
|
|
48
50
|
private
|
49
51
|
|
50
|
-
|
51
|
-
|
52
|
-
|
52
|
+
def configuration
|
53
|
+
@configuration
|
54
|
+
end
|
53
55
|
|
54
|
-
|
55
|
-
|
56
|
-
|
56
|
+
def root
|
57
|
+
@root
|
58
|
+
end
|
57
59
|
end
|
58
60
|
end
|
59
61
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module ActiveRecord
|
2
3
|
# = Active Record \Timestamp
|
3
4
|
#
|
@@ -51,15 +52,48 @@ module ActiveRecord
|
|
51
52
|
clear_timestamp_attributes
|
52
53
|
end
|
53
54
|
|
55
|
+
class_methods do
|
56
|
+
def touch_attributes_with_time(*names, time: nil)
|
57
|
+
attribute_names = timestamp_attributes_for_update_in_model
|
58
|
+
attribute_names |= names.map(&:to_s)
|
59
|
+
time ||= current_time_from_proper_timezone
|
60
|
+
attribute_names.each_with_object({}) { |attr_name, result| result[attr_name] = time }
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
def timestamp_attributes_for_create_in_model
|
65
|
+
timestamp_attributes_for_create.select { |c| column_names.include?(c) }
|
66
|
+
end
|
67
|
+
|
68
|
+
def timestamp_attributes_for_update_in_model
|
69
|
+
timestamp_attributes_for_update.select { |c| column_names.include?(c) }
|
70
|
+
end
|
71
|
+
|
72
|
+
def all_timestamp_attributes_in_model
|
73
|
+
timestamp_attributes_for_create_in_model + timestamp_attributes_for_update_in_model
|
74
|
+
end
|
75
|
+
|
76
|
+
def timestamp_attributes_for_create
|
77
|
+
["created_at", "created_on"]
|
78
|
+
end
|
79
|
+
|
80
|
+
def timestamp_attributes_for_update
|
81
|
+
["updated_at", "updated_on"]
|
82
|
+
end
|
83
|
+
|
84
|
+
def current_time_from_proper_timezone
|
85
|
+
default_timezone == :utc ? Time.now.utc : Time.now
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
54
89
|
private
|
55
90
|
|
56
91
|
def _create_record
|
57
|
-
if
|
92
|
+
if record_timestamps
|
58
93
|
current_time = current_time_from_proper_timezone
|
59
94
|
|
60
|
-
|
61
|
-
|
62
|
-
if has_attribute?(column) && !attribute_present?(column)
|
95
|
+
all_timestamp_attributes_in_model.each do |column|
|
96
|
+
if !attribute_present?(column)
|
63
97
|
write_attribute(column, current_time)
|
64
98
|
end
|
65
99
|
end
|
@@ -73,8 +107,7 @@ module ActiveRecord
|
|
73
107
|
current_time = current_time_from_proper_timezone
|
74
108
|
|
75
109
|
timestamp_attributes_for_update_in_model.each do |column|
|
76
|
-
|
77
|
-
next if attribute_changed?(column)
|
110
|
+
next if will_save_change_to_attribute?(column)
|
78
111
|
write_attribute(column, current_time)
|
79
112
|
end
|
80
113
|
end
|
@@ -82,34 +115,26 @@ module ActiveRecord
|
|
82
115
|
end
|
83
116
|
|
84
117
|
def should_record_timestamps?
|
85
|
-
|
118
|
+
record_timestamps && (!partial_writes? || has_changes_to_save?)
|
86
119
|
end
|
87
120
|
|
88
121
|
def timestamp_attributes_for_create_in_model
|
89
|
-
|
122
|
+
self.class.send(:timestamp_attributes_for_create_in_model)
|
90
123
|
end
|
91
124
|
|
92
125
|
def timestamp_attributes_for_update_in_model
|
93
|
-
|
126
|
+
self.class.send(:timestamp_attributes_for_update_in_model)
|
94
127
|
end
|
95
128
|
|
96
129
|
def all_timestamp_attributes_in_model
|
97
|
-
|
130
|
+
self.class.send(:all_timestamp_attributes_in_model)
|
98
131
|
end
|
99
132
|
|
100
|
-
def
|
101
|
-
|
102
|
-
end
|
103
|
-
|
104
|
-
def timestamp_attributes_for_create
|
105
|
-
[:created_at, :created_on]
|
106
|
-
end
|
107
|
-
|
108
|
-
def all_timestamp_attributes
|
109
|
-
timestamp_attributes_for_create + timestamp_attributes_for_update
|
133
|
+
def current_time_from_proper_timezone
|
134
|
+
self.class.send(:current_time_from_proper_timezone)
|
110
135
|
end
|
111
136
|
|
112
|
-
def max_updated_column_timestamp(timestamp_names = timestamp_attributes_for_update)
|
137
|
+
def max_updated_column_timestamp(timestamp_names = self.class.send(:timestamp_attributes_for_update))
|
113
138
|
timestamp_names
|
114
139
|
.map { |attr| self[attr] }
|
115
140
|
.compact
|
@@ -117,10 +142,6 @@ module ActiveRecord
|
|
117
142
|
.max
|
118
143
|
end
|
119
144
|
|
120
|
-
def current_time_from_proper_timezone
|
121
|
-
self.class.default_timezone == :utc ? Time.now.utc : Time.now
|
122
|
-
end
|
123
|
-
|
124
145
|
# Clear attributes and changed_attributes
|
125
146
|
def clear_timestamp_attributes
|
126
147
|
all_timestamp_attributes_in_model.each do |attribute_name|
|
@@ -25,7 +25,7 @@ module ActiveRecord
|
|
25
25
|
# touch the parents as we are not calling the after_save callbacks
|
26
26
|
self.class.reflect_on_all_associations(:belongs_to).each do |r|
|
27
27
|
if touch = r.options[:touch]
|
28
|
-
ActiveRecord::Associations::Builder::BelongsTo.touch_record(self, r.foreign_key, r.name, touch, :touch_later)
|
28
|
+
ActiveRecord::Associations::Builder::BelongsTo.touch_record(self, changes_to_save, r.foreign_key, r.name, touch, :touch_later)
|
29
29
|
end
|
30
30
|
end
|
31
31
|
end
|
@@ -58,6 +58,5 @@ module ActiveRecord
|
|
58
58
|
def belongs_to_touch_method
|
59
59
|
:touch_later
|
60
60
|
end
|
61
|
-
|
62
61
|
end
|
63
62
|
end
|
@@ -11,7 +11,6 @@ module ActiveRecord
|
|
11
11
|
:before_commit_without_transaction_enrollment,
|
12
12
|
:commit_without_transaction_enrollment,
|
13
13
|
:rollback_without_transaction_enrollment,
|
14
|
-
terminator: deprecated_false_terminator,
|
15
14
|
scope: [:kind, :name]
|
16
15
|
end
|
17
16
|
|
@@ -189,8 +188,8 @@ module ActiveRecord
|
|
189
188
|
#
|
190
189
|
# === Caveats
|
191
190
|
#
|
192
|
-
# If you're on MySQL, then do not use DDL operations in nested
|
193
|
-
# blocks that are emulated with savepoints. That is, do not execute statements
|
191
|
+
# If you're on MySQL, then do not use Data Definition Language(DDL) operations in nested
|
192
|
+
# transactions blocks that are emulated with savepoints. That is, do not execute statements
|
194
193
|
# like 'CREATE TABLE' inside such blocks. This is because MySQL automatically
|
195
194
|
# releases all savepoints upon executing a DDL operation. When +transaction+
|
196
195
|
# is finished and tries to release the savepoint it created earlier, a
|
@@ -274,35 +273,25 @@ module ActiveRecord
|
|
274
273
|
set_callback(:rollback_without_transaction_enrollment, :after, *args, &block)
|
275
274
|
end
|
276
275
|
|
277
|
-
def raise_in_transactional_callbacks
|
278
|
-
ActiveSupport::Deprecation.warn('ActiveRecord::Base.raise_in_transactional_callbacks is deprecated and will be removed without replacement.')
|
279
|
-
true
|
280
|
-
end
|
281
|
-
|
282
|
-
def raise_in_transactional_callbacks=(value)
|
283
|
-
ActiveSupport::Deprecation.warn('ActiveRecord::Base.raise_in_transactional_callbacks= is deprecated, has no effect and will be removed without replacement.')
|
284
|
-
value
|
285
|
-
end
|
286
|
-
|
287
276
|
private
|
288
277
|
|
289
|
-
|
290
|
-
|
291
|
-
|
278
|
+
def set_options_for_callbacks!(args, enforced_options = {})
|
279
|
+
options = args.extract_options!.merge!(enforced_options)
|
280
|
+
args << options
|
292
281
|
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
282
|
+
if options[:on]
|
283
|
+
fire_on = Array(options[:on])
|
284
|
+
assert_valid_transaction_action(fire_on)
|
285
|
+
options[:if] = Array(options[:if])
|
286
|
+
options[:if].unshift("transaction_include_any_action?(#{fire_on})")
|
287
|
+
end
|
298
288
|
end
|
299
|
-
end
|
300
289
|
|
301
|
-
|
302
|
-
|
303
|
-
|
290
|
+
def assert_valid_transaction_action(actions)
|
291
|
+
if (actions - ACTIONS).any?
|
292
|
+
raise ArgumentError, ":on conditions for after_commit and after_rollback callbacks have to be one of #{ACTIONS}"
|
293
|
+
end
|
304
294
|
end
|
305
|
-
end
|
306
295
|
end
|
307
296
|
|
308
297
|
# See ActiveRecord::Transactions::ClassMethods for detailed documentation.
|
@@ -407,103 +396,102 @@ module ActiveRecord
|
|
407
396
|
end
|
408
397
|
end
|
409
398
|
|
410
|
-
|
411
|
-
|
412
|
-
# Save the new record state and id of a record so it can be restored later if a transaction fails.
|
413
|
-
def remember_transaction_record_state #:nodoc:
|
414
|
-
@_start_transaction_state[:id] = id
|
415
|
-
@_start_transaction_state.reverse_merge!(
|
416
|
-
new_record: @new_record,
|
417
|
-
destroyed: @destroyed,
|
418
|
-
frozen?: frozen?,
|
419
|
-
)
|
420
|
-
@_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) + 1
|
421
|
-
end
|
399
|
+
private
|
422
400
|
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
401
|
+
# Save the new record state and id of a record so it can be restored later if a transaction fails.
|
402
|
+
def remember_transaction_record_state
|
403
|
+
@_start_transaction_state[:id] = id
|
404
|
+
@_start_transaction_state.reverse_merge!(
|
405
|
+
new_record: @new_record,
|
406
|
+
destroyed: @destroyed,
|
407
|
+
frozen?: frozen?,
|
408
|
+
)
|
409
|
+
@_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) + 1
|
410
|
+
end
|
428
411
|
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
412
|
+
# Clear the new record state and id of a record.
|
413
|
+
def clear_transaction_record_state
|
414
|
+
@_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) - 1
|
415
|
+
force_clear_transaction_record_state if @_start_transaction_state[:level] < 1
|
416
|
+
end
|
433
417
|
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
418
|
+
# Force to clear the transaction record state.
|
419
|
+
def force_clear_transaction_record_state
|
420
|
+
@_start_transaction_state.clear
|
421
|
+
end
|
422
|
+
|
423
|
+
# Restore the new record state and id of a record that was previously saved by a call to save_record_state.
|
424
|
+
def restore_transaction_record_state(force = false)
|
425
|
+
unless @_start_transaction_state.empty?
|
426
|
+
transaction_level = (@_start_transaction_state[:level] || 0) - 1
|
427
|
+
if transaction_level < 1 || force
|
428
|
+
restore_state = @_start_transaction_state
|
429
|
+
thaw
|
430
|
+
@new_record = restore_state[:new_record]
|
431
|
+
@destroyed = restore_state[:destroyed]
|
432
|
+
pk = self.class.primary_key
|
433
|
+
if pk && read_attribute(pk) != restore_state[:id]
|
434
|
+
write_attribute(pk, restore_state[:id])
|
435
|
+
end
|
436
|
+
freeze if restore_state[:frozen?]
|
446
437
|
end
|
447
|
-
freeze if restore_state[:frozen?]
|
448
438
|
end
|
449
439
|
end
|
450
|
-
end
|
451
440
|
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
441
|
+
# Determine if a record was created or destroyed in a transaction. State should be one of :new_record or :destroyed.
|
442
|
+
def transaction_record_state(state)
|
443
|
+
@_start_transaction_state[state]
|
444
|
+
end
|
456
445
|
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
446
|
+
# Determine if a transaction included an action for :create, :update, or :destroy. Used in filtering callbacks.
|
447
|
+
def transaction_include_any_action?(actions)
|
448
|
+
actions.any? do |action|
|
449
|
+
case action
|
450
|
+
when :create
|
451
|
+
transaction_record_state(:new_record)
|
452
|
+
when :destroy
|
453
|
+
defined?(@_trigger_destroy_callback) && @_trigger_destroy_callback
|
454
|
+
when :update
|
455
|
+
!(transaction_record_state(:new_record) || destroyed?) &&
|
456
|
+
(defined?(@_trigger_update_callback) && @_trigger_update_callback)
|
457
|
+
end
|
467
458
|
end
|
468
459
|
end
|
469
|
-
end
|
470
|
-
|
471
|
-
private
|
472
460
|
|
473
|
-
|
474
|
-
|
475
|
-
|
461
|
+
def set_transaction_state(state)
|
462
|
+
@transaction_state = state
|
463
|
+
end
|
476
464
|
|
477
|
-
|
478
|
-
|
479
|
-
|
465
|
+
def has_transactional_callbacks?
|
466
|
+
!_rollback_callbacks.empty? || !_commit_callbacks.empty? || !_before_commit_callbacks.empty?
|
467
|
+
end
|
480
468
|
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
469
|
+
# Updates the attributes on this particular Active Record object so that
|
470
|
+
# if it's associated with a transaction, then the state of the Active Record
|
471
|
+
# object will be updated to reflect the current state of the transaction.
|
472
|
+
#
|
473
|
+
# The +@transaction_state+ variable stores the states of the associated
|
474
|
+
# transaction. This relies on the fact that a transaction can only be in
|
475
|
+
# one rollback or commit (otherwise a list of states would be required).
|
476
|
+
# Each Active Record object inside of a transaction carries that transaction's
|
477
|
+
# TransactionState.
|
478
|
+
#
|
479
|
+
# This method checks to see if the ActiveRecord object's state reflects
|
480
|
+
# the TransactionState, and rolls back or commits the Active Record object
|
481
|
+
# as appropriate.
|
482
|
+
#
|
483
|
+
# Since Active Record objects can be inside multiple transactions, this
|
484
|
+
# method recursively goes through the parent of the TransactionState and
|
485
|
+
# checks if the Active Record object reflects the state of the object.
|
486
|
+
def sync_with_transaction_state
|
487
|
+
update_attributes_from_transaction_state(@transaction_state)
|
488
|
+
end
|
501
489
|
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
490
|
+
def update_attributes_from_transaction_state(transaction_state)
|
491
|
+
if transaction_state && transaction_state.finalized?
|
492
|
+
restore_transaction_record_state if transaction_state.rolledback?
|
493
|
+
clear_transaction_record_state
|
494
|
+
end
|
506
495
|
end
|
507
|
-
end
|
508
496
|
end
|
509
497
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "active_model/type/registry"
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
# :stopdoc:
|
@@ -10,15 +10,15 @@ module ActiveRecord
|
|
10
10
|
|
11
11
|
private
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
def registration_klass
|
14
|
+
Registration
|
15
|
+
end
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
def find_registration(symbol, *args)
|
18
|
+
registrations
|
19
|
+
.select { |registration| registration.matches?(symbol, *args) }
|
20
|
+
.max
|
21
|
+
end
|
22
22
|
end
|
23
23
|
|
24
24
|
class Registration
|
@@ -50,44 +50,46 @@ module ActiveRecord
|
|
50
50
|
priority <=> other.priority
|
51
51
|
end
|
52
52
|
|
53
|
+
# TODO Change this to private once we've dropped Ruby 2.2 support.
|
54
|
+
# Workaround for Ruby 2.2 "private attribute?" warning.
|
53
55
|
protected
|
54
56
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
57
|
+
attr_reader :name, :block, :adapter, :override
|
58
|
+
|
59
|
+
def priority
|
60
|
+
result = 0
|
61
|
+
if adapter
|
62
|
+
result |= 1
|
63
|
+
end
|
64
|
+
if override
|
65
|
+
result |= 2
|
66
|
+
end
|
67
|
+
result
|
64
68
|
end
|
65
|
-
result
|
66
|
-
end
|
67
69
|
|
68
|
-
|
69
|
-
|
70
|
-
|
70
|
+
def priority_except_adapter
|
71
|
+
priority & 0b111111100
|
72
|
+
end
|
71
73
|
|
72
74
|
private
|
73
75
|
|
74
|
-
|
75
|
-
|
76
|
-
|
76
|
+
def matches_adapter?(adapter: nil, **)
|
77
|
+
(self.adapter.nil? || adapter == self.adapter)
|
78
|
+
end
|
77
79
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
80
|
+
def conflicts_with?(other)
|
81
|
+
same_priority_except_adapter?(other) &&
|
82
|
+
has_adapter_conflict?(other)
|
83
|
+
end
|
82
84
|
|
83
|
-
|
84
|
-
|
85
|
-
|
85
|
+
def same_priority_except_adapter?(other)
|
86
|
+
priority_except_adapter == other.priority_except_adapter
|
87
|
+
end
|
86
88
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
89
|
+
def has_adapter_conflict?(other)
|
90
|
+
(override.nil? && other.adapter) ||
|
91
|
+
(adapter && other.override.nil?)
|
92
|
+
end
|
91
93
|
end
|
92
94
|
|
93
95
|
class DecorationRegistration < Registration
|
@@ -110,17 +112,19 @@ module ActiveRecord
|
|
110
112
|
super | 4
|
111
113
|
end
|
112
114
|
|
115
|
+
# TODO Change this to private once we've dropped Ruby 2.2 support.
|
116
|
+
# Workaround for Ruby 2.2 "private attribute?" warning.
|
113
117
|
protected
|
114
118
|
|
115
|
-
|
119
|
+
attr_reader :options, :klass
|
116
120
|
|
117
121
|
private
|
118
122
|
|
119
|
-
|
120
|
-
|
121
|
-
|
123
|
+
def matches_options?(**kwargs)
|
124
|
+
options.all? do |key, value|
|
125
|
+
kwargs[key] == value
|
126
|
+
end
|
122
127
|
end
|
123
|
-
end
|
124
128
|
end
|
125
129
|
end
|
126
130
|
|
@@ -15,9 +15,9 @@ module ActiveRecord
|
|
15
15
|
|
16
16
|
private
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
def perform_fetch(type, *args, &block)
|
19
|
+
@mapping.fetch(type, block).call(type, *args)
|
20
|
+
end
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
module Type
|
3
3
|
class Serialized < DelegateClass(ActiveModel::Type::Value) # :nodoc:
|
4
|
+
undef to_yaml if method_defined?(:to_yaml)
|
5
|
+
|
4
6
|
include ActiveModel::Type::Helpers::Mutable
|
5
7
|
|
6
8
|
attr_reader :subtype, :coder
|
@@ -43,21 +45,25 @@ module ActiveRecord
|
|
43
45
|
|
44
46
|
def assert_valid_value(value)
|
45
47
|
if coder.respond_to?(:assert_valid_value)
|
46
|
-
coder.assert_valid_value(value)
|
48
|
+
coder.assert_valid_value(value, action: "serialize")
|
47
49
|
end
|
48
50
|
end
|
49
51
|
|
52
|
+
def force_equality?(value)
|
53
|
+
coder.respond_to?(:object_class) && value.is_a?(coder.object_class)
|
54
|
+
end
|
55
|
+
|
50
56
|
private
|
51
57
|
|
52
|
-
|
53
|
-
|
54
|
-
|
58
|
+
def default_value?(value)
|
59
|
+
value == coder.load(nil)
|
60
|
+
end
|
55
61
|
|
56
|
-
|
57
|
-
|
58
|
-
|
62
|
+
def encoded(value)
|
63
|
+
unless default_value?(value)
|
64
|
+
coder.dump(value)
|
65
|
+
end
|
59
66
|
end
|
60
|
-
end
|
61
67
|
end
|
62
68
|
end
|
63
69
|
end
|