ActiveAdmin和Formtastic:显示单选按钮的值并使用ENUM选择框

时间:2015-01-11 19:59:59

标签: ruby-on-rails enums activeadmin formtastic

我正在使用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

这在创建新资源时可以正常工作,但在使用表单编辑同一资源时不会检索该值。


这是数据库记录的默认“奇异视图”:

The singular view

这是同一记录的默认“编辑视图”。注意没有选择任何值:

The edit view

2 个答案:

答案 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的枚举。原因如下:

  • 它代表一个有意义的字符串,带有无意义的数字(这意味着没有应用程序代码,单位列中的数据将没有任何意义)
  • 它将应用程序的源紧密地耦合到数据(在其他应用程序(例如db控制台)中很难单独使用数据)
  • 必须维护枚举值的顺序(或者必须提供显式映射)。他们都不是开发人员友好的。

使用预定义的字符串数组并验证该值是否在预定义值列表中是更好的选择。一些事情:

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