我正在使用ActiveAdmin来管理一个大型数据库,我的一个模型(ItemType)有一个ENUM属性(ItemType.units),我可以使用Formtastic渲染一个选择框和单选按钮,如下所示:
f.input :unit, :as => :radio, :collection => ItemType.units, include_blank: false
ENUM字段在模型中定义如下:
class ItemType < ActiveRecord::Base
enum unit: [ :Packages, :Pieces, :KG ]
end
这在创建新资源时可以正常工作,但在使用表单编辑同一资源时不会检索该值。
这是数据库记录的默认“奇异视图”:
这是同一记录的默认“编辑视图”。注意没有选择任何值:
答案 0 :(得分:4)
当您声明枚举然后访问映射时,它会返回一个哈希:
ItemType.units #=> { "Packages" => 0, "Pieces" => 1, "KG" => 2 }
当您将其用作无线电输入的集合时,它会将输入值设置为0,1,2等。该值与ItemType#unit
的返回值不匹配(因为它将返回枚举的字符串表示形式,例如"KG"
)。
当列表中的某个值与属性值匹配时,Rails只能设置所选值。在这种情况下,这种情况永远不会发生。
这种二元性(字符串与整数)将导致另一个痛点。您实际上无法保存表单,因为您只能将枚举值设置为允许值之一(字符串或整数表示)。
it = ItemType.new
it.unit = "KG" # this works
it.unit = :KG # this works as well
it.unit = 1 # this works but WTF?!
it.unit = "1" # this will raise an ArgumentError
由于表单参数被解析为字符串,ActiveAdmin将尝试将"1"
分配给ItemType#unit
,它将失败。
解决方案实际上非常简单。仅使用映射中的键:
f.input :unit, :as => :radio, :collection => ItemType.units.keys
虽然如果可以,你应该远离使用AR的枚举。原因如下:
使用预定义的字符串数组并验证该值是否在预定义值列表中是更好的选择。一些事情:
class ItemType
UNITS = %w[kg packages pieces]
validates :unit, inclusion: { in: UNITS }
end
答案 1 :(得分:0)
我会使用常量而不是枚举:
class ItemType < ActiveRecord::Base
UNIT_VALUES = %w{Packages Pieces KG}
end
f.input :units, :as => :radio, :collection => ItemType::UNIT_VALUES, include_blank: false