Ruby on Rails 表单中的枚举选择映射值

Posted

技术标签:

【中文标题】Ruby on Rails 表单中的枚举选择映射值【英文标题】:Enums in Ruby on Rails Form Select Mapping Values 【发布时间】:2021-10-09 22:39:33 【问题描述】:

我的模型中有一个枚举如下:

 enum construction_type: 
    brick_block: "Brick/Block",
    concrete_slab: "Concrete/Slab",
    wood_steel: "Light Framed Wood/Steel",
    timber_steel: "Heavy Framed Timber/Steel"
  

在一个表单中,我使用此代码来获取枚举值以放入下拉列表中:

  <%= form.label(:construction_type, class: "form-label") %>
  <% options = options_for_select(Site.construction_types.map |key, value| [value, Site.construction_types.key(value)], form.object.construction_type) %>
  <%= form.select(:construction_type, options, include_blank: true) %>

虽然options_for_select 中的语句在Site.construction_types.values 产生相同的选项时似乎有点矫枉过正,但该字段仅在使用映射方法时在表单上提交无效后才会保持填充。

我发现的一个解决方案是将字符串硬编码为如下形式:

  <%= form.label(:construction_type, class: "form-label") %>
  <%= form.select(:construction_type, ["Brick/Block", "Concrete/Slab", "Light Framed Wood/Steel", "Heavy Framed Timber/Steel"], include_blank: true) %>

但是,我想避免这种解决方案,因为我有第二个表单用于编辑在这个表单中初始化的信息,我必须复制代码。模型中的枚举似乎是跟踪这些值的最佳方式。

我的数据库使用枚举中的值填充我想要的值,但是在我试图显示来自表单的信息的页面上,键出现了。

<li> <strong> <%= t(".construction_type") %> </strong> <%=@site.construction_type if @site.construction_type %> </li>

使用枚举版本,上面的代码产生以下结果: 建筑类型:砖块

与我想要的相反: 建筑类型:砖/块

有没有办法使用枚举方法解决这个问题?

【问题讨论】:

【参考方案1】:

模型中的枚举似乎是跟踪 这些值。

地狱没有。 ActiveRecord::Enum 旨在将整数或任何其他有效存储和索引的类型连接到开发人员可读标签。

当您将枚举定义为:

enum construction_type: 
    brick_block: "Brick/Block",
    concrete_slab: "Concrete/Slab",
    wood_steel: "Light Framed Wood/Steel",
    timber_steel: "Heavy Framed Timber/Steel"
  

您将在数据库中存储"Heavy Framed Timber/Steel" 作为值,这是一个非常糟糕的主意,因为如果您需要更改人类友好的标签,您会要求非规范化问题。不应期望枚举映射发生变化。

如果您真的想使用 Enum,请使用 I18n 模块来提供人类可读的版本:

# the name is just an assumption
class Building < ApplicationRecord
  enum construction_type: 
    brick_block: 0,
    concrete_slab: 1,
    wood_steel: 2,
    timber_steel: 3
  
end
module BuildingsHelper
  def construction_type_options
     Building.construction_types.keys do |key|
       [key, t("activerecord.models.buildings.construction_types.# key ")]
     end
  end
end

但一个不那么老套的选择是使用单独的表/模型:

class Building
  belongs_to :construction_type
end

class ConstructionType
  has_many :buildings
end
<%= form_with(model: @buildling) do |form| %>
  <%= form.collection_select :construction_type_id, 
    ConstructionType.all,
    :id,
    :description
  %>
<% end %>

【讨论】:

以上是关于Ruby on Rails 表单中的枚举选择映射值的主要内容,如果未能解决你的问题,请参考以下文章

Ruby on Rails 表单中的 select 和 onChange

Ruby on Rails 表单添加带有文本框的“其他”选项以选择下拉菜单

通过单击 Ruby on Rails 中的按钮生成表单

Ruby on rails:按键查找值的函数

如何使用用户定义的字段数制作表单? - Ruby on Rails

Ruby on Rails 3 表单中的 _snowman 参数有啥用?