diff options
author | Sean Griffin <sean@seantheprogrammer.com> | 2015-09-21 09:01:34 -0600 |
---|---|---|
committer | Sean Griffin <sean@seantheprogrammer.com> | 2015-09-21 10:12:31 -0600 |
commit | e467deb6c66d9b45a0c596706284c140f8e1f1b3 (patch) | |
tree | b48be9e4e2846b63b6dd9d11086584bd2bc3ddfe /activerecord | |
parent | 9cc8c6f3730df3d94c81a55be9ee1b7b4ffd29f6 (diff) | |
download | rails-e467deb6c66d9b45a0c596706284c140f8e1f1b3.tar.gz rails-e467deb6c66d9b45a0c596706284c140f8e1f1b3.tar.bz2 rails-e467deb6c66d9b45a0c596706284c140f8e1f1b3.zip |
`TypeMap` and `HashLookupTypeMap` shouldn't be in Active Model
These are used by the connection adapters to convert SQL type
information into the appropriate type object, and makes no sense outside
of the context of Active Record
Diffstat (limited to 'activerecord')
-rw-r--r-- | activerecord/lib/active_record/type.rb | 7 | ||||
-rw-r--r-- | activerecord/lib/active_record/type/hash_lookup_type_map.rb | 23 | ||||
-rw-r--r-- | activerecord/lib/active_record/type/type_map.rb | 64 |
3 files changed, 90 insertions, 4 deletions
diff --git a/activerecord/lib/active_record/type.rb b/activerecord/lib/active_record/type.rb index 165043021b..5b089d66a0 100644 --- a/activerecord/lib/active_record/type.rb +++ b/activerecord/lib/active_record/type.rb @@ -16,14 +16,15 @@ 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' 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' +require 'active_record/type/type_map' +require 'active_record/type/hash_lookup_type_map' + module ActiveRecord module Type @registry = AdapterSpecificRegistry.new @@ -78,8 +79,6 @@ module ActiveRecord 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) diff --git a/activerecord/lib/active_record/type/hash_lookup_type_map.rb b/activerecord/lib/active_record/type/hash_lookup_type_map.rb new file mode 100644 index 0000000000..3b01e3f8ca --- /dev/null +++ b/activerecord/lib/active_record/type/hash_lookup_type_map.rb @@ -0,0 +1,23 @@ +module ActiveRecord + module Type + class HashLookupTypeMap < TypeMap # :nodoc: + def alias_type(type, alias_type) + register_type(type) { |_, *args| lookup(alias_type, *args) } + end + + def key?(key) + @mapping.key?(key) + end + + def keys + @mapping.keys + end + + private + + def perform_fetch(type, *args, &block) + @mapping.fetch(type, block).call(type, *args) + end + end + end +end diff --git a/activerecord/lib/active_record/type/type_map.rb b/activerecord/lib/active_record/type/type_map.rb new file mode 100644 index 0000000000..8ce36cc9af --- /dev/null +++ b/activerecord/lib/active_record/type/type_map.rb @@ -0,0 +1,64 @@ +require 'concurrent' + +module ActiveRecord + module Type + class TypeMap # :nodoc: + def initialize + @mapping = {} + @cache = Concurrent::Map.new do |h, key| + h.fetch_or_store(key, Concurrent::Map.new) + end + end + + def lookup(lookup_key, *args) + fetch(lookup_key, *args) { default_value } + end + + def fetch(lookup_key, *args, &block) + @cache[lookup_key].fetch_or_store(args) do + perform_fetch(lookup_key, *args, &block) + end + end + + def register_type(key, value = nil, &block) + raise ::ArgumentError unless value || block + @cache.clear + + if block + @mapping[key] = block + else + @mapping[key] = proc { value } + end + end + + def alias_type(key, target_key) + register_type(key) do |sql_type, *args| + metadata = sql_type[/\(.*\)/, 0] + lookup("#{target_key}#{metadata}", *args) + end + end + + def clear + @mapping.clear + end + + private + + def perform_fetch(lookup_key, *args) + matching_pair = @mapping.reverse_each.detect do |key, _| + key === lookup_key + end + + if matching_pair + matching_pair.last.call(lookup_key, *args) + else + yield lookup_key, *args + end + end + + def default_value + @default_value ||= Value.new + end + end + end +end |