activerecord 5.1.7 → 5.2.0.beta1
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 +221 -900
- data/README.rdoc +3 -3
- data/examples/performance.rb +2 -0
- data/examples/simple.rb +2 -0
- data/lib/active_record.rb +10 -3
- data/lib/active_record/aggregations.rb +2 -0
- data/lib/active_record/association_relation.rb +2 -0
- data/lib/active_record/associations.rb +13 -42
- data/lib/active_record/associations/alias_tracker.rb +17 -17
- data/lib/active_record/associations/association.rb +11 -22
- data/lib/active_record/associations/association_scope.rb +32 -44
- data/lib/active_record/associations/belongs_to_association.rb +6 -4
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -1
- data/lib/active_record/associations/builder/association.rb +2 -5
- data/lib/active_record/associations/builder/belongs_to.rb +7 -12
- data/lib/active_record/associations/builder/collection_association.rb +1 -1
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -1
- data/lib/active_record/associations/builder/has_many.rb +2 -0
- data/lib/active_record/associations/builder/has_one.rb +2 -0
- data/lib/active_record/associations/builder/singular_association.rb +2 -0
- data/lib/active_record/associations/collection_association.rb +41 -33
- data/lib/active_record/associations/collection_proxy.rb +11 -14
- data/lib/active_record/associations/foreign_association.rb +2 -0
- data/lib/active_record/associations/has_many_association.rb +4 -2
- data/lib/active_record/associations/has_many_through_association.rb +4 -2
- data/lib/active_record/associations/has_one_association.rb +3 -1
- data/lib/active_record/associations/has_one_through_association.rb +3 -1
- data/lib/active_record/associations/join_dependency.rb +22 -40
- data/lib/active_record/associations/join_dependency/join_association.rb +17 -56
- data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
- data/lib/active_record/associations/join_dependency/join_part.rb +2 -9
- data/lib/active_record/associations/preloader.rb +17 -37
- data/lib/active_record/associations/preloader/association.rb +42 -58
- data/lib/active_record/associations/preloader/through_association.rb +71 -79
- data/lib/active_record/associations/singular_association.rb +14 -10
- data/lib/active_record/associations/through_association.rb +3 -1
- data/lib/active_record/attribute_assignment.rb +2 -0
- data/lib/active_record/attribute_decorators.rb +3 -2
- data/lib/active_record/attribute_methods.rb +47 -7
- data/lib/active_record/attribute_methods/before_type_cast.rb +2 -0
- data/lib/active_record/attribute_methods/dirty.rb +25 -214
- data/lib/active_record/attribute_methods/primary_key.rb +7 -6
- data/lib/active_record/attribute_methods/query.rb +2 -0
- data/lib/active_record/attribute_methods/read.rb +8 -2
- data/lib/active_record/attribute_methods/serialization.rb +23 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +6 -8
- data/lib/active_record/attribute_methods/write.rb +21 -9
- data/lib/active_record/attributes.rb +7 -6
- data/lib/active_record/autosave_association.rb +5 -11
- data/lib/active_record/base.rb +2 -0
- data/lib/active_record/callbacks.rb +6 -8
- data/lib/active_record/coders/json.rb +2 -0
- data/lib/active_record/coders/yaml_column.rb +2 -0
- data/lib/active_record/collection_cache_key.rb +10 -5
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +110 -35
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +120 -28
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +7 -2
- data/lib/active_record/connection_adapters/abstract/quoting.rb +14 -33
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +13 -5
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +40 -2
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +103 -63
- data/lib/active_record/connection_adapters/abstract/transaction.rb +45 -9
- data/lib/active_record/connection_adapters/abstract_adapter.rb +62 -90
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +75 -138
- data/lib/active_record/connection_adapters/column.rb +3 -1
- data/lib/active_record/connection_adapters/connection_specification.rb +17 -3
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +3 -1
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +9 -10
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +5 -3
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +7 -6
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +30 -30
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +91 -1
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -2
- data/lib/active_record/connection_adapters/postgresql/column.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +6 -0
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -1
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +3 -11
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +3 -5
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +4 -2
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +10 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +11 -7
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +20 -13
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +79 -65
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +47 -82
- data/lib/active_record/connection_adapters/schema_cache.rb +2 -0
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +19 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +6 -15
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +3 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +71 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +34 -89
- data/lib/active_record/connection_adapters/statement_pool.rb +2 -0
- data/lib/active_record/connection_handling.rb +4 -2
- data/lib/active_record/core.rb +27 -57
- data/lib/active_record/counter_cache.rb +15 -12
- data/lib/active_record/define_callbacks.rb +5 -3
- data/lib/active_record/dynamic_matchers.rb +9 -9
- data/lib/active_record/enum.rb +15 -13
- data/lib/active_record/errors.rb +54 -21
- data/lib/active_record/explain.rb +3 -1
- data/lib/active_record/explain_registry.rb +2 -0
- data/lib/active_record/explain_subscriber.rb +2 -0
- data/lib/active_record/fixture_set/file.rb +2 -0
- data/lib/active_record/fixtures.rb +40 -24
- data/lib/active_record/gem_version.rb +5 -3
- data/lib/active_record/inheritance.rb +6 -5
- data/lib/active_record/integration.rb +58 -19
- data/lib/active_record/internal_metadata.rb +2 -0
- data/lib/active_record/legacy_yaml_adapter.rb +3 -1
- data/lib/active_record/locking/optimistic.rb +31 -20
- data/lib/active_record/locking/pessimistic.rb +10 -7
- data/lib/active_record/log_subscriber.rb +2 -0
- data/lib/active_record/migration.rb +47 -21
- data/lib/active_record/migration/command_recorder.rb +11 -9
- data/lib/active_record/migration/compatibility.rb +20 -2
- data/lib/active_record/migration/join_table.rb +2 -0
- data/lib/active_record/model_schema.rb +29 -38
- data/lib/active_record/nested_attributes.rb +18 -6
- data/lib/active_record/no_touching.rb +3 -1
- data/lib/active_record/null_relation.rb +2 -0
- data/lib/active_record/persistence.rb +184 -40
- data/lib/active_record/query_cache.rb +17 -12
- data/lib/active_record/querying.rb +3 -1
- data/lib/active_record/railtie.rb +54 -1
- data/lib/active_record/railties/console_sandbox.rb +2 -0
- data/lib/active_record/railties/controller_runtime.rb +2 -0
- data/lib/active_record/railties/databases.rake +41 -28
- data/lib/active_record/readonly_attributes.rb +3 -2
- data/lib/active_record/reflection.rb +100 -182
- data/lib/active_record/relation.rb +61 -193
- data/lib/active_record/relation/batches.rb +20 -5
- data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
- data/lib/active_record/relation/calculations.rb +40 -23
- data/lib/active_record/relation/delegation.rb +10 -27
- data/lib/active_record/relation/finder_methods.rb +53 -49
- data/lib/active_record/relation/from_clause.rb +2 -8
- data/lib/active_record/relation/merger.rb +22 -19
- data/lib/active_record/relation/predicate_builder.rb +42 -79
- data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -7
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +12 -1
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +54 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -6
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
- data/lib/active_record/relation/query_attribute.rb +9 -2
- data/lib/active_record/relation/query_methods.rb +80 -69
- data/lib/active_record/relation/record_fetch_warning.rb +2 -0
- data/lib/active_record/relation/spawn_methods.rb +2 -0
- data/lib/active_record/relation/where_clause.rb +50 -67
- data/lib/active_record/relation/where_clause_factory.rb +4 -46
- data/lib/active_record/result.rb +2 -0
- data/lib/active_record/runtime_registry.rb +2 -0
- data/lib/active_record/sanitization.rb +15 -9
- data/lib/active_record/schema.rb +3 -1
- data/lib/active_record/schema_dumper.rb +24 -23
- data/lib/active_record/schema_migration.rb +2 -0
- data/lib/active_record/scoping.rb +9 -8
- data/lib/active_record/scoping/default.rb +6 -7
- data/lib/active_record/scoping/named.rb +15 -7
- data/lib/active_record/secure_token.rb +2 -0
- data/lib/active_record/serialization.rb +2 -0
- data/lib/active_record/statement_cache.rb +22 -12
- data/lib/active_record/store.rb +2 -0
- data/lib/active_record/suppressor.rb +2 -0
- data/lib/active_record/table_metadata.rb +3 -1
- data/lib/active_record/tasks/database_tasks.rb +23 -12
- data/lib/active_record/tasks/mysql_database_tasks.rb +9 -48
- data/lib/active_record/tasks/postgresql_database_tasks.rb +10 -2
- data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -3
- data/lib/active_record/timestamp.rb +5 -12
- data/lib/active_record/touch_later.rb +2 -0
- data/lib/active_record/transactions.rb +9 -7
- data/lib/active_record/translation.rb +2 -0
- data/lib/active_record/type.rb +4 -1
- data/lib/active_record/type/adapter_specific_registry.rb +2 -0
- data/lib/active_record/type/date.rb +2 -0
- data/lib/active_record/type/date_time.rb +2 -0
- data/lib/active_record/type/decimal_without_scale.rb +2 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +2 -0
- data/lib/active_record/type/internal/timezone.rb +2 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +2 -4
- data/lib/active_record/type/text.rb +2 -0
- data/lib/active_record/type/time.rb +2 -0
- data/lib/active_record/type/type_map.rb +2 -0
- data/lib/active_record/type/unsigned_integer.rb +2 -0
- data/lib/active_record/type_caster.rb +2 -0
- data/lib/active_record/type_caster/connection.rb +2 -0
- data/lib/active_record/type_caster/map.rb +2 -0
- data/lib/active_record/validations.rb +2 -0
- data/lib/active_record/validations/absence.rb +2 -0
- data/lib/active_record/validations/associated.rb +2 -0
- data/lib/active_record/validations/length.rb +2 -0
- data/lib/active_record/validations/presence.rb +2 -0
- data/lib/active_record/validations/uniqueness.rb +36 -6
- data/lib/active_record/version.rb +2 -0
- data/lib/rails/generators/active_record.rb +3 -1
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
- data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
- data/lib/rails/generators/active_record/migration.rb +2 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -1
- data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +0 -0
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +0 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +2 -23
- data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +0 -0
- data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
- metadata +25 -38
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -15
- data/lib/active_record/associations/preloader/collection_association.rb +0 -17
- data/lib/active_record/associations/preloader/has_many.rb +0 -15
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
- data/lib/active_record/associations/preloader/has_one.rb +0 -15
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -18
- data/lib/active_record/attribute.rb +0 -240
- data/lib/active_record/attribute/user_provided_default.rb +0 -30
- data/lib/active_record/attribute_mutation_tracker.rb +0 -122
- data/lib/active_record/attribute_set.rb +0 -113
- data/lib/active_record/attribute_set/builder.rb +0 -126
- data/lib/active_record/attribute_set/yaml_encoder.rb +0 -41
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -10
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -59
- data/lib/active_record/type/internal/abstract_json.rb +0 -37
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module Associations
|
3
5
|
class SingularAssociation < Association #:nodoc:
|
@@ -30,24 +32,22 @@ module ActiveRecord
|
|
30
32
|
end
|
31
33
|
|
32
34
|
private
|
33
|
-
|
34
|
-
|
35
|
-
scope.scope_for_create.stringify_keys.except(klass.primary_key)
|
35
|
+
def scope_for_create
|
36
|
+
super.except!(klass.primary_key)
|
36
37
|
end
|
37
38
|
|
38
39
|
def find_target
|
39
|
-
|
40
|
+
scope = self.scope
|
41
|
+
return scope.take if skip_statement_cache?(scope)
|
40
42
|
|
41
43
|
conn = klass.connection
|
42
|
-
sc = reflection.association_scope_cache(conn, owner) do
|
43
|
-
|
44
|
-
|
45
|
-
target_scope.merge(as.scope(self, conn)).limit(1)
|
46
|
-
}
|
44
|
+
sc = reflection.association_scope_cache(conn, owner) do |params|
|
45
|
+
as = AssociationScope.create { params.bind }
|
46
|
+
target_scope.merge!(as.scope(self)).limit(1)
|
47
47
|
end
|
48
48
|
|
49
49
|
binds = AssociationScope.get_bind_values(owner, reflection.chain)
|
50
|
-
sc.execute(binds,
|
50
|
+
sc.execute(binds, conn) do |record|
|
51
51
|
set_inverse_instance record
|
52
52
|
end.first
|
53
53
|
rescue ::RangeError
|
@@ -63,6 +63,10 @@ module ActiveRecord
|
|
63
63
|
end
|
64
64
|
|
65
65
|
def _create_record(attributes, raise_error = false)
|
66
|
+
unless owner.persisted?
|
67
|
+
raise ActiveRecord::RecordNotSaved, "You cannot call create unless the parent is saved"
|
68
|
+
end
|
69
|
+
|
66
70
|
record = build_record(attributes)
|
67
71
|
yield(record) if block_given?
|
68
72
|
saved = record.save
|
@@ -1,10 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module AttributeDecorators # :nodoc:
|
3
5
|
extend ActiveSupport::Concern
|
4
6
|
|
5
7
|
included do
|
6
|
-
class_attribute :attribute_type_decorations, instance_accessor: false # :internal:
|
7
|
-
self.attribute_type_decorations = TypeDecorator.new
|
8
|
+
class_attribute :attribute_type_decorations, instance_accessor: false, default: TypeDecorator.new # :internal:
|
8
9
|
end
|
9
10
|
|
10
11
|
module ClassMethods # :nodoc:
|
@@ -1,7 +1,6 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
3
|
require "mutex_m"
|
4
|
-
require "concurrent/map"
|
5
4
|
|
6
5
|
module ActiveRecord
|
7
6
|
# = Active Record Attribute Methods
|
@@ -34,7 +33,9 @@ module ActiveRecord
|
|
34
33
|
|
35
34
|
BLACKLISTED_CLASS_METHODS = %w(private public protected allocate new name parent superclass)
|
36
35
|
|
37
|
-
class GeneratedAttributeMethods < Module
|
36
|
+
class GeneratedAttributeMethods < Module #:nodoc:
|
37
|
+
include Mutex_m
|
38
|
+
end
|
38
39
|
|
39
40
|
module ClassMethods
|
40
41
|
def inherited(child_class) #:nodoc:
|
@@ -43,7 +44,7 @@ module ActiveRecord
|
|
43
44
|
end
|
44
45
|
|
45
46
|
def initialize_generated_modules # :nodoc:
|
46
|
-
@generated_attribute_methods = GeneratedAttributeMethods.new
|
47
|
+
@generated_attribute_methods = GeneratedAttributeMethods.new
|
47
48
|
@attribute_methods_generated = false
|
48
49
|
include @generated_attribute_methods
|
49
50
|
|
@@ -62,7 +63,6 @@ module ActiveRecord
|
|
62
63
|
super(attribute_names)
|
63
64
|
@attribute_methods_generated = true
|
64
65
|
end
|
65
|
-
true
|
66
66
|
end
|
67
67
|
|
68
68
|
def undefine_attribute_methods # :nodoc:
|
@@ -167,6 +167,46 @@ module ActiveRecord
|
|
167
167
|
end
|
168
168
|
end
|
169
169
|
|
170
|
+
# Regexp whitelist. Matches the following:
|
171
|
+
# "#{table_name}.#{column_name}"
|
172
|
+
# "#{column_name}"
|
173
|
+
COLUMN_NAME_WHITELIST = /\A(?:\w+\.)?\w+\z/i
|
174
|
+
|
175
|
+
# Regexp whitelist. Matches the following:
|
176
|
+
# "#{table_name}.#{column_name}"
|
177
|
+
# "#{table_name}.#{column_name} #{direction}"
|
178
|
+
# "#{column_name}"
|
179
|
+
# "#{column_name} #{direction}"
|
180
|
+
COLUMN_NAME_ORDER_WHITELIST = /\A(?:\w+\.)?\w+(?:\s+asc|\s+desc)?\z/i
|
181
|
+
|
182
|
+
def enforce_raw_sql_whitelist(args, whitelist: COLUMN_NAME_WHITELIST) # :nodoc:
|
183
|
+
unexpected = args.reject do |arg|
|
184
|
+
arg.kind_of?(Arel::Node) ||
|
185
|
+
arg.is_a?(Arel::Nodes::SqlLiteral) ||
|
186
|
+
arg.is_a?(Arel::Attributes::Attribute) ||
|
187
|
+
arg.to_s.split(/\s*,\s*/).all? { |part| whitelist.match?(part) }
|
188
|
+
end
|
189
|
+
|
190
|
+
return if unexpected.none?
|
191
|
+
|
192
|
+
if allow_unsafe_raw_sql == :deprecated
|
193
|
+
ActiveSupport::Deprecation.warn(
|
194
|
+
"Dangerous query method (method whose arguments are used as raw " \
|
195
|
+
"SQL) called with non-attribute argument(s): " \
|
196
|
+
"#{unexpected.map(&:inspect).join(", ")}. Non-attribute " \
|
197
|
+
"arguments will be disallowed in Rails 6.0. This method should " \
|
198
|
+
"not be called with user-provided values, such as request " \
|
199
|
+
"parameters or model attributes. Known-safe values can be passed " \
|
200
|
+
"by wrapping them in Arel.sql()."
|
201
|
+
)
|
202
|
+
else
|
203
|
+
raise(ActiveRecord::UnknownAttributeReference,
|
204
|
+
"Query method called with non-attribute argument(s): " +
|
205
|
+
unexpected.map(&:inspect).join(", ")
|
206
|
+
)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
170
210
|
# Returns true if the given attribute exists, otherwise false.
|
171
211
|
#
|
172
212
|
# class Person < ActiveRecord::Base
|
@@ -236,7 +276,7 @@ module ActiveRecord
|
|
236
276
|
return has_attribute?(name)
|
237
277
|
end
|
238
278
|
|
239
|
-
|
279
|
+
true
|
240
280
|
end
|
241
281
|
|
242
282
|
# Returns +true+ if the given attribute is in the attributes hash, otherwise +false+.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require "active_support/core_ext/module/attribute_accessors"
|
3
|
-
require "active_record/attribute_mutation_tracker"
|
4
4
|
|
5
5
|
module ActiveRecord
|
6
6
|
module AttributeMethods
|
@@ -14,11 +14,10 @@ module ActiveRecord
|
|
14
14
|
raise "You cannot include Dirty after Timestamp"
|
15
15
|
end
|
16
16
|
|
17
|
-
class_attribute :partial_writes, instance_writer: false
|
18
|
-
self.partial_writes = true
|
17
|
+
class_attribute :partial_writes, instance_writer: false, default: true
|
19
18
|
|
20
|
-
after_create {
|
21
|
-
after_update {
|
19
|
+
after_create { changes_applied }
|
20
|
+
after_update { changes_applied }
|
22
21
|
|
23
22
|
# Attribute methods for "changed in last call to save?"
|
24
23
|
attribute_method_affix(prefix: "saved_change_to_", suffix: "?")
|
@@ -30,107 +29,18 @@ module ActiveRecord
|
|
30
29
|
attribute_method_suffix("_change_to_be_saved", "_in_database")
|
31
30
|
end
|
32
31
|
|
33
|
-
# Attempts to +save+ the record and clears changed attributes if successful.
|
34
|
-
def save(*)
|
35
|
-
if status = super
|
36
|
-
changes_applied
|
37
|
-
end
|
38
|
-
status
|
39
|
-
end
|
40
|
-
|
41
|
-
# Attempts to <tt>save!</tt> the record and clears changed attributes if successful.
|
42
|
-
def save!(*)
|
43
|
-
super.tap do
|
44
|
-
changes_applied
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
32
|
# <tt>reload</tt> the record and clears changed attributes.
|
49
33
|
def reload(*)
|
50
34
|
super.tap do
|
51
|
-
@
|
52
|
-
|
53
|
-
@
|
54
|
-
|
55
|
-
end
|
56
|
-
|
57
|
-
def initialize_dup(other) # :nodoc:
|
58
|
-
super
|
59
|
-
@attributes = self.class._default_attributes.map do |attr|
|
60
|
-
attr.with_value_from_user(@attributes.fetch_value(attr.name))
|
61
|
-
end
|
62
|
-
clear_mutation_trackers
|
63
|
-
end
|
64
|
-
|
65
|
-
def changes_internally_applied # :nodoc:
|
66
|
-
@mutations_before_last_save = mutations_from_database
|
67
|
-
forget_attribute_assignments
|
68
|
-
@mutations_from_database = AttributeMutationTracker.new(@attributes)
|
69
|
-
end
|
70
|
-
|
71
|
-
def changes_applied # :nodoc:
|
72
|
-
@previous_mutation_tracker = mutation_tracker
|
73
|
-
@changed_attributes = ActiveSupport::HashWithIndifferentAccess.new
|
74
|
-
@mutation_tracker = nil
|
75
|
-
@mutations_from_database = nil
|
76
|
-
end
|
77
|
-
|
78
|
-
def clear_changes_information # :nodoc:
|
79
|
-
@previous_mutation_tracker = nil
|
80
|
-
@changed_attributes = ActiveSupport::HashWithIndifferentAccess.new
|
81
|
-
forget_attribute_assignments
|
82
|
-
clear_mutation_trackers
|
83
|
-
end
|
84
|
-
|
85
|
-
def raw_write_attribute(attr_name, *) # :nodoc:
|
86
|
-
result = super
|
87
|
-
clear_attribute_change(attr_name)
|
88
|
-
result
|
89
|
-
end
|
90
|
-
|
91
|
-
def clear_attribute_changes(attr_names) # :nodoc:
|
92
|
-
super
|
93
|
-
attr_names.each do |attr_name|
|
94
|
-
clear_attribute_change(attr_name)
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
def changed_attributes # :nodoc:
|
99
|
-
# This should only be set by methods which will call changed_attributes
|
100
|
-
# multiple times when it is known that the computed value cannot change.
|
101
|
-
if defined?(@cached_changed_attributes)
|
102
|
-
@cached_changed_attributes
|
103
|
-
else
|
104
|
-
emit_warning_if_needed("changed_attributes", "saved_changes.transform_values(&:first)")
|
105
|
-
super.reverse_merge(mutation_tracker.changed_values).freeze
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
def changes # :nodoc:
|
110
|
-
cache_changed_attributes do
|
111
|
-
emit_warning_if_needed("changes", "saved_changes")
|
112
|
-
super
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
def previous_changes # :nodoc:
|
117
|
-
unless previous_mutation_tracker.equal?(mutations_before_last_save)
|
118
|
-
ActiveSupport::Deprecation.warn(<<-EOW.strip_heredoc)
|
119
|
-
The behavior of `previous_changes` inside of after callbacks is
|
120
|
-
deprecated without replacement. In the next release of Rails,
|
121
|
-
this method inside of `after_save` will return the changes that
|
122
|
-
were just saved.
|
123
|
-
EOW
|
35
|
+
@previously_changed = ActiveSupport::HashWithIndifferentAccess.new
|
36
|
+
@mutations_before_last_save = nil
|
37
|
+
@attributes_changed_by_setter = ActiveSupport::HashWithIndifferentAccess.new
|
38
|
+
@mutations_from_database = nil
|
124
39
|
end
|
125
|
-
previous_mutation_tracker.changes
|
126
|
-
end
|
127
|
-
|
128
|
-
def attribute_changed_in_place?(attr_name) # :nodoc:
|
129
|
-
mutation_tracker.changed_in_place?(attr_name)
|
130
40
|
end
|
131
41
|
|
132
42
|
# Did this attribute change when we last saved? This method can be invoked
|
133
|
-
# as
|
43
|
+
# as +saved_change_to_name?+ instead of <tt>saved_change_to_attribute?("name")</tt>.
|
134
44
|
# Behaves similarly to +attribute_changed?+. This method is useful in
|
135
45
|
# after callbacks to determine if the call to save changed a certain
|
136
46
|
# attribute.
|
@@ -153,8 +63,8 @@ module ActiveRecord
|
|
153
63
|
# Behaves similarly to +attribute_change+. This method is useful in after
|
154
64
|
# callbacks, to see the change in an attribute that just occurred
|
155
65
|
#
|
156
|
-
# This method can be invoked as
|
157
|
-
#
|
66
|
+
# This method can be invoked as +saved_change_to_name+ in instead of
|
67
|
+
# <tt>saved_change_to_attribute("name")</tt>
|
158
68
|
def saved_change_to_attribute(attr_name)
|
159
69
|
mutations_before_last_save.change_to_attribute(attr_name)
|
160
70
|
end
|
@@ -167,7 +77,7 @@ module ActiveRecord
|
|
167
77
|
mutations_before_last_save.original_value(attr_name)
|
168
78
|
end
|
169
79
|
|
170
|
-
# Did the last call to
|
80
|
+
# Did the last call to +save+ have any changes to change?
|
171
81
|
def saved_changes?
|
172
82
|
mutations_before_last_save.any_changes?
|
173
83
|
end
|
@@ -177,116 +87,46 @@ module ActiveRecord
|
|
177
87
|
mutations_before_last_save.changes
|
178
88
|
end
|
179
89
|
|
180
|
-
# Alias for
|
90
|
+
# Alias for +attribute_changed?+
|
181
91
|
def will_save_change_to_attribute?(attr_name, **options)
|
182
92
|
mutations_from_database.changed?(attr_name, **options)
|
183
93
|
end
|
184
94
|
|
185
|
-
# Alias for
|
95
|
+
# Alias for +attribute_change+
|
186
96
|
def attribute_change_to_be_saved(attr_name)
|
187
97
|
mutations_from_database.change_to_attribute(attr_name)
|
188
98
|
end
|
189
99
|
|
190
|
-
# Alias for
|
100
|
+
# Alias for +attribute_was+
|
191
101
|
def attribute_in_database(attr_name)
|
192
102
|
mutations_from_database.original_value(attr_name)
|
193
103
|
end
|
194
104
|
|
195
|
-
# Alias for
|
105
|
+
# Alias for +changed?+
|
196
106
|
def has_changes_to_save?
|
197
107
|
mutations_from_database.any_changes?
|
198
108
|
end
|
199
109
|
|
200
|
-
# Alias for
|
110
|
+
# Alias for +changes+
|
201
111
|
def changes_to_save
|
202
112
|
mutations_from_database.changes
|
203
113
|
end
|
204
114
|
|
205
|
-
# Alias for
|
115
|
+
# Alias for +changed+
|
206
116
|
def changed_attribute_names_to_save
|
207
|
-
|
117
|
+
changes_to_save.keys
|
208
118
|
end
|
209
119
|
|
210
|
-
# Alias for
|
120
|
+
# Alias for +changed_attributes+
|
211
121
|
def attributes_in_database
|
212
|
-
|
213
|
-
end
|
214
|
-
|
215
|
-
def attribute_was(*)
|
216
|
-
emit_warning_if_needed("attribute_was", "attribute_before_last_save")
|
217
|
-
super
|
218
|
-
end
|
219
|
-
|
220
|
-
def attribute_change(*)
|
221
|
-
emit_warning_if_needed("attribute_change", "saved_change_to_attribute")
|
222
|
-
super
|
223
|
-
end
|
224
|
-
|
225
|
-
def attribute_changed?(*)
|
226
|
-
emit_warning_if_needed("attribute_changed?", "saved_change_to_attribute?")
|
227
|
-
super
|
228
|
-
end
|
229
|
-
|
230
|
-
def changed?(*)
|
231
|
-
emit_warning_if_needed("changed?", "saved_changes?")
|
232
|
-
super
|
233
|
-
end
|
234
|
-
|
235
|
-
def changed(*)
|
236
|
-
emit_warning_if_needed("changed", "saved_changes.keys")
|
237
|
-
super
|
122
|
+
changes_to_save.transform_values(&:first)
|
238
123
|
end
|
239
124
|
|
240
125
|
private
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
end
|
246
|
-
@mutation_tracker ||= AttributeMutationTracker.new(@attributes)
|
247
|
-
end
|
248
|
-
|
249
|
-
def emit_warning_if_needed(method_name, new_method_name)
|
250
|
-
unless mutation_tracker.equal?(mutations_from_database)
|
251
|
-
ActiveSupport::Deprecation.warn(<<-EOW.squish)
|
252
|
-
The behavior of `#{method_name}` inside of after callbacks will
|
253
|
-
be changing in the next version of Rails. The new return value will reflect the
|
254
|
-
behavior of calling the method after `save` returned (e.g. the opposite of what
|
255
|
-
it returns now). To maintain the current behavior, use `#{new_method_name}`
|
256
|
-
instead.
|
257
|
-
EOW
|
258
|
-
end
|
259
|
-
end
|
260
|
-
|
261
|
-
def mutations_from_database
|
262
|
-
unless defined?(@mutations_from_database)
|
263
|
-
@mutations_from_database = nil
|
264
|
-
end
|
265
|
-
@mutations_from_database ||= mutation_tracker
|
266
|
-
end
|
267
|
-
|
268
|
-
def changes_include?(attr_name)
|
269
|
-
super || mutation_tracker.changed?(attr_name)
|
270
|
-
end
|
271
|
-
|
272
|
-
def clear_attribute_change(attr_name)
|
273
|
-
mutation_tracker.forget_change(attr_name)
|
274
|
-
mutations_from_database.forget_change(attr_name)
|
275
|
-
end
|
276
|
-
|
277
|
-
def attribute_will_change!(attr_name)
|
278
|
-
super
|
279
|
-
if self.class.has_attribute?(attr_name)
|
280
|
-
mutations_from_database.force_change(attr_name)
|
281
|
-
else
|
282
|
-
ActiveSupport::Deprecation.warn(<<-EOW.squish)
|
283
|
-
#{attr_name} is not an attribute known to Active Record.
|
284
|
-
This behavior is deprecated and will be removed in the next
|
285
|
-
version of Rails. If you'd like #{attr_name} to be managed
|
286
|
-
by Active Record, add `attribute :#{attr_name} to your class.
|
287
|
-
EOW
|
288
|
-
mutations_from_database.deprecated_force_change(attr_name)
|
289
|
-
end
|
126
|
+
def write_attribute_without_type_cast(attr_name, _)
|
127
|
+
result = super
|
128
|
+
clear_attribute_change(attr_name)
|
129
|
+
result
|
290
130
|
end
|
291
131
|
|
292
132
|
def _update_record(*)
|
@@ -300,35 +140,6 @@ module ActiveRecord
|
|
300
140
|
def keys_for_partial_write
|
301
141
|
changed_attribute_names_to_save & self.class.column_names
|
302
142
|
end
|
303
|
-
|
304
|
-
def forget_attribute_assignments
|
305
|
-
@attributes = @attributes.map(&:forgetting_assignment)
|
306
|
-
end
|
307
|
-
|
308
|
-
def clear_mutation_trackers
|
309
|
-
@mutation_tracker = nil
|
310
|
-
@mutations_from_database = nil
|
311
|
-
@mutations_before_last_save = nil
|
312
|
-
end
|
313
|
-
|
314
|
-
def previous_mutation_tracker
|
315
|
-
@previous_mutation_tracker ||= NullMutationTracker.instance
|
316
|
-
end
|
317
|
-
|
318
|
-
def mutations_before_last_save
|
319
|
-
@mutations_before_last_save ||= previous_mutation_tracker
|
320
|
-
end
|
321
|
-
|
322
|
-
def cache_changed_attributes
|
323
|
-
@cached_changed_attributes = changed_attributes
|
324
|
-
yield
|
325
|
-
ensure
|
326
|
-
clear_changed_attributes_cache
|
327
|
-
end
|
328
|
-
|
329
|
-
def clear_changed_attributes_cache
|
330
|
-
remove_instance_variable(:@cached_changed_attributes) if defined?(@cached_changed_attributes)
|
331
|
-
end
|
332
143
|
end
|
333
144
|
end
|
334
145
|
end
|