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
@@ -2,7 +2,6 @@ module ActiveRecord
|
|
2
2
|
module Associations
|
3
3
|
class Preloader
|
4
4
|
class HasMany < CollectionAssociation #:nodoc:
|
5
|
-
|
6
5
|
def association_key_name
|
7
6
|
reflection.foreign_key
|
8
7
|
end
|
@@ -10,7 +9,6 @@ module ActiveRecord
|
|
10
9
|
def owner_key_name
|
11
10
|
reflection.active_record_primary_key
|
12
11
|
end
|
13
|
-
|
14
12
|
end
|
15
13
|
end
|
16
14
|
end
|
@@ -2,18 +2,16 @@ module ActiveRecord
|
|
2
2
|
module Associations
|
3
3
|
class Preloader
|
4
4
|
class SingularAssociation < Association #:nodoc:
|
5
|
-
|
6
5
|
private
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
def preload(preloader)
|
8
|
+
associated_records_by_owner(preloader).each do |owner, associated_records|
|
9
|
+
record = associated_records.first
|
11
10
|
|
12
|
-
|
13
|
-
|
11
|
+
association = owner.association(reflection.name)
|
12
|
+
association.target = record
|
13
|
+
end
|
14
14
|
end
|
15
|
-
end
|
16
|
-
|
17
15
|
end
|
18
16
|
end
|
19
17
|
end
|
@@ -24,7 +24,7 @@ module ActiveRecord
|
|
24
24
|
|
25
25
|
reset_association owners, through_reflection.name
|
26
26
|
|
27
|
-
middle_records = through_records.flat_map { |(_,rec)| rec }
|
27
|
+
middle_records = through_records.flat_map { |(_, rec)| rec }
|
28
28
|
|
29
29
|
preloaders = preloader.preload(middle_records,
|
30
30
|
source_reflection.name,
|
@@ -32,13 +32,13 @@ module ActiveRecord
|
|
32
32
|
|
33
33
|
@preloaded_records = preloaders.flat_map(&:preloaded_records)
|
34
34
|
|
35
|
-
middle_to_pl = preloaders.each_with_object({}) do |pl,h|
|
35
|
+
middle_to_pl = preloaders.each_with_object({}) do |pl, h|
|
36
36
|
pl.owners.each { |middle|
|
37
37
|
h[middle] = pl
|
38
38
|
}
|
39
39
|
end
|
40
40
|
|
41
|
-
through_records.each_with_object({}) do |(lhs,center), records_by_owner|
|
41
|
+
through_records.each_with_object({}) do |(lhs, center), records_by_owner|
|
42
42
|
pl_to_middle = center.group_by { |record| middle_to_pl[record] }
|
43
43
|
|
44
44
|
records_by_owner[lhs] = pl_to_middle.flat_map do |pl, middles|
|
@@ -61,54 +61,47 @@ module ActiveRecord
|
|
61
61
|
|
62
62
|
private
|
63
63
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
64
|
+
def id_to_index_map(ids)
|
65
|
+
id_map = {}
|
66
|
+
ids.each_with_index { |id, index| id_map[id] = index }
|
67
|
+
id_map
|
68
|
+
end
|
69
69
|
|
70
|
-
|
71
|
-
|
72
|
-
|
70
|
+
def reset_association(owners, association_name)
|
71
|
+
should_reset = (through_scope != through_reflection.klass.unscoped) ||
|
72
|
+
(reflection.options[:source_type] && through_reflection.collection?)
|
73
73
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
74
|
+
# Don't cache the association - we would only be caching a subset
|
75
|
+
if should_reset
|
76
|
+
owners.each { |owner|
|
77
|
+
owner.association(association_name).reset
|
78
|
+
}
|
79
|
+
end
|
79
80
|
end
|
80
|
-
end
|
81
81
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
scope.where_clause = reflection_scope.where_clause
|
92
|
-
if joins = values[:joins]
|
93
|
-
scope.joins!(source_reflection.name => joins)
|
82
|
+
def through_scope
|
83
|
+
scope = through_reflection.klass.unscoped
|
84
|
+
|
85
|
+
if options[:source_type]
|
86
|
+
scope.where! reflection.foreign_type => options[:source_type]
|
87
|
+
else
|
88
|
+
unless reflection_scope.where_clause.empty?
|
89
|
+
scope.includes_values = Array(reflection_scope.values[:includes] || options[:source])
|
90
|
+
scope.where_clause = reflection_scope.where_clause
|
94
91
|
end
|
95
|
-
|
96
|
-
|
92
|
+
|
93
|
+
scope.references! reflection_scope.values[:references]
|
94
|
+
if scope.eager_loading? && order_values = reflection_scope.values[:order]
|
95
|
+
scope = scope.order(order_values)
|
97
96
|
end
|
98
97
|
end
|
99
98
|
|
100
|
-
scope
|
101
|
-
if scope.eager_loading? && order_values = values[:order]
|
102
|
-
scope = scope.order(order_values)
|
103
|
-
end
|
99
|
+
scope
|
104
100
|
end
|
105
101
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
def target_records_from_association(association)
|
110
|
-
association.loaded? ? association.target : association.reader
|
111
|
-
end
|
102
|
+
def target_records_from_association(association)
|
103
|
+
association.loaded? ? association.target : association.reader
|
104
|
+
end
|
112
105
|
end
|
113
106
|
end
|
114
107
|
end
|
@@ -2,15 +2,8 @@ module ActiveRecord
|
|
2
2
|
module Associations
|
3
3
|
class SingularAssociation < Association #:nodoc:
|
4
4
|
# Implements the reader method, e.g. foo.bar for Foo.has_one :bar
|
5
|
-
def reader
|
6
|
-
if
|
7
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
8
|
-
Passing an argument to force an association to reload is now
|
9
|
-
deprecated and will be removed in Rails 5.1. Please call `reload_#{reflection.name}` instead.
|
10
|
-
MSG
|
11
|
-
|
12
|
-
klass.uncached { reload }
|
13
|
-
elsif !loaded? || stale_target?
|
5
|
+
def reader
|
6
|
+
if !loaded? || stale_target?
|
14
7
|
reload
|
15
8
|
end
|
16
9
|
|
@@ -22,14 +15,6 @@ module ActiveRecord
|
|
22
15
|
replace(record)
|
23
16
|
end
|
24
17
|
|
25
|
-
def create(attributes = {}, &block)
|
26
|
-
_create_record(attributes, &block)
|
27
|
-
end
|
28
|
-
|
29
|
-
def create!(attributes = {}, &block)
|
30
|
-
_create_record(attributes, true, &block)
|
31
|
-
end
|
32
|
-
|
33
18
|
def build(attributes = {})
|
34
19
|
record = build_record(attributes)
|
35
20
|
yield(record) if block_given?
|
@@ -50,8 +35,8 @@ module ActiveRecord
|
|
50
35
|
scope.scope_for_create.stringify_keys.except(klass.primary_key)
|
51
36
|
end
|
52
37
|
|
53
|
-
def
|
54
|
-
return scope.
|
38
|
+
def find_target
|
39
|
+
return scope.take if skip_statement_cache?
|
55
40
|
|
56
41
|
conn = klass.connection
|
57
42
|
sc = reflection.association_scope_cache(conn, owner) do
|
@@ -62,13 +47,11 @@ module ActiveRecord
|
|
62
47
|
end
|
63
48
|
|
64
49
|
binds = AssociationScope.get_bind_values(owner, reflection.chain)
|
65
|
-
sc.execute
|
66
|
-
end
|
67
|
-
|
68
|
-
def find_target
|
69
|
-
if record = get_records.first
|
50
|
+
sc.execute(binds, klass, conn) do |record|
|
70
51
|
set_inverse_instance record
|
71
|
-
end
|
52
|
+
end.first
|
53
|
+
rescue ::RangeError
|
54
|
+
nil
|
72
55
|
end
|
73
56
|
|
74
57
|
def replace(record)
|
@@ -2,10 +2,9 @@ module ActiveRecord
|
|
2
2
|
# = Active Record Through Association
|
3
3
|
module Associations
|
4
4
|
module ThroughAssociation #:nodoc:
|
5
|
+
delegate :source_reflection, :through_reflection, to: :reflection
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
protected
|
7
|
+
private
|
9
8
|
|
10
9
|
# We merge in these scopes for two reasons:
|
11
10
|
#
|
@@ -14,7 +13,7 @@ module ActiveRecord
|
|
14
13
|
def target_scope
|
15
14
|
scope = super
|
16
15
|
reflection.chain.drop(1).each do |reflection|
|
17
|
-
relation = reflection.klass.
|
16
|
+
relation = reflection.klass.all
|
18
17
|
scope.merge!(
|
19
18
|
relation.except(:select, :create_with, :includes, :preload, :joins, :eager_load)
|
20
19
|
)
|
@@ -22,8 +21,6 @@ module ActiveRecord
|
|
22
21
|
scope
|
23
22
|
end
|
24
23
|
|
25
|
-
private
|
26
|
-
|
27
24
|
# Construct attributes for :through pointing to owner and associate. This is used by the
|
28
25
|
# methods which create and delete records on the association.
|
29
26
|
#
|
@@ -77,7 +77,11 @@ module ActiveRecord
|
|
77
77
|
end
|
78
78
|
|
79
79
|
def with_type(type)
|
80
|
-
|
80
|
+
if changed_in_place?
|
81
|
+
with_value_from_user(value).with_type(type)
|
82
|
+
else
|
83
|
+
self.class.new(name, value_before_type_cast, type, original_attribute)
|
84
|
+
end
|
81
85
|
end
|
82
86
|
|
83
87
|
def type_cast(*)
|
@@ -108,106 +112,129 @@ module ActiveRecord
|
|
108
112
|
[self.class, name, value_before_type_cast, type].hash
|
109
113
|
end
|
110
114
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
if defined?(@value) && @value.duplicable?
|
118
|
-
@value = @value.dup
|
119
|
-
end
|
115
|
+
def init_with(coder)
|
116
|
+
@name = coder["name"]
|
117
|
+
@value_before_type_cast = coder["value_before_type_cast"]
|
118
|
+
@type = coder["type"]
|
119
|
+
@original_attribute = coder["original_attribute"]
|
120
|
+
@value = coder["value"] if coder.map.key?("value")
|
120
121
|
end
|
121
122
|
|
122
|
-
def
|
123
|
-
|
123
|
+
def encode_with(coder)
|
124
|
+
coder["name"] = name
|
125
|
+
coder["value_before_type_cast"] = value_before_type_cast if value_before_type_cast
|
126
|
+
coder["type"] = type if type
|
127
|
+
coder["original_attribute"] = original_attribute if original_attribute
|
128
|
+
coder["value"] = value if defined?(@value)
|
124
129
|
end
|
125
130
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
else
|
130
|
-
_original_value_for_database
|
131
|
-
end
|
132
|
-
end
|
131
|
+
# TODO Change this to private once we've dropped Ruby 2.2 support.
|
132
|
+
# Workaround for Ruby 2.2 "private attribute?" warning.
|
133
|
+
protected
|
133
134
|
|
134
|
-
|
135
|
-
|
136
|
-
end
|
135
|
+
attr_reader :original_attribute
|
136
|
+
alias_method :assigned?, :original_attribute
|
137
137
|
|
138
|
-
|
139
|
-
|
140
|
-
|
138
|
+
def original_value_for_database
|
139
|
+
if assigned?
|
140
|
+
original_attribute.original_value_for_database
|
141
|
+
else
|
142
|
+
_original_value_for_database
|
143
|
+
end
|
141
144
|
end
|
142
145
|
|
143
|
-
|
144
|
-
|
146
|
+
private
|
147
|
+
def initialize_dup(other)
|
148
|
+
if defined?(@value) && @value.duplicable?
|
149
|
+
@value = @value.dup
|
150
|
+
end
|
145
151
|
end
|
146
|
-
end
|
147
152
|
|
148
|
-
|
149
|
-
|
150
|
-
type.cast(value)
|
153
|
+
def changed_from_assignment?
|
154
|
+
assigned? && type.changed?(original_value, value, value_before_type_cast)
|
151
155
|
end
|
152
156
|
|
153
|
-
def
|
154
|
-
|
157
|
+
def _original_value_for_database
|
158
|
+
type.serialize(original_value)
|
155
159
|
end
|
156
|
-
end
|
157
160
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
161
|
+
class FromDatabase < Attribute # :nodoc:
|
162
|
+
def type_cast(value)
|
163
|
+
type.deserialize(value)
|
164
|
+
end
|
162
165
|
|
163
|
-
|
164
|
-
|
166
|
+
def _original_value_for_database
|
167
|
+
value_before_type_cast
|
168
|
+
end
|
165
169
|
end
|
166
|
-
end
|
167
170
|
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
171
|
+
class FromUser < Attribute # :nodoc:
|
172
|
+
def type_cast(value)
|
173
|
+
type.cast(value)
|
174
|
+
end
|
172
175
|
|
173
|
-
|
174
|
-
|
176
|
+
def came_from_user?
|
177
|
+
true
|
178
|
+
end
|
175
179
|
end
|
176
180
|
|
177
|
-
|
178
|
-
|
179
|
-
|
181
|
+
class WithCastValue < Attribute # :nodoc:
|
182
|
+
def type_cast(value)
|
183
|
+
value
|
184
|
+
end
|
180
185
|
|
181
|
-
|
182
|
-
|
186
|
+
def changed_in_place?
|
187
|
+
false
|
188
|
+
end
|
183
189
|
end
|
184
|
-
alias_method :with_value_from_user, :with_value_from_database
|
185
|
-
end
|
186
190
|
|
187
|
-
|
188
|
-
|
191
|
+
class Null < Attribute # :nodoc:
|
192
|
+
def initialize(name)
|
193
|
+
super(name, nil, Type.default_value)
|
194
|
+
end
|
189
195
|
|
190
|
-
|
191
|
-
|
192
|
-
|
196
|
+
def type_cast(*)
|
197
|
+
nil
|
198
|
+
end
|
193
199
|
|
194
|
-
|
195
|
-
|
196
|
-
yield name
|
200
|
+
def with_type(type)
|
201
|
+
self.class.with_cast_value(name, nil, type)
|
197
202
|
end
|
198
|
-
end
|
199
203
|
|
200
|
-
|
201
|
-
|
204
|
+
def with_value_from_database(value)
|
205
|
+
raise ActiveModel::MissingAttributeError, "can't write unknown attribute `#{name}`"
|
206
|
+
end
|
207
|
+
alias_method :with_value_from_user, :with_value_from_database
|
202
208
|
end
|
203
209
|
|
204
|
-
|
205
|
-
|
210
|
+
class Uninitialized < Attribute # :nodoc:
|
211
|
+
UNINITIALIZED_ORIGINAL_VALUE = Object.new
|
206
212
|
|
207
|
-
|
208
|
-
|
213
|
+
def initialize(name, type)
|
214
|
+
super(name, nil, type)
|
215
|
+
end
|
216
|
+
|
217
|
+
def value
|
218
|
+
if block_given?
|
219
|
+
yield name
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
def original_value
|
224
|
+
UNINITIALIZED_ORIGINAL_VALUE
|
225
|
+
end
|
226
|
+
|
227
|
+
def value_for_database
|
228
|
+
end
|
229
|
+
|
230
|
+
def initialized?
|
231
|
+
false
|
232
|
+
end
|
233
|
+
|
234
|
+
def with_type(type)
|
235
|
+
self.class.new(name, type)
|
236
|
+
end
|
209
237
|
end
|
210
|
-
|
211
|
-
private_constant :FromDatabase, :FromUser, :Null, :Uninitialized, :WithCastValue
|
238
|
+
private_constant :FromDatabase, :FromUser, :Null, :Uninitialized, :WithCastValue
|
212
239
|
end
|
213
240
|
end
|