Allow AR::Enum definitions with boolean values

If `AR::Enum` is used for boolean field, it would be not expected
behavior for us.

fixes #38075

Problem:

In case of using boolean for enum, we can set with string (hash key)
to instance, but we cannot set with actual value (hash value).

```ruby
class Post < ActiveRecord::Base
  enum status: { enabled: true, disabled: false }
end

post.status = 'enabled'
post.status # 'enabled'

post.status = true
post.status # 'enabled'

post.status = 'disabled'
post.status # 'disabled'

post.status = false
post.status # nil (This is not expected behavior)
```

After looking into `AR::Enum::EnumType#cast`, I found that `blank?`
method converts from false value to nil (it seems it may not intentional behavior).

In this patch, I improved that if it defines enum with boolean,
it returns reasonable behavior.
This commit is contained in:
Yoshiyuki Hirano 2019-12-23 21:11:07 -10:00
parent 0b3c710d35
commit f4fbdb1b4e
5 changed files with 15 additions and 2 deletions

@ -123,12 +123,12 @@ def initialize(name, mapping, subtype)
end
def cast(value)
return if value.blank?
if mapping.has_key?(value)
value.to_s
elsif mapping.has_value?(value)
mapping.key(value)
elsif value.blank?
nil
else
assert_valid_value(value)
end

@ -236,6 +236,16 @@ class EnumTest < ActiveRecord::TestCase
assert_nil @book.status
end
test "assign false value to a field defined as not boolean" do
@book.status = false
assert_nil @book.status
end
test "assign false value to a field defined as boolean" do
@book.boolean_status = false
assert_equal "disabled", @book.boolean_status
end
test "assign long empty string value" do
@book.status = " "
assert_nil @book.status

@ -10,6 +10,7 @@ awdr:
illustrator_visibility: :visible
font_size: :medium
difficulty: :medium
boolean_status: :enabled
rfr:
author_id: 1

@ -18,6 +18,7 @@ class Book < ActiveRecord::Base
enum font_size: [:small, :medium, :large], _prefix: :with, _suffix: true
enum difficulty: [:easy, :medium, :hard], _suffix: :to_read
enum cover: { hard: "hard", soft: "soft" }
enum boolean_status: { enabled: true, disabled: false }
def published!
super

@ -117,6 +117,7 @@
t.column :cover, :string, default: "hard"
t.string :isbn, **case_sensitive_options
t.datetime :published_on
t.boolean :boolean_status
t.index [:author_id, :name], unique: true
t.index :isbn, where: "published_on IS NOT NULL", unique: true
end