1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Move types to the top level ActiveRecord namespace

`ActiveRecord::ConnectionAdapters::Type::Value` =>
`ActiveRecord::Type::Value`
This commit is contained in:
Sean Griffin 2014-05-27 10:59:22 -07:00
parent 7f73b9152c
commit 728fa69839
41 changed files with 592 additions and 643 deletions

View file

@ -1,9 +1,9 @@
require 'date'
require 'bigdecimal'
require 'bigdecimal/util'
require 'active_record/type'
require 'active_support/core_ext/benchmark'
require 'active_record/connection_adapters/schema_cache'
require 'active_record/connection_adapters/type'
require 'active_record/connection_adapters/abstract/schema_dumper'
require 'active_record/connection_adapters/abstract/schema_creation'
require 'monitor'

View file

@ -298,7 +298,7 @@ module ActiveRecord
end
class << self
TYPES = ConnectionAdapters::Type::HashLookupTypeMap.new # :nodoc:
TYPES = Type::HashLookupTypeMap.new # :nodoc:
delegate :register_type, :alias_type, to: :TYPES

View file

@ -1,25 +0,0 @@
require 'active_record/connection_adapters/type/numeric'
require 'active_record/connection_adapters/type/time_value'
require 'active_record/connection_adapters/type/value'
require 'active_record/connection_adapters/type/binary'
require 'active_record/connection_adapters/type/boolean'
require 'active_record/connection_adapters/type/date'
require 'active_record/connection_adapters/type/date_time'
require 'active_record/connection_adapters/type/decimal'
require 'active_record/connection_adapters/type/decimal_without_scale'
require 'active_record/connection_adapters/type/float'
require 'active_record/connection_adapters/type/integer'
require 'active_record/connection_adapters/type/string'
require 'active_record/connection_adapters/type/text'
require 'active_record/connection_adapters/type/time'
require 'active_record/connection_adapters/type/type_map'
require 'active_record/connection_adapters/type/hash_lookup_type_map'
module ActiveRecord
module ConnectionAdapters
module Type # :nodoc:
end
end
end

View file

@ -1,19 +0,0 @@
module ActiveRecord
module ConnectionAdapters
module Type
class Binary < Value # :nodoc:
def type
:binary
end
def binary?
true
end
def klass
::String
end
end
end
end
end

View file

@ -1,21 +0,0 @@
module ActiveRecord
module ConnectionAdapters
module Type
class Boolean < Value # :nodoc:
def type
:boolean
end
private
def cast_value(value)
if value == ''
nil
else
Column::TRUE_VALUES.include?(value)
end
end
end
end
end
end

View file

@ -1,44 +0,0 @@
module ActiveRecord
module ConnectionAdapters
module Type
class Date < Value # :nodoc:
def type
:date
end
def klass
::Date
end
private
def cast_value(value)
if value.is_a?(::String)
return if value.empty?
fast_string_to_date(value) || fallback_string_to_date(value)
elsif value.respond_to?(:to_date)
value.to_date
else
value
end
end
def fast_string_to_date(string)
if string =~ Column::Format::ISO_DATE
new_date $1.to_i, $2.to_i, $3.to_i
end
end
def fallback_string_to_date(string)
new_date(*::Date._parse(string, false).values_at(:year, :mon, :mday))
end
def new_date(year, mon, mday)
if year && year != 0
::Date.new(year, mon, mday) rescue nil
end
end
end
end
end
end

View file

@ -1,35 +0,0 @@
module ActiveRecord
module ConnectionAdapters
module Type
class DateTime < Value # :nodoc:
include TimeValue
def type
:datetime
end
private
def cast_value(string)
return string unless string.is_a?(::String)
return if string.empty?
fast_string_to_time(string) || fallback_string_to_time(string)
end
# '0.123456' -> 123456
# '1.123456' -> 123456
def microseconds(time)
time[:sec_fraction] ? (time[:sec_fraction] * 1_000_000).to_i : 0
end
def fallback_string_to_time(string)
time_hash = ::Date._parse(string)
time_hash[:sec_fraction] = microseconds(time_hash)
new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction, :offset))
end
end
end
end
end

View file

@ -1,27 +0,0 @@
module ActiveRecord
module ConnectionAdapters
module Type
class Decimal < Value # :nodoc:
include Numeric
def type
:decimal
end
def klass
::BigDecimal
end
private
def cast_value(value)
if value.respond_to?(:to_d)
value.to_d
else
value.to_s.to_d
end
end
end
end
end
end

View file

@ -1,13 +0,0 @@
require 'active_record/connection_adapters/type/integer'
module ActiveRecord
module ConnectionAdapters
module Type
class DecimalWithoutScale < Integer # :nodoc:
def type
:decimal
end
end
end
end
end

View file

@ -1,25 +0,0 @@
module ActiveRecord
module ConnectionAdapters
module Type
class Float < Value # :nodoc:
include Numeric
def type
:float
end
def klass
::Float
end
alias type_cast_for_database type_cast
private
def cast_value(value)
value.to_f
end
end
end
end
end

View file

@ -1,21 +0,0 @@
module ActiveRecord
module ConnectionAdapters
module Type
class HashLookupTypeMap < TypeMap # :nodoc:
delegate :key?, to: :@mapping
def lookup(type, *args)
@mapping.fetch(type, proc { default_value }).call(type, *args)
end
def fetch(type, *args, &block)
@mapping.fetch(type, block).call(type, *args)
end
def alias_type(type, alias_type)
register_type(type) { |_, *args| lookup(alias_type, *args) }
end
end
end
end
end

View file

@ -1,29 +0,0 @@
module ActiveRecord
module ConnectionAdapters
module Type
class Integer < Value # :nodoc:
include Numeric
def type
:integer
end
def klass
::Fixnum
end
alias type_cast_for_database type_cast
private
def cast_value(value)
case value
when true then 1
when false then 0
else value.to_i rescue nil
end
end
end
end
end
end

View file

@ -1,20 +0,0 @@
module ActiveRecord
module ConnectionAdapters
module Type
module Numeric # :nodoc:
def number?
true
end
def type_cast_for_write(value)
case value
when true then 1
when false then 0
when ::String then value.presence
else super
end
end
end
end
end
end

View file

@ -1,29 +0,0 @@
module ActiveRecord
module ConnectionAdapters
module Type
class String < Value # :nodoc:
def type
:string
end
def text?
true
end
def klass
::String
end
private
def cast_value(value)
case value
when true then "1"
when false then "0"
else value.to_s
end
end
end
end
end
end

View file

@ -1,13 +0,0 @@
require 'active_record/connection_adapters/type/string'
module ActiveRecord
module ConnectionAdapters
module Type
class Text < String # :nodoc:
def type
:text
end
end
end
end
end

View file

@ -1,28 +0,0 @@
module ActiveRecord
module ConnectionAdapters
module Type
class Time < Value
include TimeValue
def type
:time
end
private
def cast_value(value)
return value unless value.is_a?(::String)
return if value.empty?
dummy_time_value = "2000-01-01 #{value}"
fast_string_to_time(dummy_time_value) || begin
time_hash = ::Date._parse(dummy_time_value)
return if time_hash[:hour].nil?
new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction))
end
end
end
end
end
end

View file

@ -1,36 +0,0 @@
module ActiveRecord
module ConnectionAdapters
module Type
module TimeValue # :nodoc:
def klass
::Time
end
private
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
else
::Time.public_send(Base.default_timezone, year, mon, mday, hour, min, sec, microsec) rescue nil
end
end
# Doesn't handle time zones.
def fast_string_to_time(string)
if string =~ Column::Format::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
end
end
end
end
end

View file

@ -1,50 +0,0 @@
module ActiveRecord
module ConnectionAdapters
module Type
class TypeMap # :nodoc:
def initialize
@mapping = {}
end
def lookup(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
default_value
end
end
def register_type(key, value = nil, &block)
raise ::ArgumentError unless value || block
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 default_value
@default_value ||= Value.new
end
end
end
end
end

View file

@ -1,61 +0,0 @@
module ActiveRecord
module ConnectionAdapters
module Type
class Value # :nodoc:
attr_reader :precision, :scale, :limit
# Valid options are +precision+, +scale+, and +limit+.
# They are only used when dumping schema.
def initialize(options = {})
options.assert_valid_keys(:precision, :scale, :limit)
@precision = options[:precision]
@scale = options[:scale]
@limit = options[:limit]
end
# The simplified that this object represents. Subclasses
# should override this method.
def type; end
# Takes an input from the database, or from attribute setters,
# and casts it to a type appropriate for this object. This method
# should not be overriden by subclasses. Instead, override `cast_value`.
def type_cast(value)
cast_value(value) unless value.nil?
end
def type_cast_for_write(value)
value
end
def type_cast_for_database(value)
type_cast_for_write(value)
end
def text?
false
end
def number?
false
end
def binary?
false
end
def klass
::Object
end
private
# Responsible for casting values from external sources to the appropriate
# type. Called by `type_cast` for all values except `nil`.
def cast_value(value) # :api: public
value
end
end
end
end
end

View file

@ -516,7 +516,7 @@ module ActiveRecord
# Determines if a hash contains a truthy _destroy key.
def has_destroy_flag?(hash)
ConnectionAdapters::Type::Boolean.new.type_cast(hash['_destroy'])
Type::Boolean.new.type_cast(hash['_destroy'])
end
# Determines if a new record should be rejected by checking

View file

@ -2,7 +2,7 @@ module ActiveRecord
module Properties # :nodoc:
extend ActiveSupport::Concern
Type = ConnectionAdapters::Type
Type = ActiveRecord::Type
module ClassMethods
# Defines or overrides a property on this model. This allows customization of

View file

@ -0,0 +1,18 @@
require 'active_record/type/numeric'
require 'active_record/type/time_value'
require 'active_record/type/value'
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/string'
require 'active_record/type/text'
require 'active_record/type/time'
require 'active_record/type/type_map'
require 'active_record/type/hash_lookup_type_map'

View file

@ -0,0 +1,17 @@
module ActiveRecord
module Type
class Binary < Value # :nodoc:
def type
:binary
end
def binary?
true
end
def klass
::String
end
end
end
end

View file

@ -0,0 +1,19 @@
module ActiveRecord
module Type
class Boolean < Value # :nodoc:
def type
:boolean
end
private
def cast_value(value)
if value == ''
nil
else
ConnectionAdapters::Column::TRUE_VALUES.include?(value)
end
end
end
end
end

View file

@ -0,0 +1,42 @@
module ActiveRecord
module Type
class Date < Value # :nodoc:
def type
:date
end
def klass
::Date
end
private
def cast_value(value)
if value.is_a?(::String)
return if value.empty?
fast_string_to_date(value) || fallback_string_to_date(value)
elsif value.respond_to?(:to_date)
value.to_date
else
value
end
end
def fast_string_to_date(string)
if string =~ ConnectionAdapters::Column::Format::ISO_DATE
new_date $1.to_i, $2.to_i, $3.to_i
end
end
def fallback_string_to_date(string)
new_date(*::Date._parse(string, false).values_at(:year, :mon, :mday))
end
def new_date(year, mon, mday)
if year && year != 0
::Date.new(year, mon, mday) rescue nil
end
end
end
end
end

View file

@ -0,0 +1,33 @@
module ActiveRecord
module Type
class DateTime < Value # :nodoc:
include TimeValue
def type
:datetime
end
private
def cast_value(string)
return string unless string.is_a?(::String)
return if string.empty?
fast_string_to_time(string) || fallback_string_to_time(string)
end
# '0.123456' -> 123456
# '1.123456' -> 123456
def microseconds(time)
time[:sec_fraction] ? (time[:sec_fraction] * 1_000_000).to_i : 0
end
def fallback_string_to_time(string)
time_hash = ::Date._parse(string)
time_hash[:sec_fraction] = microseconds(time_hash)
new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction, :offset))
end
end
end
end

View file

@ -0,0 +1,25 @@
module ActiveRecord
module Type
class Decimal < Value # :nodoc:
include Numeric
def type
:decimal
end
def klass
::BigDecimal
end
private
def cast_value(value)
if value.respond_to?(:to_d)
value.to_d
else
value.to_s.to_d
end
end
end
end
end

View file

@ -0,0 +1,11 @@
require 'active_record/type/integer'
module ActiveRecord
module Type
class DecimalWithoutScale < Integer # :nodoc:
def type
:decimal
end
end
end
end

View file

@ -0,0 +1,23 @@
module ActiveRecord
module Type
class Float < Value # :nodoc:
include Numeric
def type
:float
end
def klass
::Float
end
alias type_cast_for_database type_cast
private
def cast_value(value)
value.to_f
end
end
end
end

View file

@ -0,0 +1,19 @@
module ActiveRecord
module Type
class HashLookupTypeMap < TypeMap # :nodoc:
delegate :key?, to: :@mapping
def lookup(type, *args)
@mapping.fetch(type, proc { default_value }).call(type, *args)
end
def fetch(type, *args, &block)
@mapping.fetch(type, block).call(type, *args)
end
def alias_type(type, alias_type)
register_type(type) { |_, *args| lookup(alias_type, *args) }
end
end
end
end

View file

@ -0,0 +1,27 @@
module ActiveRecord
module Type
class Integer < Value # :nodoc:
include Numeric
def type
:integer
end
def klass
::Fixnum
end
alias type_cast_for_database type_cast
private
def cast_value(value)
case value
when true then 1
when false then 0
else value.to_i rescue nil
end
end
end
end
end

View file

@ -0,0 +1,18 @@
module ActiveRecord
module Type
module Numeric # :nodoc:
def number?
true
end
def type_cast_for_write(value)
case value
when true then 1
when false then 0
when ::String then value.presence
else super
end
end
end
end
end

View file

@ -0,0 +1,27 @@
module ActiveRecord
module Type
class String < Value # :nodoc:
def type
:string
end
def text?
true
end
def klass
::String
end
private
def cast_value(value)
case value
when true then "1"
when false then "0"
else value.to_s
end
end
end
end
end

View file

@ -0,0 +1,11 @@
require 'active_record/type/string'
module ActiveRecord
module Type
class Text < String # :nodoc:
def type
:text
end
end
end
end

View file

@ -0,0 +1,26 @@
module ActiveRecord
module Type
class Time < Value # :nodoc:
include TimeValue
def type
:time
end
private
def cast_value(value)
return value unless value.is_a?(::String)
return if value.empty?
dummy_time_value = "2000-01-01 #{value}"
fast_string_to_time(dummy_time_value) || begin
time_hash = ::Date._parse(dummy_time_value)
return if time_hash[:hour].nil?
new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction))
end
end
end
end
end

View file

@ -0,0 +1,34 @@
module ActiveRecord
module Type
module TimeValue # :nodoc:
def klass
::Time
end
private
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
else
::Time.public_send(Base.default_timezone, year, mon, mday, hour, min, sec, microsec) rescue nil
end
end
# Doesn't handle time zones.
def fast_string_to_time(string)
if string =~ ConnectionAdapters::Column::Format::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
end
end
end
end

View file

@ -0,0 +1,48 @@
module ActiveRecord
module Type
class TypeMap # :nodoc:
def initialize
@mapping = {}
end
def lookup(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
default_value
end
end
def register_type(key, value = nil, &block)
raise ::ArgumentError unless value || block
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 default_value
@default_value ||= Value.new
end
end
end
end

View file

@ -0,0 +1,59 @@
module ActiveRecord
module Type
class Value # :nodoc:
attr_reader :precision, :scale, :limit
# Valid options are +precision+, +scale+, and +limit+.
# They are only used when dumping schema.
def initialize(options = {})
options.assert_valid_keys(:precision, :scale, :limit)
@precision = options[:precision]
@scale = options[:scale]
@limit = options[:limit]
end
# The simplified that this object represents. Subclasses
# should override this method.
def type; end
# Takes an input from the database, or from attribute setters,
# and casts it to a type appropriate for this object. This method
# should not be overriden by subclasses. Instead, override `cast_value`.
def type_cast(value)
cast_value(value) unless value.nil?
end
def type_cast_for_write(value)
value
end
def type_cast_for_database(value)
type_cast_for_write(value)
end
def text?
false
end
def number?
false
end
def binary?
false
end
def klass
::Object
end
private
# Responsible for casting values from external sources to the appropriate
# type. Called by `type_cast` for all values except `nil`.
def cast_value(value) # :api: public
value
end
end
end
end

View file

@ -83,7 +83,7 @@ end
class PostgresqlCompositeWithCustomOIDTest < ActiveRecord::TestCase
include PostgresqlCompositeBehavior
class FullAddressType < ActiveRecord::ConnectionAdapters::Type::Value
class FullAddressType < ActiveRecord::Type::Value
def type; :full_address end
def type_cast(value)

View file

@ -1,142 +0,0 @@
require "cases/helper"
module ActiveRecord
module ConnectionAdapters
module Type
class TypeMapTest < ActiveRecord::TestCase
def test_default_type
mapping = TypeMap.new
assert_kind_of Value, mapping.lookup(:undefined)
end
def test_registering_types
boolean = Boolean.new
mapping = TypeMap.new
mapping.register_type(/boolean/i, boolean)
assert_equal mapping.lookup('boolean'), boolean
end
def test_overriding_registered_types
time = Time.new
timestamp = DateTime.new
mapping = TypeMap.new
mapping.register_type(/time/i, time)
mapping.register_type(/time/i, timestamp)
assert_equal mapping.lookup('time'), timestamp
end
def test_fuzzy_lookup
string = String.new
mapping = TypeMap.new
mapping.register_type(/varchar/i, string)
assert_equal mapping.lookup('varchar(20)'), string
end
def test_aliasing_types
string = String.new
mapping = TypeMap.new
mapping.register_type(/string/i, string)
mapping.alias_type(/varchar/i, 'string')
assert_equal mapping.lookup('varchar'), string
end
def test_changing_type_changes_aliases
time = Time.new
timestamp = DateTime.new
mapping = TypeMap.new
mapping.register_type(/timestamp/i, time)
mapping.alias_type(/datetime/i, 'timestamp')
mapping.register_type(/timestamp/i, timestamp)
assert_equal mapping.lookup('datetime'), timestamp
end
def test_aliases_keep_metadata
mapping = TypeMap.new
mapping.register_type(/decimal/i) { |sql_type| sql_type }
mapping.alias_type(/number/i, 'decimal')
assert_equal mapping.lookup('number(20)'), 'decimal(20)'
assert_equal mapping.lookup('number'), 'decimal'
end
def test_register_proc
string = String.new
binary = Binary.new
mapping = TypeMap.new
mapping.register_type(/varchar/i) do |type|
if type.include?('(')
string
else
binary
end
end
assert_equal mapping.lookup('varchar(20)'), string
assert_equal mapping.lookup('varchar'), binary
end
def test_additional_lookup_args
mapping = TypeMap.new
mapping.register_type(/varchar/i) do |type, limit|
if limit > 255
'text'
else
'string'
end
end
mapping.alias_type(/string/i, 'varchar')
assert_equal mapping.lookup('varchar', 200), 'string'
assert_equal mapping.lookup('varchar', 400), 'text'
assert_equal mapping.lookup('string', 400), 'text'
end
def test_requires_value_or_block
mapping = TypeMap.new
assert_raises(ArgumentError) do
mapping.register_type(/only key/i)
end
end
def test_lookup_non_strings
mapping = HashLookupTypeMap.new
mapping.register_type(1, 'string')
mapping.register_type(2, 'int')
mapping.alias_type(3, 1)
assert_equal mapping.lookup(1), 'string'
assert_equal mapping.lookup(2), 'int'
assert_equal mapping.lookup(3), 'string'
assert_kind_of Type::Value, mapping.lookup(4)
end
def test_clear_mappings
time = Time.new
mapping = TypeMap.new
mapping.register_type(/time/i, time)
mapping.clear
assert_not_equal mapping.lookup('time'), time
end
end
end
end
end

View file

@ -0,0 +1,130 @@
require "cases/helper"
module ActiveRecord
module Type
class TypeMapTest < ActiveRecord::TestCase
def test_default_type
mapping = TypeMap.new
assert_kind_of Value, mapping.lookup(:undefined)
end
def test_registering_types
boolean = Boolean.new
mapping = TypeMap.new
mapping.register_type(/boolean/i, boolean)
assert_equal mapping.lookup('boolean'), boolean
end
def test_overriding_registered_types
time = Time.new
timestamp = DateTime.new
mapping = TypeMap.new
mapping.register_type(/time/i, time)
mapping.register_type(/time/i, timestamp)
assert_equal mapping.lookup('time'), timestamp
end
def test_fuzzy_lookup
string = String.new
mapping = TypeMap.new
mapping.register_type(/varchar/i, string)
assert_equal mapping.lookup('varchar(20)'), string
end
def test_aliasing_types
string = String.new
mapping = TypeMap.new
mapping.register_type(/string/i, string)
mapping.alias_type(/varchar/i, 'string')
assert_equal mapping.lookup('varchar'), string
end
def test_changing_type_changes_aliases
time = Time.new
timestamp = DateTime.new
mapping = TypeMap.new
mapping.register_type(/timestamp/i, time)
mapping.alias_type(/datetime/i, 'timestamp')
mapping.register_type(/timestamp/i, timestamp)
assert_equal mapping.lookup('datetime'), timestamp
end
def test_aliases_keep_metadata
mapping = TypeMap.new
mapping.register_type(/decimal/i) { |sql_type| sql_type }
mapping.alias_type(/number/i, 'decimal')
assert_equal mapping.lookup('number(20)'), 'decimal(20)'
assert_equal mapping.lookup('number'), 'decimal'
end
def test_register_proc
string = String.new
binary = Binary.new
mapping = TypeMap.new
mapping.register_type(/varchar/i) do |type|
if type.include?('(')
string
else
binary
end
end
assert_equal mapping.lookup('varchar(20)'), string
assert_equal mapping.lookup('varchar'), binary
end
def test_additional_lookup_args
mapping = TypeMap.new
mapping.register_type(/varchar/i) do |type, limit|
if limit > 255
'text'
else
'string'
end
end
mapping.alias_type(/string/i, 'varchar')
assert_equal mapping.lookup('varchar', 200), 'string'
assert_equal mapping.lookup('varchar', 400), 'text'
assert_equal mapping.lookup('string', 400), 'text'
end
def test_requires_value_or_block
mapping = TypeMap.new
assert_raises(ArgumentError) do
mapping.register_type(/only key/i)
end
end
def test_lookup_non_strings
mapping = HashLookupTypeMap.new
mapping.register_type(1, 'string')
mapping.register_type(2, 'int')
mapping.alias_type(3, 1)
assert_equal mapping.lookup(1), 'string'
assert_equal mapping.lookup(2), 'int'
assert_equal mapping.lookup(3), 'string'
assert_kind_of Type::Value, mapping.lookup(4)
end
end
end
end