将枚举值映射到字符串类型而不是整数的可能性

Ere*_*CAY 20 enumeration ruby-on-rails ruby-on-rails-4

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

我知道我可以使用哈希来组织具有键/值对的枚举属性,但是仍然能够使用数组并映射到数据库中的字符串值会更好.

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

Mih*_*van 23

:看,枚举的代码,你可以这样做(至少在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'
  }
Run Code Online (Sandbox Code Playgroud)

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

foo_instance.foo!
foo_instance.name
=> "foo"
foo_instance[:name]
=> "myfoo"
Run Code Online (Sandbox Code Playgroud)

更新

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


Pet*_*own 8

据我所知,Active Record的内置枚举功能无法实现.但是,有一些流行的第三方宝石可以做到这一点.与Active Record最接近的匹配可能是枚举SimpleEnum.

但是,如果你正在寻找一些不同的东西,我会推荐ClassyEnum(完全披露:我写了它).以下是关于enumerize和SimpleEnum与ClassyEnum之间区别的一些注释:

无类枚举(enumerize,SimpleEnum)非常适用于简单的用例,您只需要一个字段来表示一组固定的值.我对此解决方案的主要问题是它鼓励分散在整个模型,控制器和视图中的条件.使用这些宝石是很诱人的,因为它们是最简单的实现,但长期的收益并不是IMO,除了最简单的情况.

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


Jay*_*ley 5

怎么样:

class Foo < ApplicationRecord
  NAMES = [
    :foo,
    :bar
  ]

  enum names: NAMES.zip(NAMES).to_h
end
Run Code Online (Sandbox Code Playgroud)


Ben*_*dis 5

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

例如,

文章模型:

class Article < ApplicationRecord
  enum status: [ :visible, :hidden ]
end
Run Code Online (Sandbox Code Playgroud)

文章序列化器:

class ArticleSerializer < ActiveModel::Serializer
  attributes :id, :status, :title, :body
end
Run Code Online (Sandbox Code Playgroud)

将发布以下json:

{
  "id": "1",
  "type": "articles",
  "attributes": {
    "status": "visible",
    "title": "Enums are passed as string in a json API render",
    "body": "Great!",
}
Run Code Online (Sandbox Code Playgroud)