diff options
-rw-r--r-- | activemodel/lib/active_model/type.rb | 59 | ||||
-rw-r--r-- | activemodel/lib/active_model/type/big_integer.rb (renamed from activerecord/lib/active_record/type/big_integer.rb) | 4 | ||||
-rw-r--r-- | activemodel/lib/active_model/type/binary.rb (renamed from activerecord/lib/active_record/type/binary.rb) | 2 | ||||
-rw-r--r-- | activemodel/lib/active_model/type/boolean.rb (renamed from activerecord/lib/active_record/type/boolean.rb) | 6 | ||||
-rw-r--r-- | activemodel/lib/active_model/type/date.rb (renamed from activerecord/lib/active_record/type/date.rb) | 5 | ||||
-rw-r--r-- | activemodel/lib/active_model/type/date_time.rb (renamed from activerecord/lib/active_record/type/date_time.rb) | 2 | ||||
-rw-r--r-- | activemodel/lib/active_model/type/decimal.rb (renamed from activerecord/lib/active_record/type/decimal.rb) | 2 | ||||
-rw-r--r-- | activemodel/lib/active_model/type/decimal_without_scale.rb (renamed from activerecord/lib/active_record/type/decimal_without_scale.rb) | 4 | ||||
-rw-r--r-- | activemodel/lib/active_model/type/float.rb (renamed from activerecord/lib/active_record/type/float.rb) | 2 | ||||
-rw-r--r-- | activemodel/lib/active_model/type/hash_lookup_type_map.rb (renamed from activerecord/lib/active_record/type/hash_lookup_type_map.rb) | 2 | ||||
-rw-r--r-- | activemodel/lib/active_model/type/helpers.rb | 4 | ||||
-rw-r--r-- | activemodel/lib/active_model/type/helpers/accepts_multiparameter_time.rb (renamed from activerecord/lib/active_record/type/helpers/accepts_multiparameter_time.rb) | 7 | ||||
-rw-r--r-- | activemodel/lib/active_model/type/helpers/mutable.rb (renamed from activerecord/lib/active_record/type/helpers/mutable.rb) | 2 | ||||
-rw-r--r-- | activemodel/lib/active_model/type/helpers/numeric.rb (renamed from activerecord/lib/active_record/type/helpers/numeric.rb) | 2 | ||||
-rw-r--r-- | activemodel/lib/active_model/type/helpers/time_value.rb (renamed from activerecord/lib/active_record/type/helpers/time_value.rb) | 21 | ||||
-rw-r--r-- | activemodel/lib/active_model/type/integer.rb (renamed from activerecord/lib/active_record/type/integer.rb) | 2 | ||||
-rw-r--r-- | activemodel/lib/active_model/type/registry.rb | 151 | ||||
-rw-r--r-- | activemodel/lib/active_model/type/string.rb (renamed from activerecord/lib/active_record/type/string.rb) | 2 | ||||
-rw-r--r-- | activemodel/lib/active_model/type/text.rb (renamed from activerecord/lib/active_record/type/text.rb) | 4 | ||||
-rw-r--r-- | activemodel/lib/active_model/type/time.rb (renamed from activerecord/lib/active_record/type/time.rb) | 2 | ||||
-rw-r--r-- | activemodel/lib/active_model/type/type_map.rb (renamed from activerecord/lib/active_record/type/type_map.rb) | 2 | ||||
-rw-r--r-- | activemodel/lib/active_model/type/unsigned_integer.rb (renamed from activerecord/lib/active_record/type/unsigned_integer.rb) | 2 | ||||
-rw-r--r-- | activemodel/lib/active_model/type/value.rb (renamed from activerecord/lib/active_record/type/value.rb) | 2 | ||||
-rw-r--r-- | activerecord/lib/active_record/attribute_methods/query.rb | 2 | ||||
-rw-r--r-- | activerecord/lib/active_record/connection_adapters/column.rb | 7 | ||||
-rw-r--r-- | activerecord/lib/active_record/type.rb | 66 | ||||
-rw-r--r-- | activerecord/lib/active_record/type/adapter_specific_registry.rb | 39 | ||||
-rw-r--r-- | activerecord/lib/active_record/type/helpers.rb | 4 | ||||
-rw-r--r-- | activerecord/lib/active_record/type/internal/abstract_json.rb | 4 | ||||
-rw-r--r-- | activerecord/lib/active_record/type/internal/timezone.rb | 15 | ||||
-rw-r--r-- | activerecord/lib/active_record/type/serialized.rb | 4 |
31 files changed, 336 insertions, 96 deletions
diff --git a/activemodel/lib/active_model/type.rb b/activemodel/lib/active_model/type.rb new file mode 100644 index 0000000000..64346bcab2 --- /dev/null +++ b/activemodel/lib/active_model/type.rb @@ -0,0 +1,59 @@ +require 'active_model/type/helpers' +require 'active_model/type/value' + +require 'active_model/type/big_integer' +require 'active_model/type/binary' +require 'active_model/type/boolean' +require 'active_model/type/date' +require 'active_model/type/date_time' +require 'active_model/type/decimal' +require 'active_model/type/decimal_without_scale' +require 'active_model/type/float' +require 'active_model/type/integer' +require 'active_model/type/string' +require 'active_model/type/text' +require 'active_model/type/time' +require 'active_model/type/unsigned_integer' + +require 'active_model/type/registry' +require 'active_model/type/type_map' +require 'active_model/type/hash_lookup_type_map' + +module ActiveModel + module Type + @registry = Registry.new + + class << self + attr_accessor :registry # :nodoc: + delegate :add_modifier, to: :registry + + # Add a new type to the registry, allowing it to be referenced as a + # symbol by ActiveModel::Attributes::ClassMethods#attribute. If your + # type is only meant to be used with a specific database adapter, you can + # do so by passing +adapter: :postgresql+. If your type has the same + # name as a native type for the current adapter, an exception will be + # raised unless you specify an +:override+ option. +override: true+ will + # cause your type to be used instead of the native type. +override: + # false+ will cause the native type to be used over yours if one exists. + def register(type_name, klass = nil, **options, &block) + registry.register(type_name, klass, **options, &block) + end + + def lookup(*args, **kwargs) # :nodoc: + registry.lookup(*args, **kwargs) + end + end + + register(:big_integer, Type::BigInteger, override: false) + register(:binary, Type::Binary, override: false) + register(:boolean, Type::Boolean, override: false) + register(:date, Type::Date, override: false) + register(:date_time, Type::DateTime, override: false) + register(:decimal, Type::Decimal, override: false) + register(:float, Type::Float, override: false) + register(:integer, Type::Integer, override: false) + register(:string, Type::String, override: false) + register(:text, Type::Text, override: false) + register(:time, Type::Time, override: false) + end +end diff --git a/activerecord/lib/active_record/type/big_integer.rb b/activemodel/lib/active_model/type/big_integer.rb index 0c72d8914f..4168cbfce7 100644 --- a/activerecord/lib/active_record/type/big_integer.rb +++ b/activemodel/lib/active_model/type/big_integer.rb @@ -1,6 +1,6 @@ -require 'active_record/type/integer' +require 'active_model/type/integer' -module ActiveRecord +module ActiveModel module Type class BigInteger < Integer # :nodoc: private diff --git a/activerecord/lib/active_record/type/binary.rb b/activemodel/lib/active_model/type/binary.rb index 0baf8c63ad..a0cc45b4c3 100644 --- a/activerecord/lib/active_record/type/binary.rb +++ b/activemodel/lib/active_model/type/binary.rb @@ -1,4 +1,4 @@ -module ActiveRecord +module ActiveModel module Type class Binary < Value # :nodoc: def type diff --git a/activerecord/lib/active_record/type/boolean.rb b/activemodel/lib/active_model/type/boolean.rb index f6a75512fd..c1bce98c87 100644 --- a/activerecord/lib/active_record/type/boolean.rb +++ b/activemodel/lib/active_model/type/boolean.rb @@ -1,6 +1,8 @@ -module ActiveRecord +module ActiveModel module Type class Boolean < Value # :nodoc: + FALSE_VALUES = [false, 0, '0', 'f', 'F', 'false', 'FALSE', 'off', 'OFF'].to_set + def type :boolean end @@ -11,7 +13,7 @@ module ActiveRecord if value == '' nil else - !ConnectionAdapters::Column::FALSE_VALUES.include?(value) + !FALSE_VALUES.include?(value) end end end diff --git a/activerecord/lib/active_record/type/date.rb b/activemodel/lib/active_model/type/date.rb index 3ceab59ebb..f74243a22c 100644 --- a/activerecord/lib/active_record/type/date.rb +++ b/activemodel/lib/active_model/type/date.rb @@ -1,4 +1,4 @@ -module ActiveRecord +module ActiveModel module Type class Date < Value # :nodoc: include Helpers::AcceptsMultiparameterTime.new @@ -24,8 +24,9 @@ module ActiveRecord end end + ISO_DATE = /\A(\d{4})-(\d\d)-(\d\d)\z/ def fast_string_to_date(string) - if string =~ ConnectionAdapters::Column::Format::ISO_DATE + if string =~ ISO_DATE new_date $1.to_i, $2.to_i, $3.to_i end end diff --git a/activerecord/lib/active_record/type/date_time.rb b/activemodel/lib/active_model/type/date_time.rb index a5199959b9..b068cfc672 100644 --- a/activerecord/lib/active_record/type/date_time.rb +++ b/activemodel/lib/active_model/type/date_time.rb @@ -1,4 +1,4 @@ -module ActiveRecord +module ActiveModel module Type class DateTime < Value # :nodoc: include Helpers::TimeValue diff --git a/activerecord/lib/active_record/type/decimal.rb b/activemodel/lib/active_model/type/decimal.rb index f5b145230d..83a16018ea 100644 --- a/activerecord/lib/active_record/type/decimal.rb +++ b/activemodel/lib/active_model/type/decimal.rb @@ -1,4 +1,4 @@ -module ActiveRecord +module ActiveModel module Type class Decimal < Value # :nodoc: include Helpers::Numeric diff --git a/activerecord/lib/active_record/type/decimal_without_scale.rb b/activemodel/lib/active_model/type/decimal_without_scale.rb index ff5559e300..129baa0c10 100644 --- a/activerecord/lib/active_record/type/decimal_without_scale.rb +++ b/activemodel/lib/active_model/type/decimal_without_scale.rb @@ -1,6 +1,6 @@ -require 'active_record/type/big_integer' +require 'active_model/type/big_integer' -module ActiveRecord +module ActiveModel module Type class DecimalWithoutScale < BigInteger # :nodoc: def type diff --git a/activerecord/lib/active_record/type/float.rb b/activemodel/lib/active_model/type/float.rb index d88482b85d..0f925bc7e1 100644 --- a/activerecord/lib/active_record/type/float.rb +++ b/activemodel/lib/active_model/type/float.rb @@ -1,4 +1,4 @@ -module ActiveRecord +module ActiveModel module Type class Float < Value # :nodoc: include Helpers::Numeric diff --git a/activerecord/lib/active_record/type/hash_lookup_type_map.rb b/activemodel/lib/active_model/type/hash_lookup_type_map.rb index 3b01e3f8ca..45d3515aad 100644 --- a/activerecord/lib/active_record/type/hash_lookup_type_map.rb +++ b/activemodel/lib/active_model/type/hash_lookup_type_map.rb @@ -1,4 +1,4 @@ -module ActiveRecord +module ActiveModel module Type class HashLookupTypeMap < TypeMap # :nodoc: def alias_type(type, alias_type) diff --git a/activemodel/lib/active_model/type/helpers.rb b/activemodel/lib/active_model/type/helpers.rb new file mode 100644 index 0000000000..a805a359ab --- /dev/null +++ b/activemodel/lib/active_model/type/helpers.rb @@ -0,0 +1,4 @@ +require 'active_model/type/helpers/accepts_multiparameter_time' +require 'active_model/type/helpers/numeric' +require 'active_model/type/helpers/mutable' +require 'active_model/type/helpers/time_value' diff --git a/activerecord/lib/active_record/type/helpers/accepts_multiparameter_time.rb b/activemodel/lib/active_model/type/helpers/accepts_multiparameter_time.rb index be571fc1c7..fa1ccd057e 100644 --- a/activerecord/lib/active_record/type/helpers/accepts_multiparameter_time.rb +++ b/activemodel/lib/active_model/type/helpers/accepts_multiparameter_time.rb @@ -1,4 +1,4 @@ -module ActiveRecord +module ActiveModel module Type module Helpers class AcceptsMultiparameterTime < Module # :nodoc: @@ -17,10 +17,7 @@ module ActiveRecord end return unless values_hash[1] && values_hash[2] && values_hash[3] values = values_hash.sort.map(&:last) - ::Time.send( - ActiveRecord::Base.default_timezone, - *values - ) + ::Time.send(default_timezone, *values) end private :value_from_multiparameter_assignment end diff --git a/activerecord/lib/active_record/type/helpers/mutable.rb b/activemodel/lib/active_model/type/helpers/mutable.rb index 88a9099277..4dddbe4e5e 100644 --- a/activerecord/lib/active_record/type/helpers/mutable.rb +++ b/activemodel/lib/active_model/type/helpers/mutable.rb @@ -1,4 +1,4 @@ -module ActiveRecord +module ActiveModel module Type module Helpers module Mutable # :nodoc: diff --git a/activerecord/lib/active_record/type/helpers/numeric.rb b/activemodel/lib/active_model/type/helpers/numeric.rb index a755a02a59..c883010506 100644 --- a/activerecord/lib/active_record/type/helpers/numeric.rb +++ b/activemodel/lib/active_model/type/helpers/numeric.rb @@ -1,4 +1,4 @@ -module ActiveRecord +module ActiveModel module Type module Helpers module Numeric # :nodoc: diff --git a/activerecord/lib/active_record/type/helpers/time_value.rb b/activemodel/lib/active_model/type/helpers/time_value.rb index 7eb41557cb..5a899d43ec 100644 --- a/activerecord/lib/active_record/type/helpers/time_value.rb +++ b/activemodel/lib/active_model/type/helpers/time_value.rb @@ -1,4 +1,4 @@ -module ActiveRecord +module ActiveModel module Type module Helpers module TimeValue # :nodoc: @@ -10,7 +10,7 @@ module ActiveRecord end if value.acts_like?(:time) - zone_conversion_method = ActiveRecord::Base.default_timezone == :utc ? :getutc : :getlocal + zone_conversion_method = is_utc? ? :getutc : :getlocal if value.respond_to?(zone_conversion_method) value = value.send(zone_conversion_method) @@ -19,6 +19,14 @@ module ActiveRecord value end + + def is_utc? + ::Time.zone_default =~ 'UTC' + end + + def default_timezone + ::Time.zone_default + end def type_cast_for_schema(value) "'#{value.to_s(:db)}'" @@ -33,21 +41,24 @@ module ActiveRecord def new_time(year, mon, mday, hour, min, sec, microsec, offset = nil) # Treat 0000-00-00 00:00:00 as nil. return if year.nil? || (year == 0 && mon == 0 && mday == 0) + if offset time = ::Time.utc(year, mon, mday, hour, min, sec, microsec) rescue nil return unless time time -= offset - Base.default_timezone == :utc ? time : time.getlocal + is_utc? ? time : time.getlocal else - ::Time.public_send(Base.default_timezone, year, mon, mday, hour, min, sec, microsec) rescue nil + ::Time.public_send(default_timezone, year, mon, mday, hour, min, sec, microsec) rescue nil end end + + ISO_DATETIME = /\A(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)(\.\d+)?\z/ # Doesn't handle time zones. def fast_string_to_time(string) - if string =~ ConnectionAdapters::Column::Format::ISO_DATETIME + if string =~ ISO_DATETIME microsec = ($7.to_r * 1_000_000).to_i new_time $1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i, microsec end diff --git a/activerecord/lib/active_record/type/integer.rb b/activemodel/lib/active_model/type/integer.rb index c5040c6d3b..2f73ede009 100644 --- a/activerecord/lib/active_record/type/integer.rb +++ b/activemodel/lib/active_model/type/integer.rb @@ -1,4 +1,4 @@ -module ActiveRecord +module ActiveModel module Type class Integer < Value # :nodoc: include Helpers::Numeric diff --git a/activemodel/lib/active_model/type/registry.rb b/activemodel/lib/active_model/type/registry.rb new file mode 100644 index 0000000000..8070a4bd38 --- /dev/null +++ b/activemodel/lib/active_model/type/registry.rb @@ -0,0 +1,151 @@ +module ActiveModel + # :stopdoc: + module Type + class Registry + def initialize + @registrations = [] + end + + def register(type_name, klass = nil, **options, &block) + block ||= proc { |_, *args| klass.new(*args) } + registrations << registration_klass.new(type_name, block, **options) + end + + def lookup(symbol, *args) + registration = registrations + .select { |r| r.matches?(symbol, *args) } + .max + + if registration + registration.call(self, symbol, *args) + else + raise ArgumentError, "Unknown type #{symbol.inspect}" + end + end + + def add_modifier(options, klass, **args) + registrations << decoration_registration_klass.new(options, klass, **args) + end + + protected + + attr_reader :registrations + + private + + def registration_klass + Registration + end + + def decoration_registration_klass + DecorationRegistration + end + end + + class Registration + def initialize(name, block, override: nil) + @name = name + @block = block + @override = override + end + + def call(_registry, *args, **kwargs) + if kwargs.any? # https://bugs.ruby-lang.org/issues/10856 + block.call(*args, **kwargs) + else + block.call(*args) + end + end + + def matches?(type_name, *args, **kwargs) + type_name == name# && matches_adapter?(**kwargs) + end + + def <=>(other) + # if conflicts_with?(other) + # raise TypeConflictError.new("Type #{name} was registered for all + # adapters, but shadows a native type with + # the same name for #{other.adapter}".squish) + # end + priority <=> other.priority + end + + protected + + attr_reader :name, :block, :override + + def priority + result = 0 + # if adapter + # result |= 1 + # end + if override + result |= 2 + end + result + end + + # def priority_except_adapter + # priority & 0b111111100 + # end + + private + + # def matches_adapter?(adapter: nil, **) + # (self.adapter.nil? || adapter == self.adapter) + # end + + # def conflicts_with?(other) + # same_priority_except_adapter?(other) && + # has_adapter_conflict?(other) + # end + + # def same_priority_except_adapter?(other) + # priority_except_adapter == other.priority_except_adapter + # end + + # def has_adapter_conflict?(other) + # (override.nil? && other.adapter) || + # (adapter && other.override.nil?) + # end + end + + class DecorationRegistration < Registration + def initialize(options, klass) + @options = options + @klass = klass + # @adapter = adapter + end + + def call(registry, *args, **kwargs) + subtype = registry.lookup(*args, **kwargs.except(*options.keys)) + klass.new(subtype) + end + + def matches?(*args, **kwargs) + matches_options?(**kwargs) + end + + def priority + super | 4 + end + + protected + + attr_reader :options, :klass + + private + + def matches_options?(**kwargs) + options.all? do |key, value| + kwargs[key] == value + end + end + end + end + + class TypeConflictError < StandardError + end + + # :startdoc: +end diff --git a/activerecord/lib/active_record/type/string.rb b/activemodel/lib/active_model/type/string.rb index 2662b7e874..fd1630c751 100644 --- a/activerecord/lib/active_record/type/string.rb +++ b/activemodel/lib/active_model/type/string.rb @@ -1,4 +1,4 @@ -module ActiveRecord +module ActiveModel module Type class String < Value # :nodoc: def type diff --git a/activerecord/lib/active_record/type/text.rb b/activemodel/lib/active_model/type/text.rb index 26f980f060..1ad04daba4 100644 --- a/activerecord/lib/active_record/type/text.rb +++ b/activemodel/lib/active_model/type/text.rb @@ -1,6 +1,6 @@ -require 'active_record/type/string' +require 'active_model/type/string' -module ActiveRecord +module ActiveModel module Type class Text < String # :nodoc: def type diff --git a/activerecord/lib/active_record/type/time.rb b/activemodel/lib/active_model/type/time.rb index 19a10021bc..7101bad566 100644 --- a/activerecord/lib/active_record/type/time.rb +++ b/activemodel/lib/active_model/type/time.rb @@ -1,4 +1,4 @@ -module ActiveRecord +module ActiveModel module Type class Time < Value # :nodoc: include Helpers::TimeValue diff --git a/activerecord/lib/active_record/type/type_map.rb b/activemodel/lib/active_model/type/type_map.rb index 8ce36cc9af..402b660a71 100644 --- a/activerecord/lib/active_record/type/type_map.rb +++ b/activemodel/lib/active_model/type/type_map.rb @@ -1,6 +1,6 @@ require 'concurrent' -module ActiveRecord +module ActiveModel module Type class TypeMap # :nodoc: def initialize diff --git a/activerecord/lib/active_record/type/unsigned_integer.rb b/activemodel/lib/active_model/type/unsigned_integer.rb index ed3e527483..3f49f9f5f7 100644 --- a/activerecord/lib/active_record/type/unsigned_integer.rb +++ b/activemodel/lib/active_model/type/unsigned_integer.rb @@ -1,4 +1,4 @@ -module ActiveRecord +module ActiveModel module Type class UnsignedInteger < Integer # :nodoc: private diff --git a/activerecord/lib/active_record/type/value.rb b/activemodel/lib/active_model/type/value.rb index 6b9d147ecc..c7d1197d69 100644 --- a/activerecord/lib/active_record/type/value.rb +++ b/activemodel/lib/active_model/type/value.rb @@ -1,4 +1,4 @@ -module ActiveRecord +module ActiveModel module Type class Value attr_reader :precision, :scale, :limit diff --git a/activerecord/lib/active_record/attribute_methods/query.rb b/activerecord/lib/active_record/attribute_methods/query.rb index 553122a5fc..10498f4322 100644 --- a/activerecord/lib/active_record/attribute_methods/query.rb +++ b/activerecord/lib/active_record/attribute_methods/query.rb @@ -19,7 +19,7 @@ module ActiveRecord if Numeric === value || value !~ /[^0-9]/ !value.to_i.zero? else - return false if ActiveRecord::ConnectionAdapters::Column::FALSE_VALUES.include?(value) + return false if ActiveModel::Type::Boolean::FALSE_VALUES.include?(value) !value.blank? end elsif value.respond_to?(:zero?) diff --git a/activerecord/lib/active_record/connection_adapters/column.rb b/activerecord/lib/active_record/connection_adapters/column.rb index 8222811e0c..5e31efec4a 100644 --- a/activerecord/lib/active_record/connection_adapters/column.rb +++ b/activerecord/lib/active_record/connection_adapters/column.rb @@ -5,13 +5,6 @@ module ActiveRecord module ConnectionAdapters # An abstract definition of a column in a table. class Column - FALSE_VALUES = [false, 0, '0', 'f', 'F', 'false', 'FALSE', 'off', 'OFF'].to_set - - module Format - ISO_DATE = /\A(\d{4})-(\d\d)-(\d\d)\z/ - ISO_DATETIME = /\A(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)(\.\d+)?\z/ - end - attr_reader :name, :null, :sql_type_metadata, :default, :default_function, :collation delegate :precision, :scale, :limit, :type, :sql_type, to: :sql_type_metadata, allow_nil: true diff --git a/activerecord/lib/active_record/type.rb b/activerecord/lib/active_record/type.rb index 53f3b53bec..165043021b 100644 --- a/activerecord/lib/active_record/type.rb +++ b/activerecord/lib/active_record/type.rb @@ -1,26 +1,28 @@ -require 'active_record/type/helpers' -require 'active_record/type/value' +require 'active_model/type/helpers' +require 'active_model/type/value' -require 'active_record/type/big_integer' -require 'active_record/type/binary' -require 'active_record/type/boolean' -require 'active_record/type/date' -require 'active_record/type/date_time' -require 'active_record/type/decimal' -require 'active_record/type/decimal_without_scale' -require 'active_record/type/float' -require 'active_record/type/integer' -require 'active_record/type/serialized' -require 'active_record/type/string' -require 'active_record/type/text' -require 'active_record/type/time' -require 'active_record/type/unsigned_integer' +require 'active_model/type/big_integer' +require 'active_model/type/binary' +require 'active_model/type/boolean' +require 'active_model/type/date' +require 'active_model/type/date_time' +require 'active_model/type/decimal' +require 'active_model/type/decimal_without_scale' +require 'active_model/type/float' +require 'active_model/type/integer' +require 'active_model/type/string' +require 'active_model/type/text' +require 'active_model/type/time' +require 'active_model/type/unsigned_integer' -require 'active_record/type/adapter_specific_registry' -require 'active_record/type/type_map' -require 'active_record/type/hash_lookup_type_map' +require 'active_model/type/registry' +require 'active_model/type/type_map' +require 'active_model/type/hash_lookup_type_map' require 'active_record/type/internal/abstract_json' +require 'active_record/type/internal/timezone' +require 'active_record/type/serialized' +require 'active_record/type/adapter_specific_registry' module ActiveRecord module Type @@ -53,6 +55,32 @@ module ActiveRecord end end + class Date < ActiveModel::Type::Date + include Internal::Timezone + end + + class DateTime < ActiveModel::Type::DateTime + include Internal::Timezone + end + class Time < ActiveModel::Type::Time + include Internal::Timezone + end + + Helpers = ActiveModel::Type::Helpers + BigInteger = ActiveModel::Type::BigInteger + Binary = ActiveModel::Type::Binary + Boolean = ActiveModel::Type::Boolean + Decimal = ActiveModel::Type::Decimal + DecimalWithoutScale = ActiveModel::Type::DecimalWithoutScale + Float = ActiveModel::Type::Float + Integer = ActiveModel::Type::Integer + String = ActiveModel::Type::String + Text = ActiveModel::Type::Text + UnsignedInteger = ActiveModel::Type::UnsignedInteger + Value = ActiveModel::Type::Value + TypeMap = ActiveModel::Type::TypeMap + HashLookupTypeMap = ActiveModel::Type::HashLookupTypeMap + register(:big_integer, Type::BigInteger, override: false) register(:binary, Type::Binary, override: false) register(:boolean, Type::Boolean, override: false) diff --git a/activerecord/lib/active_record/type/adapter_specific_registry.rb b/activerecord/lib/active_record/type/adapter_specific_registry.rb index 5f71b3cb94..3509429058 100644 --- a/activerecord/lib/active_record/type/adapter_specific_registry.rb +++ b/activerecord/lib/active_record/type/adapter_specific_registry.rb @@ -1,35 +1,18 @@ +require 'active_model/type/registry' + module ActiveRecord # :stopdoc: module Type - class AdapterSpecificRegistry - def initialize - @registrations = [] - end - - def register(type_name, klass = nil, **options, &block) - block ||= proc { |_, *args| klass.new(*args) } - registrations << Registration.new(type_name, block, **options) - end - - def lookup(symbol, *args) - registration = registrations - .select { |r| r.matches?(symbol, *args) } - .max - - if registration - registration.call(self, symbol, *args) - else - raise ArgumentError, "Unknown type #{symbol.inspect}" - end + class AdapterSpecificRegistry < ActiveModel::Type::Registry + private + + def registration_klass + Registration end - - def add_modifier(options, klass, **args) - registrations << DecorationRegistration.new(options, klass, **args) + + def decoration_registration_klass + DecorationRegistration end - - protected - - attr_reader :registrations end class Registration @@ -135,7 +118,7 @@ module ActiveRecord end end - class TypeConflictError < StandardError + class TypeConflictError < ::ActiveModel::TypeConflictError end # :startdoc: diff --git a/activerecord/lib/active_record/type/helpers.rb b/activerecord/lib/active_record/type/helpers.rb deleted file mode 100644 index 634d417d13..0000000000 --- a/activerecord/lib/active_record/type/helpers.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'active_record/type/helpers/accepts_multiparameter_time' -require 'active_record/type/helpers/numeric' -require 'active_record/type/helpers/mutable' -require 'active_record/type/helpers/time_value' diff --git a/activerecord/lib/active_record/type/internal/abstract_json.rb b/activerecord/lib/active_record/type/internal/abstract_json.rb index 963a8245d0..097d1bd363 100644 --- a/activerecord/lib/active_record/type/internal/abstract_json.rb +++ b/activerecord/lib/active_record/type/internal/abstract_json.rb @@ -1,8 +1,8 @@ module ActiveRecord module Type module Internal # :nodoc: - class AbstractJson < Type::Value # :nodoc: - include Type::Helpers::Mutable + class AbstractJson < ActiveModel::Type::Value # :nodoc: + include ActiveModel::Type::Helpers::Mutable def type :json diff --git a/activerecord/lib/active_record/type/internal/timezone.rb b/activerecord/lib/active_record/type/internal/timezone.rb new file mode 100644 index 0000000000..07dbb0b2c6 --- /dev/null +++ b/activerecord/lib/active_record/type/internal/timezone.rb @@ -0,0 +1,15 @@ +module ActiveRecord + module Type + module Internal + module Timezone + def is_utc? + ActiveRecord::Base.default_timezone == :utc + end + + def default_timezone + ActiveRecord::Base.default_timezone + end + end + end + end +end diff --git a/activerecord/lib/active_record/type/serialized.rb b/activerecord/lib/active_record/type/serialized.rb index ea3e0d6a45..203a395415 100644 --- a/activerecord/lib/active_record/type/serialized.rb +++ b/activerecord/lib/active_record/type/serialized.rb @@ -1,7 +1,7 @@ module ActiveRecord module Type - class Serialized < DelegateClass(Type::Value) # :nodoc: - include Helpers::Mutable + class Serialized < DelegateClass(ActiveModel::Type::Value) # :nodoc: + include ActiveModel::Type::Helpers::Mutable attr_reader :subtype, :coder |