activerecord 4.2.11 → 5.2.4.1
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 +580 -1626
- data/MIT-LICENSE +2 -2
- data/README.rdoc +10 -11
- data/examples/performance.rb +32 -31
- data/examples/simple.rb +5 -4
- data/lib/active_record/aggregations.rb +263 -249
- data/lib/active_record/association_relation.rb +11 -6
- data/lib/active_record/associations/alias_tracker.rb +29 -35
- data/lib/active_record/associations/association.rb +77 -43
- data/lib/active_record/associations/association_scope.rb +106 -133
- data/lib/active_record/associations/belongs_to_association.rb +52 -41
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -8
- data/lib/active_record/associations/builder/association.rb +29 -38
- data/lib/active_record/associations/builder/belongs_to.rb +77 -30
- data/lib/active_record/associations/builder/collection_association.rb +9 -22
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +42 -35
- data/lib/active_record/associations/builder/has_many.rb +6 -4
- data/lib/active_record/associations/builder/has_one.rb +13 -6
- data/lib/active_record/associations/builder/singular_association.rb +15 -11
- data/lib/active_record/associations/collection_association.rb +139 -280
- data/lib/active_record/associations/collection_proxy.rb +231 -133
- data/lib/active_record/associations/foreign_association.rb +3 -1
- data/lib/active_record/associations/has_many_association.rb +34 -89
- data/lib/active_record/associations/has_many_through_association.rb +49 -76
- data/lib/active_record/associations/has_one_association.rb +38 -24
- data/lib/active_record/associations/has_one_through_association.rb +18 -9
- data/lib/active_record/associations/join_dependency/join_association.rb +40 -87
- data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
- data/lib/active_record/associations/join_dependency/join_part.rb +12 -12
- data/lib/active_record/associations/join_dependency.rb +133 -159
- data/lib/active_record/associations/preloader/association.rb +85 -120
- data/lib/active_record/associations/preloader/through_association.rb +85 -74
- data/lib/active_record/associations/preloader.rb +81 -91
- data/lib/active_record/associations/singular_association.rb +27 -34
- data/lib/active_record/associations/through_association.rb +38 -18
- data/lib/active_record/associations.rb +1732 -1597
- data/lib/active_record/attribute_assignment.rb +58 -182
- data/lib/active_record/attribute_decorators.rb +39 -15
- data/lib/active_record/attribute_methods/before_type_cast.rb +10 -8
- data/lib/active_record/attribute_methods/dirty.rb +94 -135
- data/lib/active_record/attribute_methods/primary_key.rb +86 -71
- data/lib/active_record/attribute_methods/query.rb +4 -2
- data/lib/active_record/attribute_methods/read.rb +45 -63
- data/lib/active_record/attribute_methods/serialization.rb +40 -20
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +58 -36
- data/lib/active_record/attribute_methods/write.rb +30 -45
- data/lib/active_record/attribute_methods.rb +166 -109
- data/lib/active_record/attributes.rb +201 -82
- data/lib/active_record/autosave_association.rb +94 -36
- data/lib/active_record/base.rb +57 -44
- data/lib/active_record/callbacks.rb +97 -57
- data/lib/active_record/coders/json.rb +3 -1
- data/lib/active_record/coders/yaml_column.rb +24 -12
- data/lib/active_record/collection_cache_key.rb +53 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +712 -290
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +10 -5
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +237 -90
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +71 -21
- data/lib/active_record/connection_adapters/abstract/quoting.rb +118 -52
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +5 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +67 -46
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +318 -217
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +81 -36
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +570 -228
- data/lib/active_record/connection_adapters/abstract/transaction.rb +138 -70
- data/lib/active_record/connection_adapters/abstract_adapter.rb +325 -202
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +542 -601
- data/lib/active_record/connection_adapters/column.rb +50 -41
- data/lib/active_record/connection_adapters/connection_specification.rb +147 -135
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +33 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +140 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +73 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +87 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +80 -0
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +148 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +35 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +41 -180
- data/lib/active_record/connection_adapters/postgresql/column.rb +35 -11
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +45 -114
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +50 -58
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +10 -6
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +4 -2
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +5 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +9 -22
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -19
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +5 -7
- data/lib/active_record/connection_adapters/postgresql/oid/{integer.rb → oid.rb} +6 -2
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +33 -11
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -34
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -5
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +55 -53
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid.rb +23 -25
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +107 -47
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +65 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +144 -90
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +462 -284
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +39 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +12 -8
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +432 -323
- data/lib/active_record/connection_adapters/schema_cache.rb +48 -24
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +34 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +67 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +106 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +269 -308
- data/lib/active_record/connection_adapters/statement_pool.rb +34 -13
- data/lib/active_record/connection_handling.rb +40 -27
- data/lib/active_record/core.rb +178 -198
- data/lib/active_record/counter_cache.rb +79 -36
- data/lib/active_record/define_callbacks.rb +22 -0
- data/lib/active_record/dynamic_matchers.rb +87 -105
- data/lib/active_record/enum.rb +135 -88
- data/lib/active_record/errors.rb +179 -52
- data/lib/active_record/explain.rb +23 -11
- data/lib/active_record/explain_registry.rb +4 -2
- data/lib/active_record/explain_subscriber.rb +10 -5
- data/lib/active_record/fixture_set/file.rb +35 -9
- data/lib/active_record/fixtures.rb +188 -132
- data/lib/active_record/gem_version.rb +5 -3
- data/lib/active_record/inheritance.rb +148 -112
- data/lib/active_record/integration.rb +70 -28
- data/lib/active_record/internal_metadata.rb +45 -0
- data/lib/active_record/legacy_yaml_adapter.rb +21 -3
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +88 -96
- data/lib/active_record/locking/pessimistic.rb +15 -3
- data/lib/active_record/log_subscriber.rb +95 -33
- data/lib/active_record/migration/command_recorder.rb +133 -90
- data/lib/active_record/migration/compatibility.rb +217 -0
- data/lib/active_record/migration/join_table.rb +8 -6
- data/lib/active_record/migration.rb +581 -282
- data/lib/active_record/model_schema.rb +290 -111
- data/lib/active_record/nested_attributes.rb +264 -222
- data/lib/active_record/no_touching.rb +7 -1
- data/lib/active_record/null_relation.rb +24 -37
- data/lib/active_record/persistence.rb +347 -119
- data/lib/active_record/query_cache.rb +13 -24
- data/lib/active_record/querying.rb +19 -17
- data/lib/active_record/railtie.rb +94 -32
- data/lib/active_record/railties/console_sandbox.rb +2 -0
- data/lib/active_record/railties/controller_runtime.rb +9 -3
- data/lib/active_record/railties/databases.rake +149 -156
- data/lib/active_record/readonly_attributes.rb +5 -4
- data/lib/active_record/reflection.rb +414 -267
- data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
- data/lib/active_record/relation/batches.rb +204 -55
- data/lib/active_record/relation/calculations.rb +256 -248
- data/lib/active_record/relation/delegation.rb +67 -60
- data/lib/active_record/relation/finder_methods.rb +288 -239
- data/lib/active_record/relation/from_clause.rb +26 -0
- data/lib/active_record/relation/merger.rb +86 -86
- data/lib/active_record/relation/predicate_builder/array_handler.rb +24 -24
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +19 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +20 -0
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +56 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +42 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
- data/lib/active_record/relation/predicate_builder.rb +116 -119
- data/lib/active_record/relation/query_attribute.rb +45 -0
- data/lib/active_record/relation/query_methods.rb +448 -393
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +11 -13
- data/lib/active_record/relation/where_clause.rb +186 -0
- data/lib/active_record/relation/where_clause_factory.rb +34 -0
- data/lib/active_record/relation.rb +287 -340
- data/lib/active_record/result.rb +54 -36
- data/lib/active_record/runtime_registry.rb +6 -4
- data/lib/active_record/sanitization.rb +155 -124
- data/lib/active_record/schema.rb +30 -24
- data/lib/active_record/schema_dumper.rb +91 -87
- data/lib/active_record/schema_migration.rb +19 -16
- data/lib/active_record/scoping/default.rb +102 -85
- data/lib/active_record/scoping/named.rb +81 -32
- data/lib/active_record/scoping.rb +45 -26
- data/lib/active_record/secure_token.rb +40 -0
- data/lib/active_record/serialization.rb +5 -5
- data/lib/active_record/statement_cache.rb +45 -35
- data/lib/active_record/store.rb +42 -36
- data/lib/active_record/suppressor.rb +61 -0
- data/lib/active_record/table_metadata.rb +82 -0
- data/lib/active_record/tasks/database_tasks.rb +134 -96
- data/lib/active_record/tasks/mysql_database_tasks.rb +56 -100
- data/lib/active_record/tasks/postgresql_database_tasks.rb +83 -41
- data/lib/active_record/tasks/sqlite_database_tasks.rb +44 -16
- data/lib/active_record/timestamp.rb +70 -38
- data/lib/active_record/touch_later.rb +64 -0
- data/lib/active_record/transactions.rb +199 -124
- data/lib/active_record/translation.rb +2 -0
- data/lib/active_record/type/adapter_specific_registry.rb +136 -0
- data/lib/active_record/type/date.rb +4 -45
- data/lib/active_record/type/date_time.rb +4 -49
- data/lib/active_record/type/decimal_without_scale.rb +6 -2
- data/lib/active_record/type/hash_lookup_type_map.rb +5 -3
- data/lib/active_record/type/internal/timezone.rb +17 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +24 -15
- data/lib/active_record/type/text.rb +2 -2
- data/lib/active_record/type/time.rb +11 -16
- data/lib/active_record/type/type_map.rb +15 -17
- data/lib/active_record/type/unsigned_integer.rb +9 -7
- data/lib/active_record/type.rb +79 -23
- data/lib/active_record/type_caster/connection.rb +33 -0
- data/lib/active_record/type_caster/map.rb +23 -0
- data/lib/active_record/type_caster.rb +9 -0
- data/lib/active_record/validations/absence.rb +25 -0
- data/lib/active_record/validations/associated.rb +13 -4
- data/lib/active_record/validations/length.rb +26 -0
- data/lib/active_record/validations/presence.rb +14 -13
- data/lib/active_record/validations/uniqueness.rb +40 -41
- data/lib/active_record/validations.rb +38 -35
- data/lib/active_record/version.rb +3 -1
- data/lib/active_record.rb +34 -22
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +43 -35
- data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +8 -3
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +8 -1
- data/lib/rails/generators/active_record/migration.rb +18 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +18 -22
- data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +3 -0
- data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
- data/lib/rails/generators/active_record.rb +7 -5
- metadata +72 -50
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
- data/lib/active_record/associations/preloader/collection_association.rb +0 -24
- data/lib/active_record/associations/preloader/has_many.rb +0 -17
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
- data/lib/active_record/associations/preloader/has_one.rb +0 -23
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -21
- data/lib/active_record/attribute.rb +0 -163
- data/lib/active_record/attribute_set/builder.rb +0 -106
- data/lib/active_record/attribute_set.rb +0 -81
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
- data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
- data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/serializers/xml_serializer.rb +0 -193
- data/lib/active_record/type/big_integer.rb +0 -13
- data/lib/active_record/type/binary.rb +0 -50
- data/lib/active_record/type/boolean.rb +0 -31
- data/lib/active_record/type/decimal.rb +0 -64
- data/lib/active_record/type/decorator.rb +0 -14
- data/lib/active_record/type/float.rb +0 -19
- data/lib/active_record/type/integer.rb +0 -59
- data/lib/active_record/type/mutable.rb +0 -16
- data/lib/active_record/type/numeric.rb +0 -36
- data/lib/active_record/type/string.rb +0 -40
- data/lib/active_record/type/time_value.rb +0 -38
- data/lib/active_record/type/value.rb +0 -110
@@ -0,0 +1,136 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_model/type/registry"
|
4
|
+
|
5
|
+
module ActiveRecord
|
6
|
+
# :stopdoc:
|
7
|
+
module Type
|
8
|
+
class AdapterSpecificRegistry < ActiveModel::Type::Registry
|
9
|
+
def add_modifier(options, klass, **args)
|
10
|
+
registrations << DecorationRegistration.new(options, klass, **args)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def registration_klass
|
16
|
+
Registration
|
17
|
+
end
|
18
|
+
|
19
|
+
def find_registration(symbol, *args)
|
20
|
+
registrations
|
21
|
+
.select { |registration| registration.matches?(symbol, *args) }
|
22
|
+
.max
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class Registration
|
27
|
+
def initialize(name, block, adapter: nil, override: nil)
|
28
|
+
@name = name
|
29
|
+
@block = block
|
30
|
+
@adapter = adapter
|
31
|
+
@override = override
|
32
|
+
end
|
33
|
+
|
34
|
+
def call(_registry, *args, adapter: nil, **kwargs)
|
35
|
+
if kwargs.any? # https://bugs.ruby-lang.org/issues/10856
|
36
|
+
block.call(*args, **kwargs)
|
37
|
+
else
|
38
|
+
block.call(*args)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def matches?(type_name, *args, **kwargs)
|
43
|
+
type_name == name && matches_adapter?(**kwargs)
|
44
|
+
end
|
45
|
+
|
46
|
+
def <=>(other)
|
47
|
+
if conflicts_with?(other)
|
48
|
+
raise TypeConflictError.new("Type #{name} was registered for all
|
49
|
+
adapters, but shadows a native type with
|
50
|
+
the same name for #{other.adapter}".squish)
|
51
|
+
end
|
52
|
+
priority <=> other.priority
|
53
|
+
end
|
54
|
+
|
55
|
+
# TODO Change this to private once we've dropped Ruby 2.2 support.
|
56
|
+
# Workaround for Ruby 2.2 "private attribute?" warning.
|
57
|
+
protected
|
58
|
+
|
59
|
+
attr_reader :name, :block, :adapter, :override
|
60
|
+
|
61
|
+
def priority
|
62
|
+
result = 0
|
63
|
+
if adapter
|
64
|
+
result |= 1
|
65
|
+
end
|
66
|
+
if override
|
67
|
+
result |= 2
|
68
|
+
end
|
69
|
+
result
|
70
|
+
end
|
71
|
+
|
72
|
+
def priority_except_adapter
|
73
|
+
priority & 0b111111100
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def matches_adapter?(adapter: nil, **)
|
79
|
+
(self.adapter.nil? || adapter == self.adapter)
|
80
|
+
end
|
81
|
+
|
82
|
+
def conflicts_with?(other)
|
83
|
+
same_priority_except_adapter?(other) &&
|
84
|
+
has_adapter_conflict?(other)
|
85
|
+
end
|
86
|
+
|
87
|
+
def same_priority_except_adapter?(other)
|
88
|
+
priority_except_adapter == other.priority_except_adapter
|
89
|
+
end
|
90
|
+
|
91
|
+
def has_adapter_conflict?(other)
|
92
|
+
(override.nil? && other.adapter) ||
|
93
|
+
(adapter && other.override.nil?)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
class DecorationRegistration < Registration
|
98
|
+
def initialize(options, klass, adapter: nil)
|
99
|
+
@options = options
|
100
|
+
@klass = klass
|
101
|
+
@adapter = adapter
|
102
|
+
end
|
103
|
+
|
104
|
+
def call(registry, *args, **kwargs)
|
105
|
+
subtype = registry.lookup(*args, **kwargs.except(*options.keys))
|
106
|
+
klass.new(subtype)
|
107
|
+
end
|
108
|
+
|
109
|
+
def matches?(*args, **kwargs)
|
110
|
+
matches_adapter?(**kwargs) && matches_options?(**kwargs)
|
111
|
+
end
|
112
|
+
|
113
|
+
def priority
|
114
|
+
super | 4
|
115
|
+
end
|
116
|
+
|
117
|
+
# TODO Change this to private once we've dropped Ruby 2.2 support.
|
118
|
+
# Workaround for Ruby 2.2 "private attribute?" warning.
|
119
|
+
protected
|
120
|
+
|
121
|
+
attr_reader :options, :klass
|
122
|
+
|
123
|
+
private
|
124
|
+
|
125
|
+
def matches_options?(**kwargs)
|
126
|
+
options.all? do |key, value|
|
127
|
+
kwargs[key] == value
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
class TypeConflictError < StandardError
|
134
|
+
end
|
135
|
+
# :startdoc:
|
136
|
+
end
|
@@ -1,50 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module Type
|
3
|
-
class Date <
|
4
|
-
|
5
|
-
:date
|
6
|
-
end
|
7
|
-
|
8
|
-
def klass
|
9
|
-
::Date
|
10
|
-
end
|
11
|
-
|
12
|
-
def type_cast_for_database(value)
|
13
|
-
type_cast(value)
|
14
|
-
end
|
15
|
-
|
16
|
-
def type_cast_for_schema(value)
|
17
|
-
"'#{value.to_s(:db)}'"
|
18
|
-
end
|
19
|
-
|
20
|
-
private
|
21
|
-
|
22
|
-
def cast_value(value)
|
23
|
-
if value.is_a?(::String)
|
24
|
-
return if value.empty?
|
25
|
-
fast_string_to_date(value) || fallback_string_to_date(value)
|
26
|
-
elsif value.respond_to?(:to_date)
|
27
|
-
value.to_date
|
28
|
-
else
|
29
|
-
value
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def fast_string_to_date(string)
|
34
|
-
if string =~ ConnectionAdapters::Column::Format::ISO_DATE
|
35
|
-
new_date $1.to_i, $2.to_i, $3.to_i
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def fallback_string_to_date(string)
|
40
|
-
new_date(*::Date._parse(string, false).values_at(:year, :mon, :mday))
|
41
|
-
end
|
42
|
-
|
43
|
-
def new_date(year, mon, mday)
|
44
|
-
if year && year != 0
|
45
|
-
::Date.new(year, mon, mday) rescue nil
|
46
|
-
end
|
47
|
-
end
|
5
|
+
class Date < ActiveModel::Type::Date
|
6
|
+
include Internal::Timezone
|
48
7
|
end
|
49
8
|
end
|
50
9
|
end
|
@@ -1,54 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module Type
|
3
|
-
class DateTime <
|
4
|
-
include
|
5
|
-
|
6
|
-
def type
|
7
|
-
:datetime
|
8
|
-
end
|
9
|
-
|
10
|
-
def type_cast_for_database(value)
|
11
|
-
return super unless value.acts_like?(:time)
|
12
|
-
|
13
|
-
zone_conversion_method = ActiveRecord::Base.default_timezone == :utc ? :getutc : :getlocal
|
14
|
-
|
15
|
-
if value.respond_to?(zone_conversion_method)
|
16
|
-
value = value.send(zone_conversion_method)
|
17
|
-
end
|
18
|
-
|
19
|
-
return value unless has_precision?
|
20
|
-
|
21
|
-
result = value.to_s(:db)
|
22
|
-
if value.respond_to?(:usec) && (1..6).cover?(precision)
|
23
|
-
"#{result}.#{sprintf("%0#{precision}d", value.usec / 10 ** (6 - precision))}"
|
24
|
-
else
|
25
|
-
result
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
|
-
|
31
|
-
alias has_precision? precision
|
32
|
-
|
33
|
-
def cast_value(string)
|
34
|
-
return string unless string.is_a?(::String)
|
35
|
-
return if string.empty?
|
36
|
-
|
37
|
-
fast_string_to_time(string) || fallback_string_to_time(string)
|
38
|
-
end
|
39
|
-
|
40
|
-
# '0.123456' -> 123456
|
41
|
-
# '1.123456' -> 123456
|
42
|
-
def microseconds(time)
|
43
|
-
time[:sec_fraction] ? (time[:sec_fraction] * 1_000_000).to_i : 0
|
44
|
-
end
|
45
|
-
|
46
|
-
def fallback_string_to_time(string)
|
47
|
-
time_hash = ::Date._parse(string)
|
48
|
-
time_hash[:sec_fraction] = microseconds(time_hash)
|
49
|
-
|
50
|
-
new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction, :offset))
|
51
|
-
end
|
5
|
+
class DateTime < ActiveModel::Type::DateTime
|
6
|
+
include Internal::Timezone
|
52
7
|
end
|
53
8
|
end
|
54
9
|
end
|
@@ -1,11 +1,15 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
module Type
|
5
|
-
class DecimalWithoutScale < BigInteger # :nodoc:
|
5
|
+
class DecimalWithoutScale < ActiveModel::Type::BigInteger # :nodoc:
|
6
6
|
def type
|
7
7
|
:decimal
|
8
8
|
end
|
9
|
+
|
10
|
+
def type_cast_for_schema(value)
|
11
|
+
value.to_s.inspect
|
12
|
+
end
|
9
13
|
end
|
10
14
|
end
|
11
15
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module Type
|
3
5
|
class HashLookupTypeMap < TypeMap # :nodoc:
|
@@ -15,9 +17,9 @@ module ActiveRecord
|
|
15
17
|
|
16
18
|
private
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
-
|
20
|
+
def perform_fetch(type, *args, &block)
|
21
|
+
@mapping.fetch(type, block).call(type, *args)
|
22
|
+
end
|
21
23
|
end
|
22
24
|
end
|
23
25
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module Type
|
5
|
+
module Internal
|
6
|
+
module Timezone
|
7
|
+
def is_utc?
|
8
|
+
ActiveRecord::Base.default_timezone == :utc
|
9
|
+
end
|
10
|
+
|
11
|
+
def default_timezone
|
12
|
+
ActiveRecord::Base.default_timezone
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module Type
|
5
|
+
class Json < ActiveModel::Type::Value
|
6
|
+
include ActiveModel::Type::Helpers::Mutable
|
7
|
+
|
8
|
+
def type
|
9
|
+
:json
|
10
|
+
end
|
11
|
+
|
12
|
+
def deserialize(value)
|
13
|
+
return value unless value.is_a?(::String)
|
14
|
+
ActiveSupport::JSON.decode(value) rescue nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def serialize(value)
|
18
|
+
ActiveSupport::JSON.encode(value) unless value.nil?
|
19
|
+
end
|
20
|
+
|
21
|
+
def changed_in_place?(raw_old_value, new_value)
|
22
|
+
deserialize(raw_old_value) != new_value
|
23
|
+
end
|
24
|
+
|
25
|
+
def accessor
|
26
|
+
ActiveRecord::Store::StringKeyedHashAccessor
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -1,8 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module Type
|
3
|
-
class Serialized < DelegateClass(Type::Value) # :nodoc:
|
4
|
-
|
5
|
-
|
5
|
+
class Serialized < DelegateClass(ActiveModel::Type::Value) # :nodoc:
|
6
|
+
undef to_yaml if method_defined?(:to_yaml)
|
7
|
+
|
8
|
+
include ActiveModel::Type::Helpers::Mutable
|
6
9
|
|
7
10
|
attr_reader :subtype, :coder
|
8
11
|
|
@@ -12,7 +15,7 @@ module ActiveRecord
|
|
12
15
|
super(subtype)
|
13
16
|
end
|
14
17
|
|
15
|
-
def
|
18
|
+
def deserialize(value)
|
16
19
|
if default_value?(value)
|
17
20
|
value
|
18
21
|
else
|
@@ -20,7 +23,7 @@ module ActiveRecord
|
|
20
23
|
end
|
21
24
|
end
|
22
25
|
|
23
|
-
def
|
26
|
+
def serialize(value)
|
24
27
|
return if value.nil?
|
25
28
|
unless default_value?(value)
|
26
29
|
super coder.dump(value)
|
@@ -33,7 +36,7 @@ module ActiveRecord
|
|
33
36
|
|
34
37
|
def changed_in_place?(raw_old_value, value)
|
35
38
|
return false if value.nil?
|
36
|
-
raw_new_value =
|
39
|
+
raw_new_value = encoded(value)
|
37
40
|
raw_old_value.nil? != raw_new_value.nil? ||
|
38
41
|
subtype.changed_in_place?(raw_old_value, raw_new_value)
|
39
42
|
end
|
@@ -42,21 +45,27 @@ module ActiveRecord
|
|
42
45
|
ActiveRecord::Store::IndifferentHashAccessor
|
43
46
|
end
|
44
47
|
|
45
|
-
def
|
46
|
-
|
47
|
-
|
48
|
+
def assert_valid_value(value)
|
49
|
+
if coder.respond_to?(:assert_valid_value)
|
50
|
+
coder.assert_valid_value(value, action: "serialize")
|
51
|
+
end
|
48
52
|
end
|
49
53
|
|
50
|
-
def
|
51
|
-
coder
|
52
|
-
super
|
54
|
+
def force_equality?(value)
|
55
|
+
coder.respond_to?(:object_class) && value.is_a?(coder.object_class)
|
53
56
|
end
|
54
57
|
|
55
58
|
private
|
56
59
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
+
def default_value?(value)
|
61
|
+
value == coder.load(nil)
|
62
|
+
end
|
63
|
+
|
64
|
+
def encoded(value)
|
65
|
+
unless default_value?(value)
|
66
|
+
coder.dump(value)
|
67
|
+
end
|
68
|
+
end
|
60
69
|
end
|
61
70
|
end
|
62
71
|
end
|
@@ -1,24 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module Type
|
3
|
-
class Time <
|
4
|
-
include
|
5
|
+
class Time < ActiveModel::Type::Time
|
6
|
+
include Internal::Timezone
|
5
7
|
|
6
|
-
|
7
|
-
:time
|
8
|
+
class Value < DelegateClass(::Time) # :nodoc:
|
8
9
|
end
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
dummy_time_value = "2000-01-01 #{value}"
|
17
|
-
|
18
|
-
fast_string_to_time(dummy_time_value) || begin
|
19
|
-
time_hash = ::Date._parse(dummy_time_value)
|
20
|
-
return if time_hash[:hour].nil?
|
21
|
-
new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction))
|
11
|
+
def serialize(value)
|
12
|
+
case value = super
|
13
|
+
when ::Time
|
14
|
+
Value.new(value)
|
15
|
+
else
|
16
|
+
value
|
22
17
|
end
|
23
18
|
end
|
24
19
|
end
|
@@ -1,17 +1,19 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "concurrent/map"
|
2
4
|
|
3
5
|
module ActiveRecord
|
4
6
|
module Type
|
5
7
|
class TypeMap # :nodoc:
|
6
8
|
def initialize
|
7
9
|
@mapping = {}
|
8
|
-
@cache =
|
9
|
-
h.fetch_or_store(key,
|
10
|
+
@cache = Concurrent::Map.new do |h, key|
|
11
|
+
h.fetch_or_store(key, Concurrent::Map.new)
|
10
12
|
end
|
11
13
|
end
|
12
14
|
|
13
15
|
def lookup(lookup_key, *args)
|
14
|
-
fetch(lookup_key, *args) { default_value }
|
16
|
+
fetch(lookup_key, *args) { Type.default_value }
|
15
17
|
end
|
16
18
|
|
17
19
|
def fetch(lookup_key, *args, &block)
|
@@ -44,21 +46,17 @@ module ActiveRecord
|
|
44
46
|
|
45
47
|
private
|
46
48
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
49
|
+
def perform_fetch(lookup_key, *args)
|
50
|
+
matching_pair = @mapping.reverse_each.detect do |key, _|
|
51
|
+
key === lookup_key
|
52
|
+
end
|
51
53
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
54
|
+
if matching_pair
|
55
|
+
matching_pair.last.call(lookup_key, *args)
|
56
|
+
else
|
57
|
+
yield lookup_key, *args
|
58
|
+
end
|
56
59
|
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def default_value
|
60
|
-
@default_value ||= Value.new
|
61
|
-
end
|
62
60
|
end
|
63
61
|
end
|
64
62
|
end
|
@@ -1,15 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module Type
|
3
|
-
class UnsignedInteger < Integer # :nodoc:
|
5
|
+
class UnsignedInteger < ActiveModel::Type::Integer # :nodoc:
|
4
6
|
private
|
5
7
|
|
6
|
-
|
7
|
-
|
8
|
-
|
8
|
+
def max_value
|
9
|
+
super * 2
|
10
|
+
end
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
-
|
12
|
+
def min_value
|
13
|
+
0
|
14
|
+
end
|
13
15
|
end
|
14
16
|
end
|
15
17
|
end
|
data/lib/active_record/type.rb
CHANGED
@@ -1,23 +1,79 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
|
5
|
-
require
|
6
|
-
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
11
|
-
require
|
12
|
-
require
|
13
|
-
require
|
14
|
-
|
15
|
-
require
|
16
|
-
require
|
17
|
-
|
18
|
-
require
|
19
|
-
require
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_model/type"
|
4
|
+
|
5
|
+
require "active_record/type/internal/timezone"
|
6
|
+
|
7
|
+
require "active_record/type/date"
|
8
|
+
require "active_record/type/date_time"
|
9
|
+
require "active_record/type/decimal_without_scale"
|
10
|
+
require "active_record/type/json"
|
11
|
+
require "active_record/type/time"
|
12
|
+
require "active_record/type/text"
|
13
|
+
require "active_record/type/unsigned_integer"
|
14
|
+
|
15
|
+
require "active_record/type/serialized"
|
16
|
+
require "active_record/type/adapter_specific_registry"
|
17
|
+
|
18
|
+
require "active_record/type/type_map"
|
19
|
+
require "active_record/type/hash_lookup_type_map"
|
20
|
+
|
21
|
+
module ActiveRecord
|
22
|
+
module Type
|
23
|
+
@registry = AdapterSpecificRegistry.new
|
24
|
+
|
25
|
+
class << self
|
26
|
+
attr_accessor :registry # :nodoc:
|
27
|
+
delegate :add_modifier, to: :registry
|
28
|
+
|
29
|
+
# Add a new type to the registry, allowing it to be referenced as a
|
30
|
+
# symbol by {ActiveRecord::Base.attribute}[rdoc-ref:Attributes::ClassMethods#attribute].
|
31
|
+
# If your type is only meant to be used with a specific database adapter, you can
|
32
|
+
# do so by passing <tt>adapter: :postgresql</tt>. If your type has the same
|
33
|
+
# name as a native type for the current adapter, an exception will be
|
34
|
+
# raised unless you specify an +:override+ option. <tt>override: true</tt> will
|
35
|
+
# cause your type to be used instead of the native type. <tt>override:
|
36
|
+
# false</tt> will cause the native type to be used over yours if one exists.
|
37
|
+
def register(type_name, klass = nil, **options, &block)
|
38
|
+
registry.register(type_name, klass, **options, &block)
|
39
|
+
end
|
40
|
+
|
41
|
+
def lookup(*args, adapter: current_adapter_name, **kwargs) # :nodoc:
|
42
|
+
registry.lookup(*args, adapter: adapter, **kwargs)
|
43
|
+
end
|
44
|
+
|
45
|
+
def default_value # :nodoc:
|
46
|
+
@default_value ||= Value.new
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def current_adapter_name
|
52
|
+
ActiveRecord::Base.connection.adapter_name.downcase.to_sym
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
Helpers = ActiveModel::Type::Helpers
|
57
|
+
BigInteger = ActiveModel::Type::BigInteger
|
58
|
+
Binary = ActiveModel::Type::Binary
|
59
|
+
Boolean = ActiveModel::Type::Boolean
|
60
|
+
Decimal = ActiveModel::Type::Decimal
|
61
|
+
Float = ActiveModel::Type::Float
|
62
|
+
Integer = ActiveModel::Type::Integer
|
63
|
+
String = ActiveModel::Type::String
|
64
|
+
Value = ActiveModel::Type::Value
|
65
|
+
|
66
|
+
register(:big_integer, Type::BigInteger, override: false)
|
67
|
+
register(:binary, Type::Binary, override: false)
|
68
|
+
register(:boolean, Type::Boolean, override: false)
|
69
|
+
register(:date, Type::Date, override: false)
|
70
|
+
register(:datetime, Type::DateTime, override: false)
|
71
|
+
register(:decimal, Type::Decimal, override: false)
|
72
|
+
register(:float, Type::Float, override: false)
|
73
|
+
register(:integer, Type::Integer, override: false)
|
74
|
+
register(:json, Type::Json, override: false)
|
75
|
+
register(:string, Type::String, override: false)
|
76
|
+
register(:text, Type::Text, override: false)
|
77
|
+
register(:time, Type::Time, override: false)
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module TypeCaster
|
5
|
+
class Connection # :nodoc:
|
6
|
+
def initialize(klass, table_name)
|
7
|
+
@klass = klass
|
8
|
+
@table_name = table_name
|
9
|
+
end
|
10
|
+
|
11
|
+
def type_cast_for_database(attribute_name, value)
|
12
|
+
return value if value.is_a?(Arel::Nodes::BindParam)
|
13
|
+
column = column_for(attribute_name)
|
14
|
+
connection.type_cast_from_column(column, value)
|
15
|
+
end
|
16
|
+
|
17
|
+
# TODO Change this to private once we've dropped Ruby 2.2 support.
|
18
|
+
# Workaround for Ruby 2.2 "private attribute?" warning.
|
19
|
+
protected
|
20
|
+
|
21
|
+
attr_reader :table_name
|
22
|
+
delegate :connection, to: :@klass
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def column_for(attribute_name)
|
27
|
+
if connection.schema_cache.data_source_exists?(table_name)
|
28
|
+
connection.schema_cache.columns_hash(table_name)[attribute_name.to_s]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|