activerecord 6.0.6.1 → 6.1.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +764 -942
- data/MIT-LICENSE +1 -1
- data/README.rdoc +3 -3
- data/lib/active_record/aggregations.rb +1 -1
- data/lib/active_record/association_relation.rb +22 -14
- data/lib/active_record/associations/alias_tracker.rb +19 -15
- data/lib/active_record/associations/association.rb +39 -27
- data/lib/active_record/associations/association_scope.rb +11 -15
- data/lib/active_record/associations/belongs_to_association.rb +15 -5
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +1 -1
- data/lib/active_record/associations/builder/association.rb +9 -3
- data/lib/active_record/associations/builder/belongs_to.rb +10 -7
- data/lib/active_record/associations/builder/collection_association.rb +5 -4
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +0 -1
- data/lib/active_record/associations/builder/has_many.rb +6 -2
- data/lib/active_record/associations/builder/has_one.rb +11 -14
- data/lib/active_record/associations/builder/singular_association.rb +1 -1
- data/lib/active_record/associations/collection_association.rb +19 -13
- data/lib/active_record/associations/collection_proxy.rb +12 -5
- data/lib/active_record/associations/foreign_association.rb +13 -0
- data/lib/active_record/associations/has_many_association.rb +24 -2
- data/lib/active_record/associations/has_many_through_association.rb +10 -4
- data/lib/active_record/associations/has_one_association.rb +15 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +29 -14
- data/lib/active_record/associations/join_dependency/join_part.rb +1 -1
- data/lib/active_record/associations/join_dependency.rb +63 -49
- data/lib/active_record/associations/preloader/association.rb +13 -5
- data/lib/active_record/associations/preloader/through_association.rb +1 -1
- data/lib/active_record/associations/preloader.rb +5 -3
- data/lib/active_record/associations/singular_association.rb +1 -1
- data/lib/active_record/associations.rb +114 -11
- data/lib/active_record/attribute_assignment.rb +10 -8
- data/lib/active_record/attribute_methods/before_type_cast.rb +13 -9
- data/lib/active_record/attribute_methods/dirty.rb +1 -11
- data/lib/active_record/attribute_methods/primary_key.rb +6 -2
- data/lib/active_record/attribute_methods/query.rb +3 -6
- data/lib/active_record/attribute_methods/read.rb +8 -11
- data/lib/active_record/attribute_methods/serialization.rb +4 -4
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -13
- data/lib/active_record/attribute_methods/write.rb +12 -20
- data/lib/active_record/attribute_methods.rb +52 -48
- data/lib/active_record/attributes.rb +27 -7
- data/lib/active_record/autosave_association.rb +47 -30
- data/lib/active_record/base.rb +2 -14
- data/lib/active_record/callbacks.rb +32 -22
- data/lib/active_record/coders/yaml_column.rb +2 -24
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +180 -134
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -44
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +65 -22
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -7
- data/lib/active_record/connection_adapters/abstract/quoting.rb +35 -44
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -116
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +110 -30
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +224 -85
- data/lib/active_record/connection_adapters/abstract/transaction.rb +66 -24
- data/lib/active_record/connection_adapters/abstract_adapter.rb +31 -70
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +123 -87
- data/lib/active_record/connection_adapters/column.rb +15 -1
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +31 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +22 -24
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +33 -6
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +8 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +3 -3
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +31 -12
- data/lib/active_record/connection_adapters/pool_config.rb +63 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +43 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +24 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +12 -53
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -10
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +11 -1
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +5 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +61 -29
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +72 -55
- data/lib/active_record/connection_adapters/schema_cache.rb +98 -15
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +10 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +30 -5
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +36 -3
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +48 -50
- data/lib/active_record/connection_adapters.rb +50 -0
- data/lib/active_record/connection_handling.rb +210 -71
- data/lib/active_record/core.rb +214 -58
- data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
- data/lib/active_record/database_configurations/database_config.rb +52 -9
- data/lib/active_record/database_configurations/hash_config.rb +54 -8
- data/lib/active_record/database_configurations/url_config.rb +15 -40
- data/lib/active_record/database_configurations.rb +124 -85
- data/lib/active_record/delegated_type.rb +209 -0
- data/lib/active_record/destroy_association_async_job.rb +36 -0
- data/lib/active_record/enum.rb +33 -23
- data/lib/active_record/errors.rb +47 -12
- data/lib/active_record/explain.rb +9 -4
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +10 -17
- data/lib/active_record/fixture_set/model_metadata.rb +1 -2
- data/lib/active_record/fixture_set/render_context.rb +1 -1
- data/lib/active_record/fixture_set/table_row.rb +2 -2
- data/lib/active_record/fixtures.rb +54 -8
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +40 -18
- data/lib/active_record/insert_all.rb +32 -5
- data/lib/active_record/integration.rb +3 -5
- data/lib/active_record/internal_metadata.rb +15 -4
- data/lib/active_record/legacy_yaml_adapter.rb +7 -3
- data/lib/active_record/locking/optimistic.rb +13 -16
- data/lib/active_record/locking/pessimistic.rb +6 -2
- data/lib/active_record/log_subscriber.rb +26 -8
- data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +5 -0
- data/lib/active_record/middleware/database_selector.rb +4 -1
- data/lib/active_record/migration/command_recorder.rb +47 -27
- data/lib/active_record/migration/compatibility.rb +67 -17
- data/lib/active_record/migration.rb +113 -83
- data/lib/active_record/model_schema.rb +88 -42
- data/lib/active_record/nested_attributes.rb +2 -3
- data/lib/active_record/no_touching.rb +1 -1
- data/lib/active_record/persistence.rb +50 -45
- data/lib/active_record/query_cache.rb +15 -5
- data/lib/active_record/querying.rb +11 -6
- data/lib/active_record/railtie.rb +64 -44
- data/lib/active_record/railties/databases.rake +253 -98
- data/lib/active_record/readonly_attributes.rb +4 -0
- data/lib/active_record/reflection.rb +59 -44
- data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
- data/lib/active_record/relation/batches.rb +38 -31
- data/lib/active_record/relation/calculations.rb +100 -43
- data/lib/active_record/relation/finder_methods.rb +44 -14
- data/lib/active_record/relation/from_clause.rb +1 -1
- data/lib/active_record/relation/merger.rb +20 -23
- data/lib/active_record/relation/predicate_builder/array_handler.rb +8 -9
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +2 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +3 -3
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/predicate_builder.rb +57 -33
- data/lib/active_record/relation/query_methods.rb +319 -198
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +6 -5
- data/lib/active_record/relation/where_clause.rb +104 -57
- data/lib/active_record/relation.rb +90 -64
- data/lib/active_record/result.rb +41 -33
- data/lib/active_record/runtime_registry.rb +2 -2
- data/lib/active_record/sanitization.rb +6 -17
- data/lib/active_record/schema_dumper.rb +34 -4
- data/lib/active_record/schema_migration.rb +0 -4
- data/lib/active_record/scoping/named.rb +1 -17
- data/lib/active_record/secure_token.rb +16 -8
- data/lib/active_record/serialization.rb +5 -3
- data/lib/active_record/signed_id.rb +116 -0
- data/lib/active_record/statement_cache.rb +20 -4
- data/lib/active_record/store.rb +2 -2
- data/lib/active_record/suppressor.rb +2 -2
- data/lib/active_record/table_metadata.rb +36 -52
- data/lib/active_record/tasks/database_tasks.rb +139 -113
- data/lib/active_record/tasks/mysql_database_tasks.rb +34 -35
- data/lib/active_record/tasks/postgresql_database_tasks.rb +24 -26
- data/lib/active_record/tasks/sqlite_database_tasks.rb +13 -9
- data/lib/active_record/test_databases.rb +5 -4
- data/lib/active_record/test_fixtures.rb +36 -33
- data/lib/active_record/timestamp.rb +4 -6
- data/lib/active_record/touch_later.rb +21 -21
- data/lib/active_record/transactions.rb +15 -64
- data/lib/active_record/type/serialized.rb +6 -2
- data/lib/active_record/type.rb +8 -1
- data/lib/active_record/type_caster/connection.rb +0 -1
- data/lib/active_record/type_caster/map.rb +8 -5
- data/lib/active_record/validations/associated.rb +1 -1
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/uniqueness.rb +24 -4
- data/lib/active_record/validations.rb +1 -0
- data/lib/active_record.rb +7 -14
- data/lib/arel/attributes/attribute.rb +4 -0
- data/lib/arel/collectors/bind.rb +5 -0
- data/lib/arel/collectors/composite.rb +8 -0
- data/lib/arel/collectors/sql_string.rb +7 -0
- data/lib/arel/collectors/substitute_binds.rb +7 -0
- data/lib/arel/nodes/binary.rb +82 -8
- data/lib/arel/nodes/bind_param.rb +8 -0
- data/lib/arel/nodes/casted.rb +21 -9
- data/lib/arel/nodes/equality.rb +6 -9
- data/lib/arel/nodes/grouping.rb +3 -0
- data/lib/arel/nodes/homogeneous_in.rb +72 -0
- data/lib/arel/nodes/in.rb +8 -1
- data/lib/arel/nodes/infix_operation.rb +13 -1
- data/lib/arel/nodes/join_source.rb +1 -1
- data/lib/arel/nodes/node.rb +7 -6
- data/lib/arel/nodes/ordering.rb +27 -0
- data/lib/arel/nodes/sql_literal.rb +3 -0
- data/lib/arel/nodes/table_alias.rb +7 -3
- data/lib/arel/nodes/unary.rb +0 -1
- data/lib/arel/nodes.rb +3 -1
- data/lib/arel/predications.rb +12 -18
- data/lib/arel/select_manager.rb +1 -2
- data/lib/arel/table.rb +13 -5
- data/lib/arel/visitors/dot.rb +14 -2
- data/lib/arel/visitors/mysql.rb +11 -1
- data/lib/arel/visitors/postgresql.rb +15 -4
- data/lib/arel/visitors/to_sql.rb +89 -78
- data/lib/arel/visitors.rb +0 -7
- data/lib/arel.rb +5 -13
- data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +2 -0
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +3 -3
- data/lib/rails/generators/active_record/migration.rb +6 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- metadata +30 -32
- data/lib/active_record/advisory_lock_base.rb +0 -18
- data/lib/active_record/attribute_decorators.rb +0 -88
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -296
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
- data/lib/active_record/define_callbacks.rb +0 -22
- data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
- data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
- data/lib/active_record/relation/where_clause_factory.rb +0 -33
- data/lib/arel/attributes.rb +0 -22
- data/lib/arel/visitors/depth_first.rb +0 -203
- data/lib/arel/visitors/ibm_db.rb +0 -34
- data/lib/arel/visitors/informix.rb +0 -62
- data/lib/arel/visitors/mssql.rb +0 -156
- data/lib/arel/visitors/oracle.rb +0 -158
- data/lib/arel/visitors/oracle12.rb +0 -65
- data/lib/arel/visitors/where_sql.rb +0 -22
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "mutex_m"
|
4
|
+
require "active_support/core_ext/enumerable"
|
4
5
|
|
5
6
|
module ActiveRecord
|
6
7
|
# = Active Record Attribute Methods
|
@@ -18,8 +19,6 @@ module ActiveRecord
|
|
18
19
|
include TimeZoneConversion
|
19
20
|
include Dirty
|
20
21
|
include Serialization
|
21
|
-
|
22
|
-
delegate :column_for_attribute, to: :class
|
23
22
|
end
|
24
23
|
|
25
24
|
RESTRICTED_CLASS_METHODS = %w(private public protected allocate new name parent superclass)
|
@@ -28,6 +27,17 @@ module ActiveRecord
|
|
28
27
|
include Mutex_m
|
29
28
|
end
|
30
29
|
|
30
|
+
class << self
|
31
|
+
def dangerous_attribute_methods # :nodoc:
|
32
|
+
@dangerous_attribute_methods ||= (
|
33
|
+
Base.instance_methods +
|
34
|
+
Base.private_instance_methods -
|
35
|
+
Base.superclass.instance_methods -
|
36
|
+
Base.superclass.private_instance_methods
|
37
|
+
).map { |m| -m.to_s }.to_set.freeze
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
31
41
|
module ClassMethods
|
32
42
|
def inherited(child_class) #:nodoc:
|
33
43
|
child_class.initialize_generated_modules
|
@@ -97,7 +107,7 @@ module ActiveRecord
|
|
97
107
|
# A method name is 'dangerous' if it is already (re)defined by Active Record, but
|
98
108
|
# not by any ancestors. (So 'puts' is not dangerous but 'save' is.)
|
99
109
|
def dangerous_attribute_method?(name) # :nodoc:
|
100
|
-
|
110
|
+
::ActiveRecord::AttributeMethods.dangerous_attribute_methods.include?(name.to_s)
|
101
111
|
end
|
102
112
|
|
103
113
|
def method_defined_within?(name, klass, superklass = klass.superclass) # :nodoc:
|
@@ -115,13 +125,11 @@ module ActiveRecord
|
|
115
125
|
# A class method is 'dangerous' if it is already (re)defined by Active Record, but
|
116
126
|
# not by any ancestors. (So 'puts' is not dangerous but 'new' is.)
|
117
127
|
def dangerous_class_method?(method_name)
|
118
|
-
RESTRICTED_CLASS_METHODS.include?(method_name.to_s)
|
119
|
-
end
|
128
|
+
return true if RESTRICTED_CLASS_METHODS.include?(method_name.to_s)
|
120
129
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
klass.method(name).owner != superklass.method(name).owner
|
130
|
+
if Base.respond_to?(method_name, true)
|
131
|
+
if Object.respond_to?(method_name, true)
|
132
|
+
Base.method(method_name).owner != Object.method(method_name).owner
|
125
133
|
else
|
126
134
|
true
|
127
135
|
end
|
@@ -140,7 +148,7 @@ module ActiveRecord
|
|
140
148
|
# Person.attribute_method?(:age=) # => true
|
141
149
|
# Person.attribute_method?(:nothing) # => false
|
142
150
|
def attribute_method?(attribute)
|
143
|
-
super || (table_exists? && column_names.include?(attribute.to_s.
|
151
|
+
super || (table_exists? && column_names.include?(attribute.to_s.delete_suffix("=")))
|
144
152
|
end
|
145
153
|
|
146
154
|
# Returns an array of column names as strings if it's not an abstract class and
|
@@ -156,39 +164,27 @@ module ActiveRecord
|
|
156
164
|
attribute_types.keys
|
157
165
|
else
|
158
166
|
[]
|
159
|
-
end
|
167
|
+
end.freeze
|
160
168
|
end
|
161
169
|
|
162
170
|
# Returns true if the given attribute exists, otherwise false.
|
163
171
|
#
|
164
172
|
# class Person < ActiveRecord::Base
|
173
|
+
# alias_attribute :new_name, :name
|
165
174
|
# end
|
166
175
|
#
|
167
|
-
# Person.has_attribute?('name')
|
168
|
-
# Person.has_attribute?(
|
169
|
-
# Person.has_attribute?(:
|
176
|
+
# Person.has_attribute?('name') # => true
|
177
|
+
# Person.has_attribute?('new_name') # => true
|
178
|
+
# Person.has_attribute?(:age) # => true
|
179
|
+
# Person.has_attribute?(:nothing) # => false
|
170
180
|
def has_attribute?(attr_name)
|
171
|
-
|
181
|
+
attr_name = attr_name.to_s
|
182
|
+
attr_name = attribute_aliases[attr_name] || attr_name
|
183
|
+
attribute_types.key?(attr_name)
|
172
184
|
end
|
173
185
|
|
174
|
-
|
175
|
-
|
176
|
-
# named attribute does not exist.
|
177
|
-
#
|
178
|
-
# class Person < ActiveRecord::Base
|
179
|
-
# end
|
180
|
-
#
|
181
|
-
# person = Person.new
|
182
|
-
# person.column_for_attribute(:name) # the result depends on the ConnectionAdapter
|
183
|
-
# # => #<ActiveRecord::ConnectionAdapters::Column:0x007ff4ab083980 @name="name", @sql_type="varchar(255)", @null=true, ...>
|
184
|
-
#
|
185
|
-
# person.column_for_attribute(:nothing)
|
186
|
-
# # => #<ActiveRecord::ConnectionAdapters::NullColumn:0xXXX @name=nil, @sql_type=nil, @cast_type=#<Type::Value>, ...>
|
187
|
-
def column_for_attribute(name)
|
188
|
-
name = name.to_s
|
189
|
-
columns_hash.fetch(name) do
|
190
|
-
ConnectionAdapters::NullColumn.new(name)
|
191
|
-
end
|
186
|
+
def _has_attribute?(attr_name) # :nodoc:
|
187
|
+
attribute_types.key?(attr_name)
|
192
188
|
end
|
193
189
|
end
|
194
190
|
|
@@ -217,7 +213,7 @@ module ActiveRecord
|
|
217
213
|
# have been allocated but not yet initialized.
|
218
214
|
if defined?(@attributes)
|
219
215
|
if name = self.class.symbol_column_to_string(name.to_sym)
|
220
|
-
return
|
216
|
+
return _has_attribute?(name)
|
221
217
|
end
|
222
218
|
end
|
223
219
|
|
@@ -227,14 +223,22 @@ module ActiveRecord
|
|
227
223
|
# Returns +true+ if the given attribute is in the attributes hash, otherwise +false+.
|
228
224
|
#
|
229
225
|
# class Person < ActiveRecord::Base
|
226
|
+
# alias_attribute :new_name, :name
|
230
227
|
# end
|
231
228
|
#
|
232
229
|
# person = Person.new
|
233
|
-
# person.has_attribute?(:name)
|
234
|
-
# person.has_attribute?(
|
235
|
-
# person.has_attribute?(
|
230
|
+
# person.has_attribute?(:name) # => true
|
231
|
+
# person.has_attribute?(:new_name) # => true
|
232
|
+
# person.has_attribute?('age') # => true
|
233
|
+
# person.has_attribute?(:nothing) # => false
|
236
234
|
def has_attribute?(attr_name)
|
237
|
-
|
235
|
+
attr_name = attr_name.to_s
|
236
|
+
attr_name = self.class.attribute_aliases[attr_name] || attr_name
|
237
|
+
@attributes.key?(attr_name)
|
238
|
+
end
|
239
|
+
|
240
|
+
def _has_attribute?(attr_name) # :nodoc:
|
241
|
+
@attributes.key?(attr_name)
|
238
242
|
end
|
239
243
|
|
240
244
|
# Returns an array of names for the attributes available on this object.
|
@@ -278,6 +282,8 @@ module ActiveRecord
|
|
278
282
|
# person.attribute_for_inspect(:tag_ids)
|
279
283
|
# # => "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]"
|
280
284
|
def attribute_for_inspect(attr_name)
|
285
|
+
attr_name = attr_name.to_s
|
286
|
+
attr_name = self.class.attribute_aliases[attr_name] || attr_name
|
281
287
|
value = _read_attribute(attr_name)
|
282
288
|
format_for_inspect(value)
|
283
289
|
end
|
@@ -297,8 +303,10 @@ module ActiveRecord
|
|
297
303
|
# task.is_done = true
|
298
304
|
# task.attribute_present?(:title) # => true
|
299
305
|
# task.attribute_present?(:is_done) # => true
|
300
|
-
def attribute_present?(
|
301
|
-
|
306
|
+
def attribute_present?(attr_name)
|
307
|
+
attr_name = attr_name.to_s
|
308
|
+
attr_name = self.class.attribute_aliases[attr_name] || attr_name
|
309
|
+
value = _read_attribute(attr_name)
|
302
310
|
!value.nil? && !(value.respond_to?(:empty?) && value.empty?)
|
303
311
|
end
|
304
312
|
|
@@ -377,8 +385,8 @@ module ActiveRecord
|
|
377
385
|
end
|
378
386
|
|
379
387
|
def attributes_with_values(attribute_names)
|
380
|
-
attribute_names.
|
381
|
-
|
388
|
+
attribute_names.index_with do |name|
|
389
|
+
_read_attribute(name)
|
382
390
|
end
|
383
391
|
end
|
384
392
|
|
@@ -386,7 +394,7 @@ module ActiveRecord
|
|
386
394
|
def attributes_for_update(attribute_names)
|
387
395
|
attribute_names &= self.class.column_names
|
388
396
|
attribute_names.delete_if do |name|
|
389
|
-
readonly_attribute?(name)
|
397
|
+
self.class.readonly_attribute?(name)
|
390
398
|
end
|
391
399
|
end
|
392
400
|
|
@@ -403,16 +411,12 @@ module ActiveRecord
|
|
403
411
|
if value.is_a?(String) && value.length > 50
|
404
412
|
"#{value[0, 50]}...".inspect
|
405
413
|
elsif value.is_a?(Date) || value.is_a?(Time)
|
406
|
-
%("#{value.to_s(:
|
414
|
+
%("#{value.to_s(:inspect)}")
|
407
415
|
else
|
408
416
|
value.inspect
|
409
417
|
end
|
410
418
|
end
|
411
419
|
|
412
|
-
def readonly_attribute?(name)
|
413
|
-
self.class.readonly_attributes.include?(name)
|
414
|
-
end
|
415
|
-
|
416
420
|
def pk_attribute?(name)
|
417
421
|
name == @primary_key
|
418
422
|
end
|
@@ -205,13 +205,13 @@ module ActiveRecord
|
|
205
205
|
# tracking is performed. The methods +changed?+ and +changed_in_place?+
|
206
206
|
# will be called from ActiveModel::Dirty. See the documentation for those
|
207
207
|
# methods in ActiveModel::Type::Value for more details.
|
208
|
-
def attribute(name, cast_type =
|
208
|
+
def attribute(name, cast_type = nil, **options, &block)
|
209
209
|
name = name.to_s
|
210
210
|
reload_schema_from_cache
|
211
211
|
|
212
212
|
self.attributes_to_define_after_schema_loads =
|
213
213
|
attributes_to_define_after_schema_loads.merge(
|
214
|
-
name => [cast_type, options]
|
214
|
+
name => [cast_type || block, options]
|
215
215
|
)
|
216
216
|
end
|
217
217
|
|
@@ -246,11 +246,7 @@ module ActiveRecord
|
|
246
246
|
def load_schema! # :nodoc:
|
247
247
|
super
|
248
248
|
attributes_to_define_after_schema_loads.each do |name, (type, options)|
|
249
|
-
|
250
|
-
type = ActiveRecord::Type.lookup(type, **options.except(:default))
|
251
|
-
end
|
252
|
-
|
253
|
-
define_attribute(name, type, **options.slice(:default))
|
249
|
+
define_attribute(name, _lookup_cast_type(name, type, options), **options.slice(:default))
|
254
250
|
end
|
255
251
|
end
|
256
252
|
|
@@ -273,6 +269,30 @@ module ActiveRecord
|
|
273
269
|
end
|
274
270
|
_default_attributes[name] = default_attribute
|
275
271
|
end
|
272
|
+
|
273
|
+
def decorate_attribute_type(attr_name, **default)
|
274
|
+
type, options = attributes_to_define_after_schema_loads[attr_name]
|
275
|
+
|
276
|
+
attribute(attr_name, **default) do |cast_type|
|
277
|
+
if type && !type.is_a?(Proc)
|
278
|
+
cast_type = _lookup_cast_type(attr_name, type, options)
|
279
|
+
end
|
280
|
+
|
281
|
+
yield cast_type
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
def _lookup_cast_type(name, type, options)
|
286
|
+
case type
|
287
|
+
when Symbol
|
288
|
+
adapter_name = ActiveRecord::Type.adapter_name_from(self)
|
289
|
+
ActiveRecord::Type.lookup(type, **options.except(:default), adapter: adapter_name)
|
290
|
+
when Proc
|
291
|
+
type[type_for_attribute(name)]
|
292
|
+
else
|
293
|
+
type || type_for_attribute(name)
|
294
|
+
end
|
295
|
+
end
|
276
296
|
end
|
277
297
|
end
|
278
298
|
end
|
@@ -31,7 +31,7 @@ module ActiveRecord
|
|
31
31
|
# Association with autosave option defines several callbacks on your
|
32
32
|
# model (around_save, before_save, after_create, after_update). Please note that
|
33
33
|
# callbacks are executed in the order they were defined in
|
34
|
-
# model. You should avoid modifying the association content
|
34
|
+
# model. You should avoid modifying the association content before
|
35
35
|
# autosave callbacks are executed. Placing your callbacks after
|
36
36
|
# associations is usually a good practice.
|
37
37
|
#
|
@@ -91,8 +91,9 @@ module ActiveRecord
|
|
91
91
|
# post.save # => saves both post and comment
|
92
92
|
#
|
93
93
|
# post = Post.create(title: 'ruby rocks')
|
94
|
-
# post.comments.create(body: 'hello world')
|
95
|
-
#
|
94
|
+
# comment = post.comments.create(body: 'hello world')
|
95
|
+
# comment.body = 'hi everyone'
|
96
|
+
# post.save # => saves post, but not comment
|
96
97
|
#
|
97
98
|
# When <tt>:autosave</tt> is true all children are saved, no matter whether they
|
98
99
|
# are new records or not:
|
@@ -102,11 +103,10 @@ module ActiveRecord
|
|
102
103
|
# end
|
103
104
|
#
|
104
105
|
# post = Post.create(title: 'ruby rocks')
|
105
|
-
# post.comments.create(body: 'hello world')
|
106
|
-
#
|
106
|
+
# comment = post.comments.create(body: 'hello world')
|
107
|
+
# comment.body = 'hi everyone'
|
107
108
|
# post.comments.build(body: "good morning.")
|
108
|
-
# post.
|
109
|
-
# post.save # => saves both post and comments.
|
109
|
+
# post.save # => saves post and both comments.
|
110
110
|
#
|
111
111
|
# Destroying one of the associated models as part of the parent's save action
|
112
112
|
# is as simple as marking it for destruction:
|
@@ -127,6 +127,14 @@ module ActiveRecord
|
|
127
127
|
# Now it _is_ removed from the database:
|
128
128
|
#
|
129
129
|
# Comment.find_by(id: id).nil? # => true
|
130
|
+
#
|
131
|
+
# === Caveats
|
132
|
+
#
|
133
|
+
# Note that autosave will only trigger for already-persisted association records
|
134
|
+
# if the records themselves have been changed. This is to protect against
|
135
|
+
# <tt>SystemStackError</tt> caused by circular association validations. The one
|
136
|
+
# exception is if a custom validation context is used, in which case the validations
|
137
|
+
# will always fire on the associated records.
|
130
138
|
module AutosaveAssociation
|
131
139
|
extend ActiveSupport::Concern
|
132
140
|
|
@@ -147,8 +155,23 @@ module ActiveRecord
|
|
147
155
|
|
148
156
|
module ClassMethods # :nodoc:
|
149
157
|
private
|
158
|
+
if Module.method(:method_defined?).arity == 1 # MRI 2.5 and older
|
159
|
+
using Module.new {
|
160
|
+
refine Module do
|
161
|
+
def method_defined?(method, inherit = true)
|
162
|
+
if inherit
|
163
|
+
super(method)
|
164
|
+
else
|
165
|
+
instance_methods(false).include?(method.to_sym)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
}
|
170
|
+
end
|
171
|
+
|
150
172
|
def define_non_cyclic_method(name, &block)
|
151
|
-
return if
|
173
|
+
return if method_defined?(name, false)
|
174
|
+
|
152
175
|
define_method(name) do |*args|
|
153
176
|
result = true; @_already_called ||= {}
|
154
177
|
# Loop prevention for validation of associations
|
@@ -278,8 +301,9 @@ module ActiveRecord
|
|
278
301
|
end
|
279
302
|
end
|
280
303
|
|
281
|
-
#
|
282
|
-
# any new ones), and return true if
|
304
|
+
# Go through nested autosave associations that are loaded in memory (without loading
|
305
|
+
# any new ones), and return true if any are changed for autosave.
|
306
|
+
# Returns false if already called to prevent an infinite loop.
|
283
307
|
def nested_records_changed_for_autosave?
|
284
308
|
@_nested_records_changed_for_autosave_already_called ||= false
|
285
309
|
return false if @_nested_records_changed_for_autosave_already_called
|
@@ -327,21 +351,16 @@ module ActiveRecord
|
|
327
351
|
if reflection.options[:autosave]
|
328
352
|
indexed_attribute = !index.nil? && (reflection.options[:index_errors] || ActiveRecord::Base.index_nested_attribute_errors)
|
329
353
|
|
330
|
-
record.errors.each
|
354
|
+
record.errors.group_by_attribute.each { |attribute, errors|
|
331
355
|
attribute = normalize_reflection_attribute(indexed_attribute, reflection, index, attribute)
|
332
|
-
errors[attribute] << message
|
333
|
-
errors[attribute].uniq!
|
334
|
-
end
|
335
|
-
|
336
|
-
record.errors.details.each_key do |attribute|
|
337
|
-
reflection_attribute =
|
338
|
-
normalize_reflection_attribute(indexed_attribute, reflection, index, attribute).to_sym
|
339
356
|
|
340
|
-
|
341
|
-
errors.
|
342
|
-
|
343
|
-
|
344
|
-
|
357
|
+
errors.each { |error|
|
358
|
+
self.errors.import(
|
359
|
+
error,
|
360
|
+
attribute: attribute
|
361
|
+
)
|
362
|
+
}
|
363
|
+
}
|
345
364
|
else
|
346
365
|
errors.add(reflection.name)
|
347
366
|
end
|
@@ -438,9 +457,9 @@ module ActiveRecord
|
|
438
457
|
if autosave && record.marked_for_destruction?
|
439
458
|
record.destroy
|
440
459
|
elsif autosave != false
|
441
|
-
key = reflection.options[:primary_key] ?
|
460
|
+
key = reflection.options[:primary_key] ? public_send(reflection.options[:primary_key]) : id
|
442
461
|
|
443
|
-
if (autosave && record.changed_for_autosave?) ||
|
462
|
+
if (autosave && record.changed_for_autosave?) || record_changed?(reflection, record, key)
|
444
463
|
unless reflection.through_reflection
|
445
464
|
record[reflection.foreign_key] = key
|
446
465
|
if inverse_reflection = reflection.inverse_of
|
@@ -466,7 +485,7 @@ module ActiveRecord
|
|
466
485
|
def association_foreign_key_changed?(reflection, record, key)
|
467
486
|
return false if reflection.through_reflection?
|
468
487
|
|
469
|
-
record.
|
488
|
+
record._has_attribute?(reflection.foreign_key) && record._read_attribute(reflection.foreign_key) != key
|
470
489
|
end
|
471
490
|
|
472
491
|
# Saves the associated record if it's new or <tt>:autosave</tt> is enabled.
|
@@ -487,7 +506,7 @@ module ActiveRecord
|
|
487
506
|
saved = record.save(validate: !autosave) if record.new_record? || (autosave && record.changed_for_autosave?)
|
488
507
|
|
489
508
|
if association.updated?
|
490
|
-
association_id = record.
|
509
|
+
association_id = record.public_send(reflection.options[:primary_key] || :id)
|
491
510
|
self[reflection.foreign_key] = association_id
|
492
511
|
association.loaded!
|
493
512
|
end
|
@@ -502,9 +521,7 @@ module ActiveRecord
|
|
502
521
|
end
|
503
522
|
|
504
523
|
def _ensure_no_duplicate_errors
|
505
|
-
errors.
|
506
|
-
errors[attribute].uniq!
|
507
|
-
end
|
524
|
+
errors.uniq!
|
508
525
|
end
|
509
526
|
end
|
510
527
|
end
|
data/lib/active_record/base.rb
CHANGED
@@ -1,22 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "yaml"
|
4
3
|
require "active_support/benchmarkable"
|
5
4
|
require "active_support/dependencies"
|
6
5
|
require "active_support/descendants_tracker"
|
7
6
|
require "active_support/time"
|
8
|
-
require "active_support/core_ext/module/attribute_accessors"
|
9
|
-
require "active_support/core_ext/array/extract_options"
|
10
|
-
require "active_support/core_ext/hash/deep_merge"
|
11
|
-
require "active_support/core_ext/hash/slice"
|
12
|
-
require "active_support/core_ext/string/behavior"
|
13
|
-
require "active_support/core_ext/kernel/singleton_class"
|
14
|
-
require "active_support/core_ext/module/introspection"
|
15
|
-
require "active_support/core_ext/object/duplicable"
|
16
7
|
require "active_support/core_ext/class/subclasses"
|
17
|
-
require "active_record/attribute_decorators"
|
18
|
-
require "active_record/define_callbacks"
|
19
|
-
require "active_record/errors"
|
20
8
|
require "active_record/log_subscriber"
|
21
9
|
require "active_record/explain_subscriber"
|
22
10
|
require "active_record/relation/delegation"
|
@@ -285,6 +273,7 @@ module ActiveRecord #:nodoc:
|
|
285
273
|
extend Querying
|
286
274
|
extend Translation
|
287
275
|
extend DynamicMatchers
|
276
|
+
extend DelegatedType
|
288
277
|
extend Explain
|
289
278
|
extend Enum
|
290
279
|
extend Delegation::DelegateCache
|
@@ -303,10 +292,8 @@ module ActiveRecord #:nodoc:
|
|
303
292
|
include Validations
|
304
293
|
include CounterCache
|
305
294
|
include Attributes
|
306
|
-
include AttributeDecorators
|
307
295
|
include Locking::Optimistic
|
308
296
|
include Locking::Pessimistic
|
309
|
-
include DefineCallbacks
|
310
297
|
include AttributeMethods
|
311
298
|
include Callbacks
|
312
299
|
include Timestamp
|
@@ -321,6 +308,7 @@ module ActiveRecord #:nodoc:
|
|
321
308
|
include Serialization
|
322
309
|
include Store
|
323
310
|
include SecureToken
|
311
|
+
include SignedId
|
324
312
|
include Suppressor
|
325
313
|
end
|
326
314
|
|
@@ -4,7 +4,7 @@ module ActiveRecord
|
|
4
4
|
# = Active Record \Callbacks
|
5
5
|
#
|
6
6
|
# \Callbacks are hooks into the life cycle of an Active Record object that allow you to trigger logic
|
7
|
-
# before or after
|
7
|
+
# before or after a change in the object state. This can be used to make sure that associated and
|
8
8
|
# dependent objects are deleted when {ActiveRecord::Base#destroy}[rdoc-ref:Persistence#destroy] is called (by overwriting +before_destroy+) or
|
9
9
|
# to massage attributes before they're validated (by overwriting +before_validation+).
|
10
10
|
# As an example of the callbacks initiated, consider the {ActiveRecord::Base#save}[rdoc-ref:Persistence#save] call for a new record:
|
@@ -32,7 +32,7 @@ module ActiveRecord
|
|
32
32
|
# is found and instantiated by a finder, with <tt>after_initialize</tt> being triggered after new objects
|
33
33
|
# are instantiated as well.
|
34
34
|
#
|
35
|
-
# There are nineteen callbacks in total, which give
|
35
|
+
# There are nineteen callbacks in total, which give a lot of control over how to react and prepare for each state in the
|
36
36
|
# Active Record life cycle. The sequence for calling {ActiveRecord::Base#save}[rdoc-ref:Persistence#save] for an existing record is similar,
|
37
37
|
# except that each <tt>_create</tt> callback is replaced by the corresponding <tt>_update</tt> callback.
|
38
38
|
#
|
@@ -64,7 +64,7 @@ module ActiveRecord
|
|
64
64
|
#
|
65
65
|
# Besides the overwritable callback methods, it's also possible to register callbacks through the
|
66
66
|
# use of the callback macros. Their main advantage is that the macros add behavior into a callback
|
67
|
-
# queue that is kept intact
|
67
|
+
# queue that is kept intact through an inheritance hierarchy.
|
68
68
|
#
|
69
69
|
# class Topic < ActiveRecord::Base
|
70
70
|
# before_destroy :destroy_author
|
@@ -74,7 +74,7 @@ module ActiveRecord
|
|
74
74
|
# before_destroy :destroy_readers
|
75
75
|
# end
|
76
76
|
#
|
77
|
-
#
|
77
|
+
# When <tt>Topic#destroy</tt> is run only +destroy_author+ is called. When <tt>Reply#destroy</tt> is
|
78
78
|
# run, both +destroy_author+ and +destroy_readers+ are called.
|
79
79
|
#
|
80
80
|
# *IMPORTANT:* In order for inheritance to work for the callback queues, you must specify the
|
@@ -83,10 +83,9 @@ module ActiveRecord
|
|
83
83
|
#
|
84
84
|
# == Types of callbacks
|
85
85
|
#
|
86
|
-
# There are
|
87
|
-
# inline methods (using a proc). Method references and callback objects
|
88
|
-
#
|
89
|
-
# creating mix-ins).
|
86
|
+
# There are three types of callbacks accepted by the callback macros: method references (symbol), callback objects,
|
87
|
+
# inline methods (using a proc). Method references and callback objects are the recommended approaches,
|
88
|
+
# inline methods using a proc are sometimes appropriate (such as for creating mix-ins).
|
90
89
|
#
|
91
90
|
# The method reference callbacks work by specifying a protected or private method available in the object, like this:
|
92
91
|
#
|
@@ -179,8 +178,8 @@ module ActiveRecord
|
|
179
178
|
#
|
180
179
|
# == Ordering callbacks
|
181
180
|
#
|
182
|
-
# Sometimes
|
183
|
-
# callback (+log_children+ in this case) should be executed before the children
|
181
|
+
# Sometimes application code requires that callbacks execute in a specific order. For example, a +before_destroy+
|
182
|
+
# callback (+log_children+ in this case) should be executed before records in the +children+ association are destroyed by the
|
184
183
|
# <tt>dependent: :destroy</tt> option.
|
185
184
|
#
|
186
185
|
# Let's look at the code below:
|
@@ -196,8 +195,8 @@ module ActiveRecord
|
|
196
195
|
# end
|
197
196
|
# end
|
198
197
|
#
|
199
|
-
# In this case, the problem is that when the +before_destroy+ callback is executed, the children
|
200
|
-
# because the {ActiveRecord::Base#destroy}[rdoc-ref:Persistence#destroy] callback
|
198
|
+
# In this case, the problem is that when the +before_destroy+ callback is executed, records in the +children+ association no
|
199
|
+
# longer exist because the {ActiveRecord::Base#destroy}[rdoc-ref:Persistence#destroy] callback was executed first.
|
201
200
|
# You can use the +prepend+ option on the +before_destroy+ callback to avoid this.
|
202
201
|
#
|
203
202
|
# class Topic < ActiveRecord::Base
|
@@ -211,7 +210,7 @@ module ActiveRecord
|
|
211
210
|
# end
|
212
211
|
# end
|
213
212
|
#
|
214
|
-
# This way, the +before_destroy+
|
213
|
+
# This way, the +before_destroy+ is executed before the <tt>dependent: :destroy</tt> is called, and the data is still available.
|
215
214
|
#
|
216
215
|
# Also, there are cases when you want several callbacks of the same type to
|
217
216
|
# be executed in order.
|
@@ -235,10 +234,10 @@ module ActiveRecord
|
|
235
234
|
# end
|
236
235
|
# end
|
237
236
|
#
|
238
|
-
# In this case the +log_children+
|
237
|
+
# In this case the +log_children+ is executed before +do_something_else+.
|
239
238
|
# The same applies to all non-transactional callbacks.
|
240
239
|
#
|
241
|
-
#
|
240
|
+
# As seen below, in case there are multiple transactional callbacks the order
|
242
241
|
# is reversed.
|
243
242
|
#
|
244
243
|
# For example:
|
@@ -260,16 +259,16 @@ module ActiveRecord
|
|
260
259
|
# end
|
261
260
|
# end
|
262
261
|
#
|
263
|
-
# In this case the +do_something_else+
|
262
|
+
# In this case the +do_something_else+ is executed before +log_children+.
|
264
263
|
#
|
265
264
|
# == \Transactions
|
266
265
|
#
|
267
266
|
# The entire callback chain of a {#save}[rdoc-ref:Persistence#save], {#save!}[rdoc-ref:Persistence#save!],
|
268
267
|
# or {#destroy}[rdoc-ref:Persistence#destroy] call runs within a transaction. That includes <tt>after_*</tt> hooks.
|
269
|
-
# If everything goes fine a COMMIT is executed once the chain has been completed.
|
268
|
+
# If everything goes fine a +COMMIT+ is executed once the chain has been completed.
|
270
269
|
#
|
271
|
-
# If a <tt>before_*</tt> callback cancels the action a ROLLBACK is issued. You
|
272
|
-
# can also trigger a ROLLBACK raising an exception in any of the callbacks,
|
270
|
+
# If a <tt>before_*</tt> callback cancels the action a +ROLLBACK+ is issued. You
|
271
|
+
# can also trigger a +ROLLBACK+ raising an exception in any of the callbacks,
|
273
272
|
# including <tt>after_*</tt> hooks. Note, however, that in that case the client
|
274
273
|
# needs to be aware of it because an ordinary {#save}[rdoc-ref:Persistence#save] will raise such exception
|
275
274
|
# instead of quietly returning +false+.
|
@@ -280,17 +279,17 @@ module ActiveRecord
|
|
280
279
|
# <tt>:before</tt>, <tt>:after</tt> and <tt>:around</tt> as values for the <tt>kind</tt> property. The <tt>kind</tt> property
|
281
280
|
# defines what part of the chain the callback runs in.
|
282
281
|
#
|
283
|
-
# To find all callbacks in the before_save callback chain:
|
282
|
+
# To find all callbacks in the +before_save+ callback chain:
|
284
283
|
#
|
285
284
|
# Topic._save_callbacks.select { |cb| cb.kind.eql?(:before) }
|
286
285
|
#
|
287
|
-
# Returns an array of callback objects that form the before_save chain.
|
286
|
+
# Returns an array of callback objects that form the +before_save+ chain.
|
288
287
|
#
|
289
288
|
# To further check if the before_save chain contains a proc defined as <tt>rest_when_dead</tt> use the <tt>filter</tt> property of the callback object:
|
290
289
|
#
|
291
290
|
# Topic._save_callbacks.select { |cb| cb.kind.eql?(:before) }.collect(&:filter).include?(:rest_when_dead)
|
292
291
|
#
|
293
|
-
# Returns true or false depending on whether the proc is contained in the before_save callback chain on a Topic model.
|
292
|
+
# Returns true or false depending on whether the proc is contained in the +before_save+ callback chain on a Topic model.
|
294
293
|
#
|
295
294
|
module Callbacks
|
296
295
|
extend ActiveSupport::Concern
|
@@ -302,6 +301,17 @@ module ActiveRecord
|
|
302
301
|
:before_destroy, :around_destroy, :after_destroy, :after_commit, :after_rollback
|
303
302
|
]
|
304
303
|
|
304
|
+
module ClassMethods # :nodoc:
|
305
|
+
include ActiveModel::Callbacks
|
306
|
+
end
|
307
|
+
|
308
|
+
included do
|
309
|
+
include ActiveModel::Validations::Callbacks
|
310
|
+
|
311
|
+
define_model_callbacks :initialize, :find, :touch, only: :after
|
312
|
+
define_model_callbacks :save, :create, :update, :destroy
|
313
|
+
end
|
314
|
+
|
305
315
|
def destroy #:nodoc:
|
306
316
|
@_destroy_callback_already_called ||= false
|
307
317
|
return if @_destroy_callback_already_called
|
@@ -22,8 +22,8 @@ module ActiveRecord
|
|
22
22
|
|
23
23
|
def load(yaml)
|
24
24
|
return object_class.new if object_class != Object && yaml.nil?
|
25
|
-
return yaml unless yaml.is_a?(String) &&
|
26
|
-
obj =
|
25
|
+
return yaml unless yaml.is_a?(String) && yaml.start_with?("---")
|
26
|
+
obj = YAML.load(yaml)
|
27
27
|
|
28
28
|
assert_valid_value(obj, action: "load")
|
29
29
|
obj ||= object_class.new if object_class != Object
|
@@ -44,28 +44,6 @@ module ActiveRecord
|
|
44
44
|
rescue ArgumentError
|
45
45
|
raise ArgumentError, "Cannot serialize #{object_class}. Classes passed to `serialize` must have a 0 argument constructor."
|
46
46
|
end
|
47
|
-
|
48
|
-
if YAML.respond_to?(:unsafe_load)
|
49
|
-
def yaml_load(payload)
|
50
|
-
if ActiveRecord::Base.use_yaml_unsafe_load
|
51
|
-
YAML.unsafe_load(payload)
|
52
|
-
elsif YAML.method(:safe_load).parameters.include?([:key, :permitted_classes])
|
53
|
-
YAML.safe_load(payload, permitted_classes: ActiveRecord::Base.yaml_column_permitted_classes, aliases: true)
|
54
|
-
else
|
55
|
-
YAML.safe_load(payload, ActiveRecord::Base.yaml_column_permitted_classes, [], true)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
else
|
59
|
-
def yaml_load(payload)
|
60
|
-
if ActiveRecord::Base.use_yaml_unsafe_load
|
61
|
-
YAML.load(payload)
|
62
|
-
elsif YAML.method(:safe_load).parameters.include?([:key, :permitted_classes])
|
63
|
-
YAML.safe_load(payload, permitted_classes: ActiveRecord::Base.yaml_column_permitted_classes, aliases: true)
|
64
|
-
else
|
65
|
-
YAML.safe_load(payload, ActiveRecord::Base.yaml_column_permitted_classes, [], true)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
47
|
end
|
70
48
|
end
|
71
49
|
end
|