提交 d24e6407 编写于 作者: S Sean Griffin

Rename `type_cast` to `type_cast_from_database`

In some cases there is a difference between the two, we should always
be doing one or the other. For convenience, `type_cast` is still a
private method on type, so new types that do not need different behavior
don't need to implement two methods, but it has been moved to private so
it cannot be used accidentally.
上级 254efb71
......@@ -57,7 +57,7 @@ def ids_reader
def ids_writer(ids)
pk_column = reflection.primary_key_column
ids = Array(ids).reject { |id| id.blank? }
ids.map! { |i| pk_column.type_cast(i) }
ids.map! { |i| pk_column.type_cast_from_user(i) }
replace(klass.find(ids).index_by { |r| r.id }.values_at(*ids))
end
......
......@@ -144,7 +144,7 @@ def instantiate(result_set, aliases)
column_aliases = aliases.column_aliases join_root
result_set.each { |row_hash|
primary_id = type_caster.type_cast row_hash[primary_key]
primary_id = type_caster.type_cast_from_database row_hash[primary_key]
parent = parents[primary_id] ||= join_root.instantiate(row_hash, column_aliases)
construct(parent, join_root, row_hash, result_set, seen, model_cache, aliases)
}
......
......@@ -123,9 +123,9 @@ def read_attribute(attr_name)
}
if self.class.cache_attribute?(name)
@attributes[name] = column.type_cast(value)
@attributes[name] = column.type_cast_from_database(value)
else
column.type_cast value
column.type_cast_from_database value
end
}
end
......
......@@ -2,7 +2,7 @@ module ActiveRecord
module AttributeMethods
module TimeZoneConversion
class Type < SimpleDelegator # :nodoc:
def type_cast(value)
def type_cast_from_database(value)
convert_time_to_time_zone(super)
end
......
......@@ -17,7 +17,7 @@ module Format
delegate :type, :precision, :scale, :limit, :klass, :accessor,
:text?, :number?, :binary?, :serialized?, :changed?,
:type_cast, :type_cast_from_user, :type_cast_for_database,
:type_cast_from_user, :type_cast_from_database, :type_cast_for_database,
:type_cast_for_schema,
to: :cast_type
......@@ -52,7 +52,7 @@ def human_name
end
def default
@default ||= type_cast(@original_default)
@default ||= type_cast_from_database(@original_default)
end
def with_type(type)
......
......@@ -108,7 +108,7 @@ def type_cast_array(oid, value)
if ::Array === value
value.map {|item| type_cast_array(oid, item)}
else
oid.type_cast value
oid.type_cast_from_database value
end
end
end
......
......@@ -8,15 +8,15 @@ def type
end
def type_cast_from_user(value)
type_cast(type_cast_for_database(value))
type_cast_from_database(type_cast_for_database(value))
end
def type_cast_for_database(value)
ConnectionAdapters::PostgreSQLColumn.hstore_to_string(value)
def type_cast_from_database(value)
ConnectionAdapters::PostgreSQLColumn.string_to_hstore(value)
end
def cast_value(value)
ConnectionAdapters::PostgreSQLColumn.string_to_hstore value
def type_cast_for_database(value)
ConnectionAdapters::PostgreSQLColumn.hstore_to_string(value)
end
def accessor
......
......@@ -8,15 +8,15 @@ def type
end
def type_cast_from_user(value)
type_cast(type_cast_for_database(value))
type_cast_from_database(type_cast_for_database(value))
end
def type_cast_for_database(value)
ConnectionAdapters::PostgreSQLColumn.json_to_string(value)
def type_cast_from_database(value)
ConnectionAdapters::PostgreSQLColumn.string_to_json(value)
end
def cast_value(value)
ConnectionAdapters::PostgreSQLColumn.string_to_json value
def type_cast_for_database(value)
ConnectionAdapters::PostgreSQLColumn.json_to_string(value)
end
def accessor
......
......@@ -29,7 +29,7 @@ def type_cast_for_schema(value)
end
def type_cast_single(value)
infinity?(value) ? value : @subtype.type_cast(value)
infinity?(value) ? value : @subtype.type_cast_from_database(value)
end
def cast_value(value)
......
......@@ -348,14 +348,14 @@ def extension_enabled?(name)
if supports_extensions?
res = exec_query "SELECT EXISTS(SELECT * FROM pg_available_extensions WHERE name = '#{name}' AND installed_version IS NOT NULL) as enabled",
'SCHEMA'
res.column_types['enabled'].type_cast res.rows.first.first
res.column_types['enabled'].type_cast_from_database res.rows.first.first
end
end
def extensions
if supports_extensions?
res = exec_query "SELECT extname from pg_extension", "SCHEMA"
res.rows.map { |r| res.column_types['extname'].type_cast r.first }
res.rows.map { |r| res.column_types['extname'].type_cast_from_database r.first }
else
super
end
......
......@@ -516,7 +516,7 @@ def assign_to_or_mark_for_destruction(record, attributes, allow_destroy)
# Determines if a hash contains a truthy _destroy key.
def has_destroy_flag?(hash)
Type::Boolean.new.type_cast(hash['_destroy'])
Type::Boolean.new.type_cast_from_user(hash['_destroy'])
end
# Determines if a new record should be rejected by checking
......
......@@ -179,7 +179,7 @@ def pluck(*column_names)
result = result.map do |attributes|
values = attributes.values
columns.zip(values).map { |column, value| column.type_cast value }
columns.zip(values).map { |column, value| column.type_cast_from_database value }
end
columns.one? ? result.map!(&:first) : result
end
......@@ -379,7 +379,7 @@ def type_cast_calculated_value(value, column, operation = nil)
end
def type_cast_using_column(value, column)
column ? column.type_cast(value) : value
column ? column.type_cast_from_database(value) : value
end
# TODO: refactor to allow non-string `select_values` (eg. Arel nodes).
......
......@@ -9,7 +9,7 @@ def initialize(subtype, coder)
super(subtype)
end
def type_cast(value)
def type_cast_from_database(value)
if is_default_value?(value)
value
else
......@@ -18,7 +18,7 @@ def type_cast(value)
end
def type_cast_from_user(value)
type_cast(type_cast_for_database(value))
type_cast_from_database(type_cast_for_database(value))
end
def type_cast_for_database(value)
......
......@@ -16,11 +16,8 @@ def initialize(options = {})
# must 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?
def type_cast_from_database(value)
type_cast(value)
end
def type_cast_from_user(value)
......@@ -64,6 +61,12 @@ def changed?(old_value, new_value, _new_value_before_type_cast) # :nodoc:
end
private
# 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) # :api: public
cast_value(value) unless value.nil?
end
# Responsible for casting values from external sources to the appropriate
# type. Called by `type_cast` for all values except `nil`.
......
......@@ -105,7 +105,7 @@ def test_tinyint_integer_typecasting
result = @conn.exec_query('SELECT status FROM ex')
assert_equal 2, result.column_types['status'].type_cast(result.last['status'])
assert_equal 2, result.column_types['status'].type_cast_from_database(result.last['status'])
end
end
......
......@@ -90,9 +90,9 @@ def test_change_column_default_with_array
end
def test_type_cast_array
assert_equal(['1', '2', '3'], @column.type_cast('{1,2,3}'))
assert_equal([], @column.type_cast('{}'))
assert_equal([nil], @column.type_cast('{NULL}'))
assert_equal(['1', '2', '3'], @column.type_cast_from_database('{1,2,3}'))
assert_equal([], @column.type_cast_from_database('{}'))
assert_equal([nil], @column.type_cast_from_database('{NULL}'))
end
def test_type_cast_integers
......
......@@ -33,16 +33,16 @@ def test_type_cast_binary_converts_the_encoding
data = "\u001F\x8B"
assert_equal('UTF-8', data.encoding.name)
assert_equal('ASCII-8BIT', @column.type_cast(data).encoding.name)
assert_equal('ASCII-8BIT', @column.type_cast_from_database(data).encoding.name)
end
def test_type_cast_binary_value
data = "\u001F\x8B".force_encoding("BINARY")
assert_equal(data, @column.type_cast(data))
assert_equal(data, @column.type_cast_from_database(data))
end
def test_type_case_nil
assert_equal(nil, @column.type_cast(nil))
assert_equal(nil, @column.type_cast_from_database(nil))
end
def test_read_value
......
......@@ -121,7 +121,7 @@ def test_statement_key_is_logged
name = @subscriber.payloads.last[:statement_name]
assert name
res = @connection.exec_query("EXPLAIN (FORMAT JSON) EXECUTE #{name}(#{bindval})")
plan = res.column_types['QUERY PLAN'].type_cast res.rows.first.first
plan = res.column_types['QUERY PLAN'].type_cast_from_database res.rows.first.first
assert_operator plan.length, :>, 0
end
......
......@@ -118,11 +118,11 @@ def test_type_cast_hstore
data = "\"1\"=>\"2\""
hash = @column.class.string_to_hstore data
assert_equal({'1' => '2'}, hash)
assert_equal({'1' => '2'}, @column.type_cast(data))
assert_equal({'1' => '2'}, @column.type_cast_from_database(data))
assert_equal({}, @column.type_cast(""))
assert_equal({'key'=>nil}, @column.type_cast('key => NULL'))
assert_equal({'c'=>'}','"a"'=>'b "a b'}, @column.type_cast(%q(c=>"}", "\"a\""=>"b \"a b")))
assert_equal({}, @column.type_cast_from_database(""))
assert_equal({'key'=>nil}, @column.type_cast_from_database('key => NULL'))
assert_equal({'c'=>'}','"a"'=>'b "a b'}, @column.type_cast_from_database(%q(c=>"}", "\"a\""=>"b \"a b")))
end
def test_with_store_accessors
......@@ -180,31 +180,31 @@ def test_gen4
end
def test_parse1
assert_equal({'a'=>nil,'b'=>nil,'c'=>'NuLl','null'=>'c'}, @column.type_cast('a=>null,b=>NuLl,c=>"NuLl",null=>c'))
assert_equal({'a'=>nil,'b'=>nil,'c'=>'NuLl','null'=>'c'}, @column.type_cast_from_database('a=>null,b=>NuLl,c=>"NuLl",null=>c'))
end
def test_parse2
assert_equal({" " => " "}, @column.type_cast("\\ =>\\ "))
assert_equal({" " => " "}, @column.type_cast_from_database("\\ =>\\ "))
end
def test_parse3
assert_equal({"=" => ">"}, @column.type_cast("==>>"))
assert_equal({"=" => ">"}, @column.type_cast_from_database("==>>"))
end
def test_parse4
assert_equal({"=a"=>"q=w"}, @column.type_cast('\=a=>q=w'))
assert_equal({"=a"=>"q=w"}, @column.type_cast_from_database('\=a=>q=w'))
end
def test_parse5
assert_equal({"=a"=>"q=w"}, @column.type_cast('"=a"=>q\=w'))
assert_equal({"=a"=>"q=w"}, @column.type_cast_from_database('"=a"=>q\=w'))
end
def test_parse6
assert_equal({"\"a"=>"q>w"}, @column.type_cast('"\"a"=>q>w'))
assert_equal({"\"a"=>"q>w"}, @column.type_cast_from_database('"\"a"=>q>w'))
end
def test_parse7
assert_equal({"\"a"=>"q\"w"}, @column.type_cast('\"a=>q"w'))
assert_equal({"\"a"=>"q\"w"}, @column.type_cast_from_database('\"a=>q"w'))
end
def test_rewrite
......
......@@ -80,11 +80,11 @@ def test_type_cast_json
data = "{\"a_key\":\"a_value\"}"
hash = column.class.string_to_json data
assert_equal({'a_key' => 'a_value'}, hash)
assert_equal({'a_key' => 'a_value'}, column.type_cast(data))
assert_equal({'a_key' => 'a_value'}, column.type_cast_from_database(data))
assert_equal({}, column.type_cast("{}"))
assert_equal({'key'=>nil}, column.type_cast('{"key": null}'))
assert_equal({'c'=>'}','"a"'=>'b "a b'}, column.type_cast(%q({"c":"}", "\"a\"":"b \"a b"})))
assert_equal({}, column.type_cast_from_database("{}"))
assert_equal({'key'=>nil}, column.type_cast_from_database('{"key": null}'))
assert_equal({'c'=>'}','"a"'=>'b "a b'}, column.type_cast_from_database(%q({"c":"}", "\"a\"":"b \"a b"})))
end
def test_rewrite
......
......@@ -49,10 +49,10 @@ def test_money_values
def test_money_type_cast
column = PostgresqlMoney.columns_hash['wealth']
assert_equal(12345678.12, column.type_cast("$12,345,678.12"))
assert_equal(12345678.12, column.type_cast("$12.345.678,12"))
assert_equal(-1.15, column.type_cast("-$1.15"))
assert_equal(-2.25, column.type_cast("($2.25)"))
assert_equal(12345678.12, column.type_cast_from_user("$12,345,678.12"))
assert_equal(12345678.12, column.type_cast_from_user("$12.345.678,12"))
assert_equal(-1.15, column.type_cast_from_user("-$1.15"))
assert_equal(-2.25, column.type_cast_from_user("($2.25)"))
end
def test_schema_dumping
......
......@@ -12,11 +12,11 @@ def initialize(delegate, decoration = "decorated!")
super(delegate)
end
def type_cast(value)
def type_cast_from_user(value)
"#{super} #{@decoration}"
end
alias type_cast_from_user type_cast
alias type_cast_from_database type_cast_from_user
end
setup do
......
......@@ -1489,7 +1489,7 @@ def test_column_types_typecast
attrs.delete 'id'
typecast = Class.new {
def type_cast value
def type_cast_from_database value
"t.lo"
end
}
......
......@@ -85,7 +85,7 @@ def test_decimal_without_scale
cast_type = @connection.type_map.lookup(type)
assert_equal :decimal, cast_type.type
assert_equal 2, cast_type.type_cast(2.1)
assert_equal 2, cast_type.type_cast_from_user(2.1)
end
end
......
......@@ -95,7 +95,7 @@ def test_non_existent_columns_are_identity_types
column = @first.column_for_attribute("attribute_that_doesnt_exist")
object = Object.new
assert_equal object, column.type_cast(object)
assert_equal object, column.type_cast_from_database(object)
assert_equal object, column.type_cast_from_user(object)
assert_equal object, column.type_cast_for_database(object)
end
......
......@@ -6,141 +6,141 @@ module ConnectionAdapters
class TypesTest < ActiveRecord::TestCase
def test_type_cast_boolean
type = Type::Boolean.new
assert type.type_cast('').nil?
assert type.type_cast(nil).nil?
assert type.type_cast(true)
assert type.type_cast(1)
assert type.type_cast('1')
assert type.type_cast('t')
assert type.type_cast('T')
assert type.type_cast('true')
assert type.type_cast('TRUE')
assert type.type_cast('on')
assert type.type_cast('ON')
assert type.type_cast_from_user('').nil?
assert type.type_cast_from_user(nil).nil?
assert type.type_cast_from_user(true)
assert type.type_cast_from_user(1)
assert type.type_cast_from_user('1')
assert type.type_cast_from_user('t')
assert type.type_cast_from_user('T')
assert type.type_cast_from_user('true')
assert type.type_cast_from_user('TRUE')
assert type.type_cast_from_user('on')
assert type.type_cast_from_user('ON')
# explicitly check for false vs nil
assert_equal false, type.type_cast(false)
assert_equal false, type.type_cast(0)
assert_equal false, type.type_cast('0')
assert_equal false, type.type_cast('f')
assert_equal false, type.type_cast('F')
assert_equal false, type.type_cast('false')
assert_equal false, type.type_cast('FALSE')
assert_equal false, type.type_cast('off')
assert_equal false, type.type_cast('OFF')
assert_equal false, type.type_cast(' ')
assert_equal false, type.type_cast("\u3000\r\n")
assert_equal false, type.type_cast("\u0000")
assert_equal false, type.type_cast('SOMETHING RANDOM')
assert_equal false, type.type_cast_from_user(false)
assert_equal false, type.type_cast_from_user(0)
assert_equal false, type.type_cast_from_user('0')
assert_equal false, type.type_cast_from_user('f')
assert_equal false, type.type_cast_from_user('F')
assert_equal false, type.type_cast_from_user('false')
assert_equal false, type.type_cast_from_user('FALSE')
assert_equal false, type.type_cast_from_user('off')
assert_equal false, type.type_cast_from_user('OFF')
assert_equal false, type.type_cast_from_user(' ')
assert_equal false, type.type_cast_from_user("\u3000\r\n")
assert_equal false, type.type_cast_from_user("\u0000")
assert_equal false, type.type_cast_from_user('SOMETHING RANDOM')
end
def test_type_cast_string
type = Type::String.new
assert_equal "1", type.type_cast(true)
assert_equal "0", type.type_cast(false)
assert_equal "123", type.type_cast(123)
assert_equal "1", type.type_cast_from_user(true)
assert_equal "0", type.type_cast_from_user(false)
assert_equal "123", type.type_cast_from_user(123)
end
def test_type_cast_integer
type = Type::Integer.new
assert_equal 1, type.type_cast(1)
assert_equal 1, type.type_cast('1')
assert_equal 1, type.type_cast('1ignore')
assert_equal 0, type.type_cast('bad1')
assert_equal 0, type.type_cast('bad')
assert_equal 1, type.type_cast(1.7)
assert_equal 0, type.type_cast(false)
assert_equal 1, type.type_cast(true)
assert_nil type.type_cast(nil)
assert_equal 1, type.type_cast_from_user(1)
assert_equal 1, type.type_cast_from_user('1')
assert_equal 1, type.type_cast_from_user('1ignore')
assert_equal 0, type.type_cast_from_user('bad1')
assert_equal 0, type.type_cast_from_user('bad')
assert_equal 1, type.type_cast_from_user(1.7)
assert_equal 0, type.type_cast_from_user(false)
assert_equal 1, type.type_cast_from_user(true)
assert_nil type.type_cast_from_user(nil)
end
def test_type_cast_non_integer_to_integer
type = Type::Integer.new
assert_nil type.type_cast([1,2])
assert_nil type.type_cast({1 => 2})
assert_nil type.type_cast((1..2))
assert_nil type.type_cast_from_user([1,2])
assert_nil type.type_cast_from_user({1 => 2})
assert_nil type.type_cast_from_user((1..2))
end
def test_type_cast_activerecord_to_integer
type = Type::Integer.new
firm = Firm.create(:name => 'Apple')
assert_nil type.type_cast(firm)
assert_nil type.type_cast_from_user(firm)
end
def test_type_cast_object_without_to_i_to_integer
type = Type::Integer.new
assert_nil type.type_cast(Object.new)
assert_nil type.type_cast_from_user(Object.new)
end
def test_type_cast_nan_and_infinity_to_integer
type = Type::Integer.new
assert_nil type.type_cast(Float::NAN)
assert_nil type.type_cast(1.0/0.0)
assert_nil type.type_cast_from_user(Float::NAN)
assert_nil type.type_cast_from_user(1.0/0.0)
end
def test_type_cast_float
type = Type::Float.new
assert_equal 1.0, type.type_cast("1")
assert_equal 1.0, type.type_cast_from_user("1")
end
def test_type_cast_decimal
type = Type::Decimal.new
assert_equal BigDecimal.new("0"), type.type_cast(BigDecimal.new("0"))
assert_equal BigDecimal.new("123"), type.type_cast(123.0)
assert_equal BigDecimal.new("1"), type.type_cast(:"1")
assert_equal BigDecimal.new("0"), type.type_cast_from_user(BigDecimal.new("0"))
assert_equal BigDecimal.new("123"), type.type_cast_from_user(123.0)
assert_equal BigDecimal.new("1"), type.type_cast_from_user(:"1")
end
def test_type_cast_binary
type = Type::Binary.new
assert_equal nil, type.type_cast(nil)
assert_equal "1", type.type_cast("1")
assert_equal 1, type.type_cast(1)
assert_equal nil, type.type_cast_from_user(nil)
assert_equal "1", type.type_cast_from_user("1")
assert_equal 1, type.type_cast_from_user(1)
end
def test_type_cast_time
type = Type::Time.new
assert_equal nil, type.type_cast(nil)
assert_equal nil, type.type_cast('')
assert_equal nil, type.type_cast('ABC')
assert_equal nil, type.type_cast_from_user(nil)
assert_equal nil, type.type_cast_from_user('')
assert_equal nil, type.type_cast_from_user('ABC')
time_string = Time.now.utc.strftime("%T")
assert_equal time_string, type.type_cast(time_string).strftime("%T")
assert_equal time_string, type.type_cast_from_user(time_string).strftime("%T")
end
def test_type_cast_datetime_and_timestamp
type = Type::DateTime.new
assert_equal nil, type.type_cast(nil)
assert_equal nil, type.type_cast('')
assert_equal nil, type.type_cast(' ')
assert_equal nil, type.type_cast('ABC')
assert_equal nil, type.type_cast_from_user(nil)
assert_equal nil, type.type_cast_from_user('')
assert_equal nil, type.type_cast_from_user(' ')
assert_equal nil, type.type_cast_from_user('ABC')
datetime_string = Time.now.utc.strftime("%FT%T")
assert_equal datetime_string, type.type_cast(datetime_string).strftime("%FT%T")
assert_equal datetime_string, type.type_cast_from_user(datetime_string).strftime("%FT%T")
end
def test_type_cast_date
type = Type::Date.new
assert_equal nil, type.type_cast(nil)
assert_equal nil, type.type_cast('')
assert_equal nil, type.type_cast(' ')
assert_equal nil, type.type_cast('ABC')
assert_equal nil, type.type_cast_from_user(nil)
assert_equal nil, type.type_cast_from_user('')
assert_equal nil, type.type_cast_from_user(' ')
assert_equal nil, type.type_cast_from_user('ABC')
date_string = Time.now.utc.strftime("%F")
assert_equal date_string, type.type_cast(date_string).strftime("%F")
assert_equal date_string, type.type_cast_from_user(date_string).strftime("%F")
end
def test_type_cast_duration_to_integer
type = Type::Integer.new
assert_equal 1800, type.type_cast(30.minutes)
assert_equal 7200, type.type_cast(2.hours)
assert_equal 1800, type.type_cast_from_user(30.minutes)
assert_equal 7200, type.type_cast_from_user(2.hours)
end
def test_string_to_time_with_timezone
[:utc, :local].each do |zone|
with_timezone_config default: zone do
type = Type::DateTime.new
assert_equal Time.utc(2013, 9, 4, 0, 0, 0), type.type_cast("Wed, 04 Sep 2013 03:00:00 EAT")
assert_equal Time.utc(2013, 9, 4, 0, 0, 0), type.type_cast_from_user("Wed, 04 Sep 2013 03:00:00 EAT")
end
end
end
......@@ -149,7 +149,7 @@ def test_string_to_time_with_timezone
def test_binary_encoding
type = SQLite3Binary.new
utf8_string = "a string".encode(Encoding::UTF_8)
type_cast = type.type_cast(utf8_string)
type_cast = type.type_cast_from_user(utf8_string)
assert_equal Encoding::ASCII_8BIT, type_cast.encoding
end
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册