From 2d12f800f1c6b0a2018346e0139301070273e46f Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Fri, 29 Mar 2019 18:21:56 +0900 Subject: Type cast falsy boolean symbols on boolean attribute as false Before 34cc301, type casting by boolean attribute when querying is a no-op, so finding by truthy boolean string (i.e. `where(value: "true") # => value = 'true'`) didn't work as expected (matches it to FALSE in MySQL #32624). By type casting is ensured, a value on boolean attribute is always serialized to TRUE or FALSE. In PostgreSQL, `where(value: :false) # => value = 'false'` was a valid SQL, so 34cc301 is a regresson for PostgreSQL since all symbol values are serialized as TRUE. I'd say using `:false` is mostly a developer's mistake (user's input basically comes as a string), but `:false` on boolean attribute is serialized as TRUE is not a desirable behavior for anybody. This allows falsy boolean symbols as false, i.e. `klass.create(value: :false).value? # => false` and `where(value: :false) # => value = FALSE`. Fixes #35676. --- activemodel/CHANGELOG.md | 6 ++++++ activemodel/lib/active_model/type/boolean.rb | 11 ++++++++++- activemodel/test/cases/type/boolean_test.rb | 14 ++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) (limited to 'activemodel') diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md index 56fbfacbd7..51912ec3ce 100644 --- a/activemodel/CHANGELOG.md +++ b/activemodel/CHANGELOG.md @@ -1,3 +1,9 @@ +* Type cast falsy boolean symbols on boolean attribute as false. + + Fixes #35676. + + *Ryuta Kamizono* + * Change how validation error translation strings are fetched: The new behavior will first try the more specific keys, including doing locale fallback, then try the less specific ones. diff --git a/activemodel/lib/active_model/type/boolean.rb b/activemodel/lib/active_model/type/boolean.rb index f6c6efbc87..e64d2c793c 100644 --- a/activemodel/lib/active_model/type/boolean.rb +++ b/activemodel/lib/active_model/type/boolean.rb @@ -14,7 +14,16 @@ module ActiveModel # - Empty strings are coerced to +nil+ # - All other values will be coerced to +true+ class Boolean < Value - FALSE_VALUES = [false, 0, "0", "f", "F", "false", "FALSE", "off", "OFF"].to_set + FALSE_VALUES = [ + false, 0, + "0", :"0", + "f", :f, + "F", :F, + "false", :false, + "FALSE", :FALSE, + "off", :off, + "OFF", :OFF, + ].to_set.freeze def type # :nodoc: :boolean diff --git a/activemodel/test/cases/type/boolean_test.rb b/activemodel/test/cases/type/boolean_test.rb index 2de0f53640..7f8490b2fe 100644 --- a/activemodel/test/cases/type/boolean_test.rb +++ b/activemodel/test/cases/type/boolean_test.rb @@ -23,6 +23,13 @@ module ActiveModel assert type.cast("\u3000\r\n") assert type.cast("\u0000") assert type.cast("SOMETHING RANDOM") + assert type.cast(:"1") + assert type.cast(:t) + assert type.cast(:T) + assert type.cast(:true) + assert type.cast(:TRUE) + assert type.cast(:on) + assert type.cast(:ON) # explicitly check for false vs nil assert_equal false, type.cast(false) @@ -34,6 +41,13 @@ module ActiveModel assert_equal false, type.cast("FALSE") assert_equal false, type.cast("off") assert_equal false, type.cast("OFF") + assert_equal false, type.cast(:"0") + assert_equal false, type.cast(:f) + assert_equal false, type.cast(:F) + assert_equal false, type.cast(:false) + assert_equal false, type.cast(:FALSE) + assert_equal false, type.cast(:off) + assert_equal false, type.cast(:OFF) end end end -- cgit v1.2.3