枚举属性很棒,我想使用它们。但是将枚举值映射到整数将使得难以维护代码和数据库。此外,我的数据库将与我的代码高度耦合,我认为我应该认为这是一件坏事。
我知道我可以使用哈希来组织带有键/值对的枚举属性,但是能够使用数组并映射到数据库中的字符串值仍然会好得多。
默认情况下有没有办法将枚举映射到字符串?
答案 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最接近的匹配可能是enumerize和SimpleEnum。
然而,如果你正在寻找一些不同的东西,我建议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。