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.

Files changed (216) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +389 -2252
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/examples/performance.rb +28 -28
  6. data/examples/simple.rb +3 -3
  7. data/lib/active_record.rb +20 -20
  8. data/lib/active_record/aggregations.rb +244 -244
  9. data/lib/active_record/association_relation.rb +5 -5
  10. data/lib/active_record/associations.rb +1579 -1569
  11. data/lib/active_record/associations/alias_tracker.rb +1 -1
  12. data/lib/active_record/associations/association.rb +23 -15
  13. data/lib/active_record/associations/association_scope.rb +83 -81
  14. data/lib/active_record/associations/belongs_to_association.rb +0 -1
  15. data/lib/active_record/associations/builder/belongs_to.rb +16 -14
  16. data/lib/active_record/associations/builder/collection_association.rb +1 -2
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +27 -27
  18. data/lib/active_record/associations/collection_association.rb +74 -241
  19. data/lib/active_record/associations/collection_proxy.rb +144 -70
  20. data/lib/active_record/associations/has_many_association.rb +15 -19
  21. data/lib/active_record/associations/has_many_through_association.rb +12 -5
  22. data/lib/active_record/associations/has_one_association.rb +22 -28
  23. data/lib/active_record/associations/has_one_through_association.rb +5 -1
  24. data/lib/active_record/associations/join_dependency.rb +117 -115
  25. data/lib/active_record/associations/join_dependency/join_association.rb +16 -13
  26. data/lib/active_record/associations/join_dependency/join_base.rb +1 -1
  27. data/lib/active_record/associations/join_dependency/join_part.rb +1 -1
  28. data/lib/active_record/associations/preloader.rb +94 -94
  29. data/lib/active_record/associations/preloader/association.rb +87 -64
  30. data/lib/active_record/associations/preloader/belongs_to.rb +0 -2
  31. data/lib/active_record/associations/preloader/collection_association.rb +6 -6
  32. data/lib/active_record/associations/preloader/has_many.rb +0 -2
  33. data/lib/active_record/associations/preloader/singular_association.rb +6 -8
  34. data/lib/active_record/associations/preloader/through_association.rb +34 -41
  35. data/lib/active_record/associations/singular_association.rb +8 -25
  36. data/lib/active_record/associations/through_association.rb +3 -6
  37. data/lib/active_record/attribute.rb +98 -71
  38. data/lib/active_record/attribute/user_provided_default.rb +4 -2
  39. data/lib/active_record/attribute_assignment.rb +61 -61
  40. data/lib/active_record/attribute_decorators.rb +35 -13
  41. data/lib/active_record/attribute_methods.rb +56 -65
  42. data/lib/active_record/attribute_methods/before_type_cast.rb +7 -7
  43. data/lib/active_record/attribute_methods/dirty.rb +216 -34
  44. data/lib/active_record/attribute_methods/primary_key.rb +78 -73
  45. data/lib/active_record/attribute_methods/read.rb +39 -35
  46. data/lib/active_record/attribute_methods/serialization.rb +7 -7
  47. data/lib/active_record/attribute_methods/time_zone_conversion.rb +35 -58
  48. data/lib/active_record/attribute_methods/write.rb +36 -30
  49. data/lib/active_record/attribute_mutation_tracker.rb +53 -10
  50. data/lib/active_record/attribute_set.rb +9 -6
  51. data/lib/active_record/attribute_set/builder.rb +41 -49
  52. data/lib/active_record/attribute_set/yaml_encoder.rb +41 -0
  53. data/lib/active_record/attributes.rb +21 -21
  54. data/lib/active_record/autosave_association.rb +13 -13
  55. data/lib/active_record/base.rb +24 -22
  56. data/lib/active_record/callbacks.rb +52 -14
  57. data/lib/active_record/coders/yaml_column.rb +9 -11
  58. data/lib/active_record/collection_cache_key.rb +6 -17
  59. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +320 -278
  60. data/lib/active_record/connection_adapters/abstract/database_limits.rb +1 -3
  61. data/lib/active_record/connection_adapters/abstract/database_statements.rb +22 -34
  62. data/lib/active_record/connection_adapters/abstract/query_cache.rb +31 -27
  63. data/lib/active_record/connection_adapters/abstract/quoting.rb +44 -57
  64. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +9 -19
  65. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +78 -79
  66. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +53 -41
  67. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +99 -93
  68. data/lib/active_record/connection_adapters/abstract/transaction.rb +1 -5
  69. data/lib/active_record/connection_adapters/abstract_adapter.rb +156 -128
  70. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +424 -382
  71. data/lib/active_record/connection_adapters/column.rb +27 -5
  72. data/lib/active_record/connection_adapters/connection_specification.rb +128 -118
  73. data/lib/active_record/connection_adapters/mysql/column.rb +6 -31
  74. data/lib/active_record/connection_adapters/mysql/database_statements.rb +45 -43
  75. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +22 -22
  76. data/lib/active_record/connection_adapters/mysql/quoting.rb +6 -12
  77. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +49 -45
  78. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +16 -19
  79. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +49 -31
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +5 -6
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +24 -26
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +1 -28
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +46 -35
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +3 -3
  85. data/lib/active_record/connection_adapters/postgresql/oid.rb +22 -21
  86. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +9 -9
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +5 -3
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +1 -1
  90. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -2
  91. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +3 -3
  92. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +16 -16
  93. data/lib/active_record/connection_adapters/postgresql/oid/{rails_5_1_point.rb → legacy_point.rb} +9 -16
  94. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
  95. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +13 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +28 -8
  97. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +28 -30
  98. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -1
  99. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +51 -51
  100. data/lib/active_record/connection_adapters/postgresql/quoting.rb +38 -36
  101. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +15 -0
  102. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +37 -24
  103. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +19 -23
  104. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +161 -170
  105. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +4 -4
  106. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -7
  107. data/lib/active_record/connection_adapters/postgresql_adapter.rb +179 -152
  108. data/lib/active_record/connection_adapters/schema_cache.rb +16 -7
  109. data/lib/active_record/connection_adapters/sql_type_metadata.rb +3 -3
  110. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +1 -1
  111. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +16 -20
  112. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +1 -8
  113. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +28 -0
  114. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +17 -0
  115. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +187 -130
  116. data/lib/active_record/connection_adapters/statement_pool.rb +7 -7
  117. data/lib/active_record/connection_handling.rb +14 -26
  118. data/lib/active_record/core.rb +110 -93
  119. data/lib/active_record/counter_cache.rb +62 -13
  120. data/lib/active_record/define_callbacks.rb +20 -0
  121. data/lib/active_record/dynamic_matchers.rb +80 -79
  122. data/lib/active_record/enum.rb +8 -6
  123. data/lib/active_record/errors.rb +58 -15
  124. data/lib/active_record/explain.rb +1 -2
  125. data/lib/active_record/explain_registry.rb +1 -1
  126. data/lib/active_record/explain_subscriber.rb +7 -4
  127. data/lib/active_record/fixture_set/file.rb +11 -8
  128. data/lib/active_record/fixtures.rb +66 -53
  129. data/lib/active_record/gem_version.rb +3 -3
  130. data/lib/active_record/inheritance.rb +93 -79
  131. data/lib/active_record/integration.rb +7 -7
  132. data/lib/active_record/internal_metadata.rb +3 -16
  133. data/lib/active_record/legacy_yaml_adapter.rb +1 -1
  134. data/lib/active_record/locking/optimistic.rb +64 -56
  135. data/lib/active_record/locking/pessimistic.rb +10 -1
  136. data/lib/active_record/log_subscriber.rb +29 -29
  137. data/lib/active_record/migration.rb +155 -172
  138. data/lib/active_record/migration/command_recorder.rb +94 -94
  139. data/lib/active_record/migration/compatibility.rb +76 -37
  140. data/lib/active_record/migration/join_table.rb +6 -6
  141. data/lib/active_record/model_schema.rb +85 -119
  142. data/lib/active_record/nested_attributes.rb +200 -199
  143. data/lib/active_record/null_relation.rb +10 -33
  144. data/lib/active_record/persistence.rb +45 -38
  145. data/lib/active_record/query_cache.rb +4 -8
  146. data/lib/active_record/querying.rb +2 -3
  147. data/lib/active_record/railtie.rb +16 -17
  148. data/lib/active_record/railties/controller_runtime.rb +6 -2
  149. data/lib/active_record/railties/databases.rake +125 -140
  150. data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
  151. data/lib/active_record/readonly_attributes.rb +2 -2
  152. data/lib/active_record/reflection.rb +79 -96
  153. data/lib/active_record/relation.rb +72 -115
  154. data/lib/active_record/relation/batches.rb +87 -58
  155. data/lib/active_record/relation/batches/batch_enumerator.rb +1 -1
  156. data/lib/active_record/relation/calculations.rb +154 -160
  157. data/lib/active_record/relation/delegation.rb +30 -29
  158. data/lib/active_record/relation/finder_methods.rb +195 -226
  159. data/lib/active_record/relation/merger.rb +58 -62
  160. data/lib/active_record/relation/predicate_builder.rb +92 -89
  161. data/lib/active_record/relation/predicate_builder/array_handler.rb +7 -5
  162. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +23 -23
  163. data/lib/active_record/relation/predicate_builder/base_handler.rb +3 -1
  164. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +0 -8
  165. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +12 -10
  166. data/lib/active_record/relation/predicate_builder/range_handler.rb +0 -8
  167. data/lib/active_record/relation/query_attribute.rb +1 -1
  168. data/lib/active_record/relation/query_methods.rb +247 -295
  169. data/lib/active_record/relation/record_fetch_warning.rb +3 -3
  170. data/lib/active_record/relation/spawn_methods.rb +4 -5
  171. data/lib/active_record/relation/where_clause.rb +79 -65
  172. data/lib/active_record/relation/where_clause_factory.rb +47 -8
  173. data/lib/active_record/result.rb +29 -31
  174. data/lib/active_record/runtime_registry.rb +3 -3
  175. data/lib/active_record/sanitization.rb +182 -197
  176. data/lib/active_record/schema.rb +3 -3
  177. data/lib/active_record/schema_dumper.rb +14 -37
  178. data/lib/active_record/schema_migration.rb +3 -3
  179. data/lib/active_record/scoping.rb +9 -10
  180. data/lib/active_record/scoping/default.rb +87 -91
  181. data/lib/active_record/scoping/named.rb +16 -28
  182. data/lib/active_record/secure_token.rb +2 -2
  183. data/lib/active_record/statement_cache.rb +13 -15
  184. data/lib/active_record/store.rb +31 -32
  185. data/lib/active_record/suppressor.rb +2 -1
  186. data/lib/active_record/table_metadata.rb +9 -5
  187. data/lib/active_record/tasks/database_tasks.rb +72 -65
  188. data/lib/active_record/tasks/mysql_database_tasks.rb +75 -72
  189. data/lib/active_record/tasks/postgresql_database_tasks.rb +53 -48
  190. data/lib/active_record/tasks/sqlite_database_tasks.rb +18 -16
  191. data/lib/active_record/timestamp.rb +39 -25
  192. data/lib/active_record/touch_later.rb +1 -2
  193. data/lib/active_record/transactions.rb +98 -110
  194. data/lib/active_record/type.rb +17 -13
  195. data/lib/active_record/type/adapter_specific_registry.rb +46 -42
  196. data/lib/active_record/type/decimal_without_scale.rb +9 -0
  197. data/lib/active_record/type/hash_lookup_type_map.rb +3 -3
  198. data/lib/active_record/type/serialized.rb +8 -8
  199. data/lib/active_record/type/text.rb +9 -0
  200. data/lib/active_record/type/time.rb +0 -1
  201. data/lib/active_record/type/type_map.rb +11 -15
  202. data/lib/active_record/type/unsigned_integer.rb +15 -0
  203. data/lib/active_record/type_caster.rb +2 -2
  204. data/lib/active_record/type_caster/connection.rb +8 -6
  205. data/lib/active_record/type_caster/map.rb +3 -1
  206. data/lib/active_record/validations.rb +4 -4
  207. data/lib/active_record/validations/associated.rb +1 -1
  208. data/lib/active_record/validations/presence.rb +2 -2
  209. data/lib/active_record/validations/uniqueness.rb +8 -39
  210. data/lib/active_record/version.rb +1 -1
  211. data/lib/rails/generators/active_record.rb +4 -4
  212. data/lib/rails/generators/active_record/migration.rb +2 -2
  213. data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -34
  214. data/lib/rails/generators/active_record/model/model_generator.rb +9 -9
  215. metadata +22 -13
  216. 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
- if changed?(attr_name)
18
- result[attr_name] = [attributes[attr_name].original_value, attributes.fetch_value(attr_name)]
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 changed?(attr_name)
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
- attributes[attr_name].changed?
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
- attr_reader :attributes
72
+ attr_reader :attributes, :forced_changes, :deprecated_forced_changes
40
73
 
41
74
  private
42
75
 
43
- def attr_names
44
- attributes.keys
45
- end
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 'active_record/attribute_set/builder'
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 :fetch, :except, to: :attributes
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
- attr_reader :attributes
105
+ attr_reader :attributes
103
106
 
104
107
  private
105
108
 
106
- def initialized_attributes
107
- attributes.select { |_, attr| attr.initialized? }
108
- end
109
+ def initialized_attributes
110
+ attributes.select { |_, attr| attr.initialized? }
111
+ end
109
112
  end
110
113
  end
@@ -1,32 +1,37 @@
1
- require 'active_record/attribute'
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, :default_attributes
6
+ attr_reader :types, :always_initialized, :default
7
7
 
8
- def initialize(types, default_attributes = {})
8
+ def initialize(types, always_initialized = nil, &default)
9
9
  @types = types
10
- @default_attributes = default_attributes
10
+ @always_initialized = always_initialized
11
+ @default = default
11
12
  end
12
13
 
13
14
  def build_from_database(values = {}, additional_types = {})
14
- attributes = LazyAttributeHash.new(types, values, additional_types, default_attributes)
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, :fetch, :except, to: :materialize
26
+ delegate :transform_values, :each_key, :each_value, :fetch, to: :materialize
22
27
 
23
- def initialize(types, values, additional_types, default_attributes, delegate_hash = {})
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 = delegate_hash
29
- @default_attributes = default_attributes
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
- [@types, @values, @additional_types, @default_attributes, @delegate_hash]
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 encode_with(coder)
91
- coder["delegate_hash"] = materialize
92
- end
93
-
94
- def init_with(coder)
95
- marshal_load(coder["delegate_hash"])
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
- attr_reader :types, :values, :additional_types, :delegate_hash, :default_attributes
97
+ attr_reader :types, :values, :additional_types, :delegate_hash, :default
101
98
 
102
- def materialize
103
- unless @materialized
104
- values.each_key { |key| self[key] }
105
- types.each_key { |key| self[key] }
106
- unless frozen?
107
- @materialized = true
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
- def assign_default_value(name)
116
- type = additional_types.fetch(name, types[name])
117
- value_present = true
118
- value = values.fetch(name) { value_present = false }
119
-
120
- if value_present
121
- delegate_hash[name] = Attribute.from_database(name, value, type)
122
- elsif types.key?(name)
123
- attr = default_attributes[name]
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 'active_record/attribute/user_provided_default'
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 ActiveRecord::Type::Value for the
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
- # ActiveRecord::Type::Value. For more details on registering your types
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 ActiveRecord::Type::Value for more details.
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
- NO_DEFAULT_PROVIDED = Object.new # :nodoc:
246
- private_constant :NO_DEFAULT_PROVIDED
245
+ NO_DEFAULT_PROVIDED = Object.new # :nodoc:
246
+ private_constant :NO_DEFAULT_PROVIDED
247
247
 
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)
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? || changed? || marked_for_destruction? || nested_records_changed_for_autosave?
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
- validation_context = self.validation_context unless [:create, :update].include?(self.validation_context)
331
+ context = validation_context unless [:create, :update].include?(validation_context)
332
332
 
333
- unless valid = record.valid?(validation_context)
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(:validate => false)
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(:validate => !autosave)
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.attribute_changed?(reflection.foreign_key)
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(:validate => !autosave) if record.new_record? || (autosave && record.changed_for_autosave?)
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)