aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/type
diff options
context:
space:
mode:
authorSean Griffin <sean@seantheprogrammer.com>2015-09-21 09:01:34 -0600
committerSean Griffin <sean@seantheprogrammer.com>2015-09-21 10:12:31 -0600
commite467deb6c66d9b45a0c596706284c140f8e1f1b3 (patch)
treeb48be9e4e2846b63b6dd9d11086584bd2bc3ddfe /activerecord/lib/active_record/type
parent9cc8c6f3730df3d94c81a55be9ee1b7b4ffd29f6 (diff)
downloadrails-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/lib/active_record/type')
-rw-r--r--activerecord/lib/active_record/type/hash_lookup_type_map.rb23
-rw-r--r--activerecord/lib/active_record/type/type_map.rb64
2 files changed, 87 insertions, 0 deletions
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