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

问题描述 投票:0回答:2

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

 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> <%[email protected]_type if @site.construction_type %> </li>

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

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

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

ruby-on-rails forms drop-down-menu enums
2个回答
2
投票

模型中的枚举似乎是跟踪的最佳方式 这些值。

天哪。 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 %>

0
投票

根据第一个答案添加更新,枚举现在声明如下:

class Building < ApplicationRecord
  enum :construction_type, [:brick_block, 
                            :concrete_slab, 
                            :wood_steel, 
                            :timber_steel]
end

对于帮助者:

module BuildingsHelper
  def construction_type_options
    Building.construction_types.map do |key, _v|
      [t("enums.building.construction_types.#{key}"), key]
    end
  end
end

这是由于枚举定义的新格式。

我还更改了 I18n 模块,en.yml:

en:
  enums:
    building:
      construction_types:
        brick_block: "brick block"
        concrete_slab: "concrete slab"
        wood_steel: "wood steel"
        timber_steel: "timber steel"
© www.soinside.com 2019 - 2024. All rights reserved.