【问题标题】:Possibility of mapping enum values to string type instead of integer将枚举值映射到字符串类型而不是整数的可能性
【发布时间】:2014-07-29 03:20:54
【问题描述】:

枚举属性很棒,我想使用它们。但是将枚举值映射到整数会使代码和数据库都难以维护。此外,我的数据库将与我的代码高度耦合,我认为我应该认为这是一件坏事。

我知道我可以使用散列来组织带有键/值对的枚举属性,但是能够使用数组并映射到数据库中的字符串值仍然会好得多。

默认情况下有没有办法将枚举映射到字符串?

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-4 enumeration


    【解决方案1】:

    查看枚举的代码,您可以这样做(至少在 4.1+ 中):https://github.com/rails/rails/blob/master/activerecord/lib/active_record/enum.rb#L96-98 通过传递哈希,例如:

    class Foo
      enum name: {
        foo: 'myfoo',
        bar: 'mybar'
      }
    

    虽然访问时出现意外结果,请参阅https://github.com/rails/rails/issues/16459

    foo_instance.foo!
    foo_instance.name
    => "foo"
    foo_instance[:name]
    => "myfoo"
    

    更新

    此问题已在 Rails 5 中修复,请参阅 https://github.com/rails/rails/commit/c51f9b61ce1e167f5f58f07441adcfa117694301。谢谢尤里。

    【讨论】:

    【解决方案2】:

    据我所知,使用 Active Record 的内置枚举功能是不可能的。但是,有一些流行的 3rd 方宝石可以做到这一点。与 Active Record 最接近的匹配可能是 enumerizeSimpleEnum

    但是,如果您正在寻找一些不同的东西,我推荐ClassyEnum(完全披露:我写的)。以下是 some of my notes 关于 enumerize 和 SimpleEnum 与 ClassyEnum 的区别:

    无类枚举(enumerize、SimpleEnum)非常适合简单使用 您只需要一个字段来表示一组固定的一组 价值观。我对这个解决方案的主要问题是它鼓励 分散在你的模型、控制器和视图中的条件。 使用这些宝石很诱人,因为它们是最简单的 实施,但长期的回报就是没有任何东西IMO 但最简单的情况。

    ClassyEnum 旨在解决分散的问题 与不同枚举相关的条件逻辑。你仍然可以使用它 对于没有逻辑的简单集合,但当你确实需要时 添加逻辑(你几乎肯定会),你可以把它推到 单独的枚举类并利用多态性。

    【讨论】:

      【解决方案3】:

      似乎仅使用 Rails 5 API,模型的枚举属性将保存在数据库中作为整数,但将在公共 API 中发布作为字符串 (使用 ActiveModel::Serializer)。

      例如,

      文章型号:

      class Article < ApplicationRecord
        enum status: [ :visible, :hidden ]
      end
      

      文章序列化器:

      class ArticleSerializer < ActiveModel::Serializer
        attributes :id, :status, :title, :body
      end
      

      将发布以下json:

      {
        "id": "1",
        "type": "articles",
        "attributes": {
          "status": "visible",
          "title": "Enums are passed as string in a json API render",
          "body": "Great!",
      }
      

      【讨论】:

      • 这正是我所需要的,但序列化程序和 JSON 输出之间似乎存在差距。文章/id 和属性值之间的映射在哪里找到位置?
      【解决方案4】:

      怎么样:

      class Foo < ApplicationRecord
        NAMES = [
          :foo,
          :bar
        ]
      
        enum names: NAMES.zip(NAMES).to_h
      end
      

      【讨论】:

        【解决方案5】:

        简短的回答是否定的。如果您想要做任何事情而不是存储整数,则需要使用 gem(例如 magic-enum)。

        the pull request that added this feature 上的 cmets 用 DHH 自己的话说:

        将枚举存储为文本是非常低效的。您将一遍又一遍地重复相同的文本。我认为这是一种反模式。如果人们想使用它,最好迁移到整数。

        【讨论】:

        • DHH 还说“我很高兴看到这得到数据库枚举的支持。”这更接近于使用字符串而不是整数。但不确定是否发生过任何事情。
        • DHH 有道理,但我不会考虑使用 -ambiguous and hard to maintain- 整数,而不是一遍又一遍地重复相同的 - 有意义且易于维护的字符串。
        • 考虑到布尔值通常存储为字符,因此存储字符串并没有那么遥远。
        • 哈!他太虚伪了。那么为什么 DHH 不实现整数支持的多态关联呢? type: 'CompanyAddress' 占用了大量空间......
        • 考虑到多态关联的想法...您将如何确保字符串的顺序(以及它们的整数值)不会改变?这就是他不这样做的原因。
        猜你喜欢
        • 2021-11-09
        • 2019-04-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多