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

时间:2014-06-08 11:48:14

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

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

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

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

5 个答案:

答案 0 :(得分:21)

查看枚举的代码,您可以通过传递哈希来执行此操作(至少在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'
  }

Altough在访问时会出现意外结果,请参阅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。谢谢Yuri。

答案 1 :(得分:8)

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

然而,如果你正在寻找一些不同的东西,我建议ClassyEnum(完全披露:我写了它)。以下是关于enumerize和SimpleEnum与ClassyEnum之间差异的some of my notes

  

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

     

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

答案 2 :(得分:5)

怎么样:

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

  enum names: NAMES.zip(NAMES).to_h
end

答案 3 :(得分:5)

似乎仅使用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!",
}

答案 4 :(得分:4)

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

DHH自己对the pull request that added this feature的评论中所说的话:

  

将枚举存储为文本效率非常低。你将一遍又一遍地重复相同的文字。我认为这是一种反模式。如果他们想要使用它,人们最好转移到int。