【问题标题】:ActiveAdmin and Formtastic: Displaying the value for radio buttons and select boxes using ENUMActiveAdmin 和 Formtastic:使用 ENUM 显示单选按钮和选择框的值
【发布时间】:2015-03-09 14:20:18
【问题描述】:

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

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


这是数据库记录的默认“单一视图”:

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

【问题讨论】:

    标签: ruby-on-rails enums activeadmin formtastic


    【解决方案1】:

    当您声明一个枚举然后访问映射时,它会返回一个哈希:

    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
    

    【讨论】:

    • OP 不是在寻找关于枚举是否好用的建议,而是在寻找如何实现它们的建议。但是由于我们正在辩论:我发现如果您明智地使用枚举,枚举将非常有用,即始终使用散列形式将键显式映射到值(当然,编写规范以保证您不会更改键)。有关此主题的更多信息,我推荐这篇博文:bendyworks.com/blog/rails-enum-sharp-knife(Rails Enum 是一把锋利的刀)
    【解决方案2】:

    我会使用常量而不是枚举:

    class ItemType < ActiveRecord::Base
      UNIT_VALUES = %w{Packages Pieces KG}
    end
    
    f.input :units, :as => :radio, :collection => ItemType::UNIT_VALUES, include_blank: false
    

    【讨论】:

    • 这也是一样的。我正在寻找一种方法让 ActiveAdmin 在编辑表单中勾选正确的值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-12
    • 2013-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多