activerecord 5.0.7.2 → 5.1.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 +389 -2252
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/examples/performance.rb +28 -28
- data/examples/simple.rb +3 -3
- data/lib/active_record.rb +20 -20
- data/lib/active_record/aggregations.rb +244 -244
- data/lib/active_record/association_relation.rb +5 -5
- data/lib/active_record/associations.rb +1579 -1569
- data/lib/active_record/associations/alias_tracker.rb +1 -1
- data/lib/active_record/associations/association.rb +23 -15
- data/lib/active_record/associations/association_scope.rb +83 -81
- data/lib/active_record/associations/belongs_to_association.rb +0 -1
- data/lib/active_record/associations/builder/belongs_to.rb +16 -14
- data/lib/active_record/associations/builder/collection_association.rb +1 -2
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +27 -27
- data/lib/active_record/associations/collection_association.rb +74 -241
- data/lib/active_record/associations/collection_proxy.rb +144 -70
- data/lib/active_record/associations/has_many_association.rb +15 -19
- data/lib/active_record/associations/has_many_through_association.rb +12 -5
- data/lib/active_record/associations/has_one_association.rb +22 -28
- data/lib/active_record/associations/has_one_through_association.rb +5 -1
- data/lib/active_record/associations/join_dependency.rb +117 -115
- data/lib/active_record/associations/join_dependency/join_association.rb +16 -13
- data/lib/active_record/associations/join_dependency/join_base.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_part.rb +1 -1
- data/lib/active_record/associations/preloader.rb +94 -94
- data/lib/active_record/associations/preloader/association.rb +87 -64
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -2
- data/lib/active_record/associations/preloader/collection_association.rb +6 -6
- data/lib/active_record/associations/preloader/has_many.rb +0 -2
- data/lib/active_record/associations/preloader/singular_association.rb +6 -8
- data/lib/active_record/associations/preloader/through_association.rb +34 -41
- data/lib/active_record/associations/singular_association.rb +8 -25
- data/lib/active_record/associations/through_association.rb +3 -6
- data/lib/active_record/attribute.rb +98 -71
- data/lib/active_record/attribute/user_provided_default.rb +4 -2
- data/lib/active_record/attribute_assignment.rb +61 -61
- data/lib/active_record/attribute_decorators.rb +35 -13
- data/lib/active_record/attribute_methods.rb +56 -65
- data/lib/active_record/attribute_methods/before_type_cast.rb +7 -7
- data/lib/active_record/attribute_methods/dirty.rb +216 -34
- data/lib/active_record/attribute_methods/primary_key.rb +78 -73
- data/lib/active_record/attribute_methods/read.rb +39 -35
- data/lib/active_record/attribute_methods/serialization.rb +7 -7
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +35 -58
- data/lib/active_record/attribute_methods/write.rb +36 -30
- data/lib/active_record/attribute_mutation_tracker.rb +53 -10
- data/lib/active_record/attribute_set.rb +9 -6
- data/lib/active_record/attribute_set/builder.rb +41 -49
- data/lib/active_record/attribute_set/yaml_encoder.rb +41 -0
- data/lib/active_record/attributes.rb +21 -21
- data/lib/active_record/autosave_association.rb +13 -13
- data/lib/active_record/base.rb +24 -22
- data/lib/active_record/callbacks.rb +52 -14
- data/lib/active_record/coders/yaml_column.rb +9 -11
- data/lib/active_record/collection_cache_key.rb +6 -17
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +320 -278
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +1 -3
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +22 -34
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +31 -27
- data/lib/active_record/connection_adapters/abstract/quoting.rb +44 -57
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +9 -19
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +78 -79
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +53 -41
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +99 -93
- data/lib/active_record/connection_adapters/abstract/transaction.rb +1 -5
- data/lib/active_record/connection_adapters/abstract_adapter.rb +156 -128
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +424 -382
- data/lib/active_record/connection_adapters/column.rb +27 -5
- data/lib/active_record/connection_adapters/connection_specification.rb +128 -118
- data/lib/active_record/connection_adapters/mysql/column.rb +6 -31
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +45 -43
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +22 -22
- data/lib/active_record/connection_adapters/mysql/quoting.rb +6 -12
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +49 -45
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +16 -19
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +49 -31
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +5 -6
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +24 -26
- data/lib/active_record/connection_adapters/postgresql/column.rb +1 -28
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +46 -35
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +22 -21
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +9 -9
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +16 -16
- data/lib/active_record/connection_adapters/postgresql/oid/{rails_5_1_point.rb → legacy_point.rb} +9 -16
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +28 -8
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +28 -30
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +51 -51
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +38 -36
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +37 -24
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +19 -23
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +161 -170
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -7
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +179 -152
- data/lib/active_record/connection_adapters/schema_cache.rb +16 -7
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +3 -3
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +1 -1
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +16 -20
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +1 -8
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +28 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +17 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +187 -130
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -7
- data/lib/active_record/connection_handling.rb +14 -26
- data/lib/active_record/core.rb +110 -93
- data/lib/active_record/counter_cache.rb +62 -13
- data/lib/active_record/define_callbacks.rb +20 -0
- data/lib/active_record/dynamic_matchers.rb +80 -79
- data/lib/active_record/enum.rb +8 -6
- data/lib/active_record/errors.rb +58 -15
- data/lib/active_record/explain.rb +1 -2
- data/lib/active_record/explain_registry.rb +1 -1
- data/lib/active_record/explain_subscriber.rb +7 -4
- data/lib/active_record/fixture_set/file.rb +11 -8
- data/lib/active_record/fixtures.rb +66 -53
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +93 -79
- data/lib/active_record/integration.rb +7 -7
- data/lib/active_record/internal_metadata.rb +3 -16
- data/lib/active_record/legacy_yaml_adapter.rb +1 -1
- data/lib/active_record/locking/optimistic.rb +64 -56
- data/lib/active_record/locking/pessimistic.rb +10 -1
- data/lib/active_record/log_subscriber.rb +29 -29
- data/lib/active_record/migration.rb +155 -172
- data/lib/active_record/migration/command_recorder.rb +94 -94
- data/lib/active_record/migration/compatibility.rb +76 -37
- data/lib/active_record/migration/join_table.rb +6 -6
- data/lib/active_record/model_schema.rb +85 -119
- data/lib/active_record/nested_attributes.rb +200 -199
- data/lib/active_record/null_relation.rb +10 -33
- data/lib/active_record/persistence.rb +45 -38
- data/lib/active_record/query_cache.rb +4 -8
- data/lib/active_record/querying.rb +2 -3
- data/lib/active_record/railtie.rb +16 -17
- data/lib/active_record/railties/controller_runtime.rb +6 -2
- data/lib/active_record/railties/databases.rake +125 -140
- data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
- data/lib/active_record/readonly_attributes.rb +2 -2
- data/lib/active_record/reflection.rb +79 -96
- data/lib/active_record/relation.rb +72 -115
- data/lib/active_record/relation/batches.rb +87 -58
- data/lib/active_record/relation/batches/batch_enumerator.rb +1 -1
- data/lib/active_record/relation/calculations.rb +154 -160
- data/lib/active_record/relation/delegation.rb +30 -29
- data/lib/active_record/relation/finder_methods.rb +195 -226
- data/lib/active_record/relation/merger.rb +58 -62
- data/lib/active_record/relation/predicate_builder.rb +92 -89
- data/lib/active_record/relation/predicate_builder/array_handler.rb +7 -5
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +23 -23
- data/lib/active_record/relation/predicate_builder/base_handler.rb +3 -1
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +0 -8
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +12 -10
- data/lib/active_record/relation/predicate_builder/range_handler.rb +0 -8
- data/lib/active_record/relation/query_attribute.rb +1 -1
- data/lib/active_record/relation/query_methods.rb +247 -295
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +4 -5
- data/lib/active_record/relation/where_clause.rb +79 -65
- data/lib/active_record/relation/where_clause_factory.rb +47 -8
- data/lib/active_record/result.rb +29 -31
- data/lib/active_record/runtime_registry.rb +3 -3
- data/lib/active_record/sanitization.rb +182 -197
- data/lib/active_record/schema.rb +3 -3
- data/lib/active_record/schema_dumper.rb +14 -37
- data/lib/active_record/schema_migration.rb +3 -3
- data/lib/active_record/scoping.rb +9 -10
- data/lib/active_record/scoping/default.rb +87 -91
- data/lib/active_record/scoping/named.rb +16 -28
- data/lib/active_record/secure_token.rb +2 -2
- data/lib/active_record/statement_cache.rb +13 -15
- data/lib/active_record/store.rb +31 -32
- data/lib/active_record/suppressor.rb +2 -1
- data/lib/active_record/table_metadata.rb +9 -5
- data/lib/active_record/tasks/database_tasks.rb +72 -65
- data/lib/active_record/tasks/mysql_database_tasks.rb +75 -72
- data/lib/active_record/tasks/postgresql_database_tasks.rb +53 -48
- data/lib/active_record/tasks/sqlite_database_tasks.rb +18 -16
- data/lib/active_record/timestamp.rb +39 -25
- data/lib/active_record/touch_later.rb +1 -2
- data/lib/active_record/transactions.rb +98 -110
- data/lib/active_record/type.rb +17 -13
- data/lib/active_record/type/adapter_specific_registry.rb +46 -42
- data/lib/active_record/type/decimal_without_scale.rb +9 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +3 -3
- data/lib/active_record/type/serialized.rb +8 -8
- data/lib/active_record/type/text.rb +9 -0
- data/lib/active_record/type/time.rb +0 -1
- data/lib/active_record/type/type_map.rb +11 -15
- data/lib/active_record/type/unsigned_integer.rb +15 -0
- data/lib/active_record/type_caster.rb +2 -2
- data/lib/active_record/type_caster/connection.rb +8 -6
- data/lib/active_record/type_caster/map.rb +3 -1
- data/lib/active_record/validations.rb +4 -4
- data/lib/active_record/validations/associated.rb +1 -1
- data/lib/active_record/validations/presence.rb +2 -2
- data/lib/active_record/validations/uniqueness.rb +8 -39
- data/lib/active_record/version.rb +1 -1
- data/lib/rails/generators/active_record.rb +4 -4
- data/lib/rails/generators/active_record/migration.rb +2 -2
- data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -34
- data/lib/rails/generators/active_record/model/model_generator.rb +9 -9
- metadata +22 -13
- data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
@@ -1,7 +1,11 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
class AttributeMutationTracker # :nodoc:
|
3
|
+
OPTION_NOT_GIVEN = Object.new
|
4
|
+
|
3
5
|
def initialize(attributes)
|
4
6
|
@attributes = attributes
|
7
|
+
@forced_changes = Set.new
|
8
|
+
@deprecated_forced_changes = Set.new
|
5
9
|
end
|
6
10
|
|
7
11
|
def changed_values
|
@@ -14,15 +18,29 @@ module ActiveRecord
|
|
14
18
|
|
15
19
|
def changes
|
16
20
|
attr_names.each_with_object({}.with_indifferent_access) do |attr_name, result|
|
17
|
-
|
18
|
-
|
21
|
+
change = change_to_attribute(attr_name)
|
22
|
+
if change
|
23
|
+
result[attr_name] = change
|
19
24
|
end
|
20
25
|
end
|
21
26
|
end
|
22
27
|
|
23
|
-
def
|
28
|
+
def change_to_attribute(attr_name)
|
29
|
+
if changed?(attr_name)
|
30
|
+
[attributes[attr_name].original_value, attributes.fetch_value(attr_name)]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def any_changes?
|
35
|
+
attr_names.any? { |attr| changed?(attr) } || deprecated_forced_changes.any?
|
36
|
+
end
|
37
|
+
|
38
|
+
def changed?(attr_name, from: OPTION_NOT_GIVEN, to: OPTION_NOT_GIVEN)
|
24
39
|
attr_name = attr_name.to_s
|
25
|
-
|
40
|
+
forced_changes.include?(attr_name) ||
|
41
|
+
attributes[attr_name].changed? &&
|
42
|
+
(OPTION_NOT_GIVEN == from || attributes[attr_name].original_value == from) &&
|
43
|
+
(OPTION_NOT_GIVEN == to || attributes[attr_name].value == to)
|
26
44
|
end
|
27
45
|
|
28
46
|
def changed_in_place?(attr_name)
|
@@ -32,30 +50,52 @@ module ActiveRecord
|
|
32
50
|
def forget_change(attr_name)
|
33
51
|
attr_name = attr_name.to_s
|
34
52
|
attributes[attr_name] = attributes[attr_name].forgetting_assignment
|
53
|
+
forced_changes.delete(attr_name)
|
54
|
+
end
|
55
|
+
|
56
|
+
def original_value(attr_name)
|
57
|
+
attributes[attr_name].original_value
|
58
|
+
end
|
59
|
+
|
60
|
+
def force_change(attr_name)
|
61
|
+
forced_changes << attr_name.to_s
|
62
|
+
end
|
63
|
+
|
64
|
+
def deprecated_force_change(attr_name)
|
65
|
+
deprecated_forced_changes << attr_name.to_s
|
35
66
|
end
|
36
67
|
|
68
|
+
# TODO Change this to private once we've dropped Ruby 2.2 support.
|
69
|
+
# Workaround for Ruby 2.2 "private attribute?" warning.
|
37
70
|
protected
|
38
71
|
|
39
|
-
|
72
|
+
attr_reader :attributes, :forced_changes, :deprecated_forced_changes
|
40
73
|
|
41
74
|
private
|
42
75
|
|
43
|
-
|
44
|
-
|
45
|
-
|
76
|
+
def attr_names
|
77
|
+
attributes.keys
|
78
|
+
end
|
46
79
|
end
|
47
80
|
|
48
81
|
class NullMutationTracker # :nodoc:
|
49
82
|
include Singleton
|
50
83
|
|
51
|
-
def changed_values
|
84
|
+
def changed_values(*)
|
52
85
|
{}
|
53
86
|
end
|
54
87
|
|
55
|
-
def changes
|
88
|
+
def changes(*)
|
56
89
|
{}
|
57
90
|
end
|
58
91
|
|
92
|
+
def change_to_attribute(attr_name)
|
93
|
+
end
|
94
|
+
|
95
|
+
def any_changes?(*)
|
96
|
+
false
|
97
|
+
end
|
98
|
+
|
59
99
|
def changed?(*)
|
60
100
|
false
|
61
101
|
end
|
@@ -66,5 +106,8 @@ module ActiveRecord
|
|
66
106
|
|
67
107
|
def forget_change(*)
|
68
108
|
end
|
109
|
+
|
110
|
+
def original_value(*)
|
111
|
+
end
|
69
112
|
end
|
70
113
|
end
|
@@ -1,8 +1,9 @@
|
|
1
|
-
require
|
1
|
+
require "active_record/attribute_set/builder"
|
2
|
+
require "active_record/attribute_set/yaml_encoder"
|
2
3
|
|
3
4
|
module ActiveRecord
|
4
5
|
class AttributeSet # :nodoc:
|
5
|
-
delegate :
|
6
|
+
delegate :each_value, :fetch, to: :attributes
|
6
7
|
|
7
8
|
def initialize(attributes)
|
8
9
|
@attributes = attributes
|
@@ -97,14 +98,16 @@ module ActiveRecord
|
|
97
98
|
attributes == other.attributes
|
98
99
|
end
|
99
100
|
|
101
|
+
# TODO Change this to private once we've dropped Ruby 2.2 support.
|
102
|
+
# Workaround for Ruby 2.2 "private attribute?" warning.
|
100
103
|
protected
|
101
104
|
|
102
|
-
|
105
|
+
attr_reader :attributes
|
103
106
|
|
104
107
|
private
|
105
108
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
+
def initialized_attributes
|
110
|
+
attributes.select { |_, attr| attr.initialized? }
|
111
|
+
end
|
109
112
|
end
|
110
113
|
end
|
@@ -1,32 +1,37 @@
|
|
1
|
-
require
|
1
|
+
require "active_record/attribute"
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
class AttributeSet # :nodoc:
|
5
5
|
class Builder # :nodoc:
|
6
|
-
attr_reader :types, :
|
6
|
+
attr_reader :types, :always_initialized, :default
|
7
7
|
|
8
|
-
def initialize(types,
|
8
|
+
def initialize(types, always_initialized = nil, &default)
|
9
9
|
@types = types
|
10
|
-
@
|
10
|
+
@always_initialized = always_initialized
|
11
|
+
@default = default
|
11
12
|
end
|
12
13
|
|
13
14
|
def build_from_database(values = {}, additional_types = {})
|
14
|
-
|
15
|
+
if always_initialized && !values.key?(always_initialized)
|
16
|
+
values[always_initialized] = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
attributes = LazyAttributeHash.new(types, values, additional_types, &default)
|
15
20
|
AttributeSet.new(attributes)
|
16
21
|
end
|
17
22
|
end
|
18
23
|
end
|
19
24
|
|
20
25
|
class LazyAttributeHash # :nodoc:
|
21
|
-
delegate :transform_values, :each_key, :
|
26
|
+
delegate :transform_values, :each_key, :each_value, :fetch, to: :materialize
|
22
27
|
|
23
|
-
def initialize(types, values, additional_types,
|
28
|
+
def initialize(types, values, additional_types, &default)
|
24
29
|
@types = types
|
25
30
|
@values = values
|
26
31
|
@additional_types = additional_types
|
27
32
|
@materialized = false
|
28
|
-
@delegate_hash =
|
29
|
-
@
|
33
|
+
@delegate_hash = {}
|
34
|
+
@default = default || proc {}
|
30
35
|
end
|
31
36
|
|
32
37
|
def key?(key)
|
@@ -74,59 +79,46 @@ module ActiveRecord
|
|
74
79
|
end
|
75
80
|
|
76
81
|
def marshal_dump
|
77
|
-
|
78
|
-
end
|
79
|
-
|
80
|
-
def marshal_load(values)
|
81
|
-
if values.is_a?(Hash)
|
82
|
-
empty_hash = {}.freeze
|
83
|
-
initialize(empty_hash, empty_hash, empty_hash, empty_hash, values)
|
84
|
-
@materialized = true
|
85
|
-
else
|
86
|
-
initialize(*values)
|
87
|
-
end
|
82
|
+
materialize
|
88
83
|
end
|
89
84
|
|
90
|
-
def
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
85
|
+
def marshal_load(delegate_hash)
|
86
|
+
@delegate_hash = delegate_hash
|
87
|
+
@types = {}
|
88
|
+
@values = {}
|
89
|
+
@additional_types = {}
|
90
|
+
@materialized = true
|
96
91
|
end
|
97
92
|
|
93
|
+
# TODO Change this to private once we've dropped Ruby 2.2 support.
|
94
|
+
# Workaround for Ruby 2.2 "private attribute?" warning.
|
98
95
|
protected
|
99
96
|
|
100
|
-
|
97
|
+
attr_reader :types, :values, :additional_types, :delegate_hash, :default
|
101
98
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
99
|
+
def materialize
|
100
|
+
unless @materialized
|
101
|
+
values.each_key { |key| self[key] }
|
102
|
+
types.each_key { |key| self[key] }
|
103
|
+
unless frozen?
|
104
|
+
@materialized = true
|
105
|
+
end
|
108
106
|
end
|
107
|
+
delegate_hash
|
109
108
|
end
|
110
|
-
delegate_hash
|
111
|
-
end
|
112
109
|
|
113
110
|
private
|
114
111
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
if attr
|
125
|
-
delegate_hash[name] = attr.dup
|
126
|
-
else
|
127
|
-
delegate_hash[name] = Attribute.uninitialized(name, type)
|
112
|
+
def assign_default_value(name)
|
113
|
+
type = additional_types.fetch(name, types[name])
|
114
|
+
value_present = true
|
115
|
+
value = values.fetch(name) { value_present = false }
|
116
|
+
|
117
|
+
if value_present
|
118
|
+
delegate_hash[name] = Attribute.from_database(name, value, type)
|
119
|
+
elsif types.key?(name)
|
120
|
+
delegate_hash[name] = default.call(name) || Attribute.uninitialized(name, type)
|
128
121
|
end
|
129
122
|
end
|
130
|
-
end
|
131
123
|
end
|
132
124
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
class AttributeSet
|
3
|
+
# Attempts to do more intelligent YAML dumping of an
|
4
|
+
# ActiveRecord::AttributeSet to reduce the size of the resulting string
|
5
|
+
class YAMLEncoder # :nodoc:
|
6
|
+
def initialize(default_types)
|
7
|
+
@default_types = default_types
|
8
|
+
end
|
9
|
+
|
10
|
+
def encode(attribute_set, coder)
|
11
|
+
coder["concise_attributes"] = attribute_set.each_value.map do |attr|
|
12
|
+
if attr.type.equal?(default_types[attr.name])
|
13
|
+
attr.with_type(nil)
|
14
|
+
else
|
15
|
+
attr
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def decode(coder)
|
21
|
+
if coder["attributes"]
|
22
|
+
coder["attributes"]
|
23
|
+
else
|
24
|
+
attributes_hash = Hash[coder["concise_attributes"].map do |attr|
|
25
|
+
if attr.type.nil?
|
26
|
+
attr = attr.with_type(default_types[attr.name])
|
27
|
+
end
|
28
|
+
[attr.name, attr]
|
29
|
+
end]
|
30
|
+
AttributeSet.new(attributes_hash)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# TODO Change this to private once we've dropped Ruby 2.2 support.
|
35
|
+
# Workaround for Ruby 2.2 "private attribute?" warning.
|
36
|
+
protected
|
37
|
+
|
38
|
+
attr_reader :default_types
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "active_record/attribute/user_provided_default"
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
# See ActiveRecord::Attributes::ClassMethods for documentation
|
@@ -116,7 +116,7 @@ module ActiveRecord
|
|
116
116
|
# Users may also define their own custom types, as long as they respond
|
117
117
|
# to the methods defined on the value type. The method +deserialize+ or
|
118
118
|
# +cast+ will be called on your type object, with raw input from the
|
119
|
-
# database or from your controllers. See
|
119
|
+
# database or from your controllers. See ActiveModel::Type::Value for the
|
120
120
|
# expected API. It is recommended that your type objects inherit from an
|
121
121
|
# existing type, or from ActiveRecord::Type::Value
|
122
122
|
#
|
@@ -143,7 +143,7 @@ module ActiveRecord
|
|
143
143
|
# store_listing.price_in_cents # => 1000
|
144
144
|
#
|
145
145
|
# For more details on creating custom types, see the documentation for
|
146
|
-
#
|
146
|
+
# ActiveModel::Type::Value. For more details on registering your types
|
147
147
|
# to be referenced by a symbol, see ActiveRecord::Type.register. You can
|
148
148
|
# also pass a type object directly, in place of a symbol.
|
149
149
|
#
|
@@ -190,8 +190,8 @@ module ActiveRecord
|
|
190
190
|
# The type of an attribute is given the opportunity to change how dirty
|
191
191
|
# tracking is performed. The methods +changed?+ and +changed_in_place?+
|
192
192
|
# will be called from ActiveModel::Dirty. See the documentation for those
|
193
|
-
# methods in
|
194
|
-
def attribute(name, cast_type, **options)
|
193
|
+
# methods in ActiveModel::Type::Value for more details.
|
194
|
+
def attribute(name, cast_type = Type::Value.new, **options)
|
195
195
|
name = name.to_s
|
196
196
|
reload_schema_from_cache
|
197
197
|
|
@@ -242,24 +242,24 @@ module ActiveRecord
|
|
242
242
|
|
243
243
|
private
|
244
244
|
|
245
|
-
|
246
|
-
|
245
|
+
NO_DEFAULT_PROVIDED = Object.new # :nodoc:
|
246
|
+
private_constant :NO_DEFAULT_PROVIDED
|
247
247
|
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
248
|
+
def define_default_attribute(name, value, type, from_user:)
|
249
|
+
if value == NO_DEFAULT_PROVIDED
|
250
|
+
default_attribute = _default_attributes[name].with_type(type)
|
251
|
+
elsif from_user
|
252
|
+
default_attribute = Attribute::UserProvidedDefault.new(
|
253
|
+
name,
|
254
|
+
value,
|
255
|
+
type,
|
256
|
+
_default_attributes.fetch(name.to_s) { nil },
|
257
|
+
)
|
258
|
+
else
|
259
|
+
default_attribute = Attribute.from_database(name, value, type)
|
260
|
+
end
|
261
|
+
_default_attributes[name] = default_attribute
|
260
262
|
end
|
261
|
-
_default_attributes[name] = default_attribute
|
262
|
-
end
|
263
263
|
end
|
264
264
|
end
|
265
265
|
end
|
@@ -154,10 +154,10 @@ module ActiveRecord
|
|
154
154
|
# Loop prevention for validation of associations
|
155
155
|
unless @_already_called[name]
|
156
156
|
begin
|
157
|
-
@_already_called[name]=true
|
157
|
+
@_already_called[name] = true
|
158
158
|
result = instance_eval(&block)
|
159
159
|
ensure
|
160
|
-
@_already_called[name]=false
|
160
|
+
@_already_called[name] = false
|
161
161
|
end
|
162
162
|
end
|
163
163
|
|
@@ -267,7 +267,7 @@ module ActiveRecord
|
|
267
267
|
# Returns whether or not this record has been changed in any way (including whether
|
268
268
|
# any of its nested autosave associations are likewise changed)
|
269
269
|
def changed_for_autosave?
|
270
|
-
new_record? ||
|
270
|
+
new_record? || has_changes_to_save? || marked_for_destruction? || nested_records_changed_for_autosave?
|
271
271
|
end
|
272
272
|
|
273
273
|
private
|
@@ -325,12 +325,12 @@ module ActiveRecord
|
|
325
325
|
# Returns whether or not the association is valid and applies any errors to
|
326
326
|
# the parent, <tt>self</tt>, if it wasn't. Skips any <tt>:autosave</tt>
|
327
327
|
# enabled records if they're marked_for_destruction? or destroyed.
|
328
|
-
def association_valid?(reflection, record, index=nil)
|
328
|
+
def association_valid?(reflection, record, index = nil)
|
329
329
|
return true if record.destroyed? || (reflection.options[:autosave] && record.marked_for_destruction?)
|
330
330
|
|
331
|
-
|
331
|
+
context = validation_context unless [:create, :update].include?(validation_context)
|
332
332
|
|
333
|
-
unless valid = record.valid?(
|
333
|
+
unless valid = record.valid?(context)
|
334
334
|
if reflection.options[:autosave]
|
335
335
|
indexed_attribute = !index.nil? && (reflection.options[:index_errors] || ActiveRecord::Base.index_nested_attribute_errors)
|
336
336
|
|
@@ -383,6 +383,9 @@ module ActiveRecord
|
|
383
383
|
if association = association_instance_get(reflection.name)
|
384
384
|
autosave = reflection.options[:autosave]
|
385
385
|
|
386
|
+
# reconstruct the scope now that we know the owner's id
|
387
|
+
association.reset_scope if association.respond_to?(:reset_scope)
|
388
|
+
|
386
389
|
if records = associated_records_to_validate_or_save(association, @new_record_before_save, autosave)
|
387
390
|
if autosave
|
388
391
|
records_to_destroy = records.select(&:marked_for_destruction?)
|
@@ -402,15 +405,12 @@ module ActiveRecord
|
|
402
405
|
association.insert_record(record) unless reflection.nested?
|
403
406
|
end
|
404
407
|
elsif autosave
|
405
|
-
saved = record.save(:
|
408
|
+
saved = record.save(validate: false)
|
406
409
|
end
|
407
410
|
|
408
411
|
raise ActiveRecord::Rollback unless saved
|
409
412
|
end
|
410
413
|
end
|
411
|
-
|
412
|
-
# reconstruct the scope now that we know the owner's id
|
413
|
-
association.reset_scope if association.respond_to?(:reset_scope)
|
414
414
|
end
|
415
415
|
end
|
416
416
|
|
@@ -439,7 +439,7 @@ module ActiveRecord
|
|
439
439
|
record[reflection.foreign_key] = key
|
440
440
|
end
|
441
441
|
|
442
|
-
saved = record.save(:
|
442
|
+
saved = record.save(validate: !autosave)
|
443
443
|
raise ActiveRecord::Rollback if !saved && autosave
|
444
444
|
saved
|
445
445
|
end
|
@@ -451,7 +451,7 @@ module ActiveRecord
|
|
451
451
|
def record_changed?(reflection, record, key)
|
452
452
|
record.new_record? ||
|
453
453
|
(record.has_attribute?(reflection.foreign_key) && record[reflection.foreign_key] != key) ||
|
454
|
-
record.
|
454
|
+
record.will_save_change_to_attribute?(reflection.foreign_key)
|
455
455
|
end
|
456
456
|
|
457
457
|
# Saves the associated record if it's new or <tt>:autosave</tt> is enabled.
|
@@ -469,7 +469,7 @@ module ActiveRecord
|
|
469
469
|
self[reflection.foreign_key] = nil
|
470
470
|
record.destroy
|
471
471
|
elsif autosave != false
|
472
|
-
saved = record.save(:
|
472
|
+
saved = record.save(validate: !autosave) if record.new_record? || (autosave && record.changed_for_autosave?)
|
473
473
|
|
474
474
|
if association.updated?
|
475
475
|
association_id = record.send(reflection.options[:primary_key] || :id)
|