diff options
author | Sean Griffin <sean@thoughtbot.com> | 2014-11-09 20:38:40 -0700 |
---|---|---|
committer | Sean Griffin <sean@thoughtbot.com> | 2014-11-09 20:42:36 -0700 |
commit | 52c3a16fa07cde643af3c2200e4b87bcb470eb12 (patch) | |
tree | 9198c2872f832080d0d32e263cfe1e2ddd8dd4cb /activerecord | |
parent | cb0ba2f2b144d15e825cf890ea9bc7e322d25349 (diff) | |
download | rails-52c3a16fa07cde643af3c2200e4b87bcb470eb12.tar.gz rails-52c3a16fa07cde643af3c2200e4b87bcb470eb12.tar.bz2 rails-52c3a16fa07cde643af3c2200e4b87bcb470eb12.zip |
Revert the behavior of booleans in string columns to that of 4.1
Why are people assigning booleans to string columns? >_>
We unintentionally changed the behavior on Sqlite3 and PostgreSQL.
Boolean values should cast to the database's representation of true and
false. This is 't' and 'f' by default, and "1" and "0" on Mysql. The
implementation to make the connection adapter specific behavior is hacky
at best, and should be re-visted once we decide how we actually want to
separate the concerns related to things that should change based on the
database adapter.
That said, this isn't something I'd expect to change based on my
database adapter. We're storing a string, so the way the database
represents a boolean should be irrelevant. It also seems strange for us
to give booleans special behavior at all in string columns. Why is
`to_s` not sufficient? It's inconsistent and confusing. Perhaps we
should consider deprecating in the future.
Fixes #17571
Diffstat (limited to 'activerecord')
3 files changed, 29 insertions, 7 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb index 5f512758e9..26015528e5 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -648,6 +648,8 @@ module ActiveRecord def initialize_type_map(m) # :nodoc: super + register_class_with_limit m, %r(char)i, MysqlString + m.register_type %r(tinytext)i, Type::Text.new(limit: 2**8 - 1) m.register_type %r(tinyblob)i, Type::Binary.new(limit: 2**8 - 1) m.register_type %r(text)i, Type::Text.new(limit: 2**16 - 1) @@ -672,7 +674,7 @@ module ActiveRecord m.register_type(%r(enum)i) do |sql_type| limit = sql_type[/^enum\((.+)\)/i, 1] .split(',').map{|enum| enum.strip.length - 2}.max - Type::String.new(limit: limit) + MysqlString.new(limit: limit) end end @@ -847,6 +849,26 @@ module ActiveRecord end end end + + class MysqlString < Type::String # :nodoc: + def type_cast_for_database(value) + case value + when true then "1" + when false then "0" + else super + end + end + + private + + def cast_value(value) + case value + when true then "1" + when false then "0" + else super + end + end + end end end end diff --git a/activerecord/lib/active_record/type/string.rb b/activerecord/lib/active_record/type/string.rb index 150defb106..fbc0af2c5a 100644 --- a/activerecord/lib/active_record/type/string.rb +++ b/activerecord/lib/active_record/type/string.rb @@ -15,8 +15,8 @@ module ActiveRecord case value when ::Numeric, ActiveSupport::Duration then value.to_s when ::String then ::String.new(value) - when true then "1" - when false then "0" + when true then "t" + when false then "f" else super end end @@ -25,8 +25,8 @@ module ActiveRecord def cast_value(value) case value - when true then "1" - when false then "0" + when true then "t" + when false then "f" # String.new is slightly faster than dup else ::String.new(value.to_s) end diff --git a/activerecord/test/cases/type/string_test.rb b/activerecord/test/cases/type/string_test.rb index 420177ed49..4d78f287f1 100644 --- a/activerecord/test/cases/type/string_test.rb +++ b/activerecord/test/cases/type/string_test.rb @@ -4,8 +4,8 @@ module ActiveRecord class StringTypeTest < ActiveRecord::TestCase test "type casting" do type = Type::String.new - assert_equal "1", type.type_cast_from_user(true) - assert_equal "0", type.type_cast_from_user(false) + assert_equal "t", type.type_cast_from_user(true) + assert_equal "f", type.type_cast_from_user(false) assert_equal "123", type.type_cast_from_user(123) end |