activerecord 5.1.7 → 5.2.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +556 -685
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -5
- data/examples/performance.rb +2 -0
- data/examples/simple.rb +2 -0
- data/lib/active_record.rb +11 -4
- data/lib/active_record/aggregations.rb +6 -5
- data/lib/active_record/association_relation.rb +7 -5
- data/lib/active_record/associations.rb +40 -63
- data/lib/active_record/associations/alias_tracker.rb +19 -27
- data/lib/active_record/associations/association.rb +41 -37
- data/lib/active_record/associations/association_scope.rb +38 -50
- data/lib/active_record/associations/belongs_to_association.rb +27 -8
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -8
- data/lib/active_record/associations/builder/association.rb +4 -7
- data/lib/active_record/associations/builder/belongs_to.rb +12 -4
- data/lib/active_record/associations/builder/collection_association.rb +3 -3
- 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 +59 -47
- data/lib/active_record/associations/collection_proxy.rb +20 -49
- data/lib/active_record/associations/foreign_association.rb +2 -0
- data/lib/active_record/associations/has_many_association.rb +12 -1
- data/lib/active_record/associations/has_many_through_association.rb +36 -30
- data/lib/active_record/associations/has_one_association.rb +12 -1
- data/lib/active_record/associations/has_one_through_association.rb +13 -8
- data/lib/active_record/associations/join_dependency.rb +48 -93
- data/lib/active_record/associations/join_dependency/join_association.rb +39 -63
- data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
- data/lib/active_record/associations/join_dependency/join_part.rb +9 -9
- data/lib/active_record/associations/preloader.rb +18 -38
- data/lib/active_record/associations/preloader/association.rb +45 -61
- data/lib/active_record/associations/preloader/through_association.rb +71 -79
- data/lib/active_record/associations/singular_association.rb +14 -16
- data/lib/active_record/associations/through_association.rb +26 -11
- data/lib/active_record/attribute_assignment.rb +2 -5
- data/lib/active_record/attribute_decorators.rb +3 -2
- data/lib/active_record/attribute_methods.rb +65 -24
- data/lib/active_record/attribute_methods/before_type_cast.rb +2 -0
- data/lib/active_record/attribute_methods/dirty.rb +30 -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 +9 -3
- 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 +6 -5
- data/lib/active_record/autosave_association.rb +35 -19
- data/lib/active_record/base.rb +2 -0
- data/lib/active_record/callbacks.rb +8 -6
- 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 +12 -8
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +139 -41
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +7 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +174 -33
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +15 -5
- data/lib/active_record/connection_adapters/abstract/quoting.rb +13 -31
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +14 -5
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +64 -6
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +152 -81
- data/lib/active_record/connection_adapters/abstract/transaction.rb +66 -21
- data/lib/active_record/connection_adapters/abstract_adapter.rb +84 -97
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +92 -165
- 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 +13 -2
- data/lib/active_record/connection_adapters/mysql/column.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +47 -2
- 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 -10
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +30 -30
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +106 -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 +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +2 -0
- 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.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +2 -0
- 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 +4 -2
- 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 +18 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +24 -11
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +20 -13
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +233 -111
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +57 -73
- data/lib/active_record/connection_adapters/schema_cache.rb +4 -2
- 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 +22 -0
- 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 +75 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +81 -94
- 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 +41 -61
- data/lib/active_record/counter_cache.rb +10 -3
- data/lib/active_record/define_callbacks.rb +5 -3
- data/lib/active_record/dynamic_matchers.rb +9 -9
- data/lib/active_record/enum.rb +18 -13
- data/lib/active_record/errors.rb +42 -3
- 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 +67 -60
- data/lib/active_record/gem_version.rb +5 -3
- data/lib/active_record/inheritance.rb +49 -19
- 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 +14 -17
- data/lib/active_record/locking/pessimistic.rb +9 -6
- data/lib/active_record/log_subscriber.rb +43 -0
- data/lib/active_record/migration.rb +189 -139
- data/lib/active_record/migration/command_recorder.rb +11 -9
- data/lib/active_record/migration/compatibility.rb +47 -9
- data/lib/active_record/migration/join_table.rb +2 -0
- data/lib/active_record/model_schema.rb +16 -21
- 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 +167 -16
- data/lib/active_record/query_cache.rb +6 -8
- data/lib/active_record/querying.rb +4 -2
- data/lib/active_record/railtie.rb +62 -6
- 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 +46 -36
- data/lib/active_record/readonly_attributes.rb +3 -2
- data/lib/active_record/reflection.rb +108 -194
- data/lib/active_record/relation.rb +120 -214
- 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 +45 -19
- data/lib/active_record/relation/delegation.rb +45 -27
- data/lib/active_record/relation/finder_methods.rb +75 -76
- data/lib/active_record/relation/from_clause.rb +2 -8
- data/lib/active_record/relation/merger.rb +53 -23
- data/lib/active_record/relation/predicate_builder.rb +60 -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 +56 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +26 -9
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
- data/lib/active_record/relation/query_attribute.rb +28 -2
- data/lib/active_record/relation/query_methods.rb +128 -99
- data/lib/active_record/relation/record_fetch_warning.rb +2 -0
- data/lib/active_record/relation/spawn_methods.rb +4 -2
- data/lib/active_record/relation/where_clause.rb +65 -68
- data/lib/active_record/relation/where_clause_factory.rb +5 -48
- data/lib/active_record/result.rb +2 -0
- data/lib/active_record/runtime_registry.rb +2 -0
- data/lib/active_record/sanitization.rb +129 -121
- data/lib/active_record/schema.rb +4 -2
- data/lib/active_record/schema_dumper.rb +36 -26
- data/lib/active_record/schema_migration.rb +2 -0
- data/lib/active_record/scoping.rb +9 -8
- data/lib/active_record/scoping/default.rb +8 -9
- data/lib/active_record/scoping/named.rb +23 -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 +23 -13
- data/lib/active_record/store.rb +3 -1
- data/lib/active_record/suppressor.rb +2 -0
- data/lib/active_record/table_metadata.rb +12 -3
- data/lib/active_record/tasks/database_tasks.rb +25 -14
- 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 +6 -6
- data/lib/active_record/touch_later.rb +2 -0
- data/lib/active_record/transactions.rb +33 -28
- 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 -0
- 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 +3 -1
- 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 +35 -5
- 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 +23 -36
- 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,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,7 @@ 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
|
19
|
-
|
20
|
-
after_create { changes_internally_applied }
|
21
|
-
after_update { changes_internally_applied }
|
17
|
+
class_attribute :partial_writes, instance_writer: false, default: true
|
22
18
|
|
23
19
|
# Attribute methods for "changed in last call to save?"
|
24
20
|
attribute_method_affix(prefix: "saved_change_to_", suffix: "?")
|
@@ -30,107 +26,18 @@ module ActiveRecord
|
|
30
26
|
attribute_method_suffix("_change_to_be_saved", "_in_database")
|
31
27
|
end
|
32
28
|
|
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
29
|
# <tt>reload</tt> the record and clears changed attributes.
|
49
30
|
def reload(*)
|
50
31
|
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
|
32
|
+
@previously_changed = ActiveSupport::HashWithIndifferentAccess.new
|
33
|
+
@mutations_before_last_save = nil
|
34
|
+
@attributes_changed_by_setter = ActiveSupport::HashWithIndifferentAccess.new
|
35
|
+
@mutations_from_database = nil
|
124
36
|
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
37
|
end
|
131
38
|
|
132
39
|
# Did this attribute change when we last saved? This method can be invoked
|
133
|
-
# as
|
40
|
+
# as +saved_change_to_name?+ instead of <tt>saved_change_to_attribute?("name")</tt>.
|
134
41
|
# Behaves similarly to +attribute_changed?+. This method is useful in
|
135
42
|
# after callbacks to determine if the call to save changed a certain
|
136
43
|
# attribute.
|
@@ -153,8 +60,8 @@ module ActiveRecord
|
|
153
60
|
# Behaves similarly to +attribute_change+. This method is useful in after
|
154
61
|
# callbacks, to see the change in an attribute that just occurred
|
155
62
|
#
|
156
|
-
# This method can be invoked as
|
157
|
-
#
|
63
|
+
# This method can be invoked as +saved_change_to_name+ in instead of
|
64
|
+
# <tt>saved_change_to_attribute("name")</tt>
|
158
65
|
def saved_change_to_attribute(attr_name)
|
159
66
|
mutations_before_last_save.change_to_attribute(attr_name)
|
160
67
|
end
|
@@ -167,7 +74,7 @@ module ActiveRecord
|
|
167
74
|
mutations_before_last_save.original_value(attr_name)
|
168
75
|
end
|
169
76
|
|
170
|
-
# Did the last call to
|
77
|
+
# Did the last call to +save+ have any changes to change?
|
171
78
|
def saved_changes?
|
172
79
|
mutations_before_last_save.any_changes?
|
173
80
|
end
|
@@ -177,158 +84,67 @@ module ActiveRecord
|
|
177
84
|
mutations_before_last_save.changes
|
178
85
|
end
|
179
86
|
|
180
|
-
# Alias for
|
87
|
+
# Alias for +attribute_changed?+
|
181
88
|
def will_save_change_to_attribute?(attr_name, **options)
|
182
89
|
mutations_from_database.changed?(attr_name, **options)
|
183
90
|
end
|
184
91
|
|
185
|
-
# Alias for
|
92
|
+
# Alias for +attribute_change+
|
186
93
|
def attribute_change_to_be_saved(attr_name)
|
187
94
|
mutations_from_database.change_to_attribute(attr_name)
|
188
95
|
end
|
189
96
|
|
190
|
-
# Alias for
|
97
|
+
# Alias for +attribute_was+
|
191
98
|
def attribute_in_database(attr_name)
|
192
99
|
mutations_from_database.original_value(attr_name)
|
193
100
|
end
|
194
101
|
|
195
|
-
# Alias for
|
102
|
+
# Alias for +changed?+
|
196
103
|
def has_changes_to_save?
|
197
104
|
mutations_from_database.any_changes?
|
198
105
|
end
|
199
106
|
|
200
|
-
# Alias for
|
107
|
+
# Alias for +changes+
|
201
108
|
def changes_to_save
|
202
109
|
mutations_from_database.changes
|
203
110
|
end
|
204
111
|
|
205
|
-
# Alias for
|
112
|
+
# Alias for +changed+
|
206
113
|
def changed_attribute_names_to_save
|
207
114
|
mutations_from_database.changed_attribute_names
|
208
115
|
end
|
209
116
|
|
210
|
-
# Alias for
|
117
|
+
# Alias for +changed_attributes+
|
211
118
|
def attributes_in_database
|
212
119
|
mutations_from_database.changed_values
|
213
120
|
end
|
214
121
|
|
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
|
238
|
-
end
|
239
|
-
|
240
122
|
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)
|
123
|
+
def write_attribute_without_type_cast(attr_name, value)
|
124
|
+
name = attr_name.to_s
|
125
|
+
if self.class.attribute_alias?(name)
|
126
|
+
name = self.class.attribute_alias(name)
|
289
127
|
end
|
128
|
+
result = super(name, value)
|
129
|
+
clear_attribute_change(name)
|
130
|
+
result
|
290
131
|
end
|
291
132
|
|
292
133
|
def _update_record(*)
|
293
|
-
partial_writes? ? super(keys_for_partial_write) : super
|
134
|
+
affected_rows = partial_writes? ? super(keys_for_partial_write) : super
|
135
|
+
changes_applied
|
136
|
+
affected_rows
|
294
137
|
end
|
295
138
|
|
296
139
|
def _create_record(*)
|
297
|
-
partial_writes? ? super(keys_for_partial_write) : super
|
140
|
+
id = partial_writes? ? super(keys_for_partial_write) : super
|
141
|
+
changes_applied
|
142
|
+
id
|
298
143
|
end
|
299
144
|
|
300
145
|
def keys_for_partial_write
|
301
146
|
changed_attribute_names_to_save & self.class.column_names
|
302
147
|
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
148
|
end
|
333
149
|
end
|
334
150
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "set"
|
2
4
|
|
3
5
|
module ActiveRecord
|
@@ -8,23 +10,22 @@ module ActiveRecord
|
|
8
10
|
# Returns this record's primary key value wrapped in an array if one is
|
9
11
|
# available.
|
10
12
|
def to_key
|
11
|
-
sync_with_transaction_state
|
12
13
|
key = id
|
13
14
|
[key] if key
|
14
15
|
end
|
15
16
|
|
16
17
|
# Returns the primary key value.
|
17
18
|
def id
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
end
|
19
|
+
sync_with_transaction_state
|
20
|
+
primary_key = self.class.primary_key
|
21
|
+
_read_attribute(primary_key) if primary_key
|
22
22
|
end
|
23
23
|
|
24
24
|
# Sets the primary key value.
|
25
25
|
def id=(value)
|
26
26
|
sync_with_transaction_state
|
27
|
-
|
27
|
+
primary_key = self.class.primary_key
|
28
|
+
_write_attribute(primary_key, value) if primary_key
|
28
29
|
end
|
29
30
|
|
30
31
|
# Queries the primary key value.
|
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module AttributeMethods
|
3
5
|
module Read
|
4
6
|
extend ActiveSupport::Concern
|
5
7
|
|
6
|
-
module ClassMethods
|
8
|
+
module ClassMethods # :nodoc:
|
7
9
|
private
|
8
10
|
|
9
11
|
# We want to generate the methods via module_eval rather than
|
@@ -29,9 +31,11 @@ module ActiveRecord
|
|
29
31
|
temp_method = "__temp__#{safe_name}"
|
30
32
|
|
31
33
|
ActiveRecord::AttributeMethods::AttrNames.set_name_cache safe_name, name
|
34
|
+
sync_with_transaction_state = "sync_with_transaction_state" if name == primary_key
|
32
35
|
|
33
36
|
generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
|
34
37
|
def #{temp_method}
|
38
|
+
#{sync_with_transaction_state}
|
35
39
|
name = ::ActiveRecord::AttributeMethods::AttrNames::ATTR_#{safe_name}
|
36
40
|
_read_attribute(name) { |n| missing_attribute(n, caller) }
|
37
41
|
end
|
@@ -54,7 +58,9 @@ module ActiveRecord
|
|
54
58
|
attr_name.to_s
|
55
59
|
end
|
56
60
|
|
57
|
-
|
61
|
+
primary_key = self.class.primary_key
|
62
|
+
name = primary_key if name == "id".freeze && primary_key
|
63
|
+
sync_with_transaction_state if name == primary_key
|
58
64
|
_read_attribute(name, &block)
|
59
65
|
end
|
60
66
|
|
@@ -63,7 +69,7 @@ module ActiveRecord
|
|
63
69
|
if defined?(JRUBY_VERSION)
|
64
70
|
# This form is significantly faster on JRuby, and this is one of our biggest hotspots.
|
65
71
|
# https://github.com/jruby/jruby/pull/2562
|
66
|
-
def _read_attribute(attr_name, &block) # :nodoc
|
72
|
+
def _read_attribute(attr_name, &block) # :nodoc:
|
67
73
|
@attributes.fetch_value(attr_name.to_s, &block)
|
68
74
|
end
|
69
75
|
else
|
@@ -1,8 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module AttributeMethods
|
3
5
|
module Serialization
|
4
6
|
extend ActiveSupport::Concern
|
5
7
|
|
8
|
+
class ColumnNotSerializableError < StandardError
|
9
|
+
def initialize(name, type)
|
10
|
+
super <<-EOS.strip_heredoc
|
11
|
+
Column `#{name}` of type #{type.class} does not support `serialize` feature.
|
12
|
+
Usually it means that you are trying to use `serialize`
|
13
|
+
on a column that already implements serialization natively.
|
14
|
+
EOS
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
6
18
|
module ClassMethods
|
7
19
|
# If you have an attribute that needs to be saved to the database as an
|
8
20
|
# object, and retrieved as the same object, then specify the name of that
|
@@ -58,9 +70,20 @@ module ActiveRecord
|
|
58
70
|
end
|
59
71
|
|
60
72
|
decorate_attribute_type(attr_name, :serialize) do |type|
|
73
|
+
if type_incompatible_with_serialize?(type, class_name_or_coder)
|
74
|
+
raise ColumnNotSerializableError.new(attr_name, type)
|
75
|
+
end
|
76
|
+
|
61
77
|
Type::Serialized.new(type, coder)
|
62
78
|
end
|
63
79
|
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def type_incompatible_with_serialize?(type, class_name)
|
84
|
+
type.is_a?(ActiveRecord::Type::Json) && class_name == ::JSON ||
|
85
|
+
type.respond_to?(:type_cast_array, true) && class_name == ::Array
|
86
|
+
end
|
64
87
|
end
|
65
88
|
end
|
66
89
|
end
|