Ruby-on-rails 将枚举值映射到字符串类型而不是整数的可能性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24105813/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Possibility of mapping enum values to string type instead of integer
提问by Eren CAY
Enum attributes are great and I want to use them. But mapping enum values to integer would make it hard to maintain both code and database. Also my database would be highly coupled with my code which I think I should consider that a bad thing.
枚举属性很棒,我想使用它们。但是将枚举值映射到整数会使代码和数据库难以维护。此外,我的数据库将与我的代码高度耦合,我认为我应该认为这是一件坏事。
I know I can use a hash to organize an enum attribute with key/value pairs, but still it would be a lot better to be able to use an array and map to string values in database.
我知道我可以使用散列来组织具有键/值对的枚举属性,但是能够使用数组并映射到数据库中的字符串值仍然会好得多。
Is there any way to map enum to strings by default?
有没有办法默认将枚举映射到字符串?
采纳答案by Peter Brown
As far as I know it's not possible with Active Record's built-in enum functionality. However, there are a few popular 3rd party gems that do this. The closest match to what comes with Active Record are probably enumerizeand SimpleEnum.
据我所知,Active Record 的内置枚举功能是不可能的。但是,有一些流行的 3rd 方宝石可以做到这一点。最接近 Active Record 的可能是enumerize和SimpleEnum。
However, if you're looking for something a little different, I'd recommend ClassyEnum(full disclosure: I wrote it). Here are some of my noteson the difference between enumerize and SimpleEnum vs ClassyEnum:
但是,如果您正在寻找一些不同的东西,我会推荐ClassyEnum(完全披露:我写的)。以下是我关于 enumerize 和 SimpleEnum 与 ClassyEnum 之间区别的一些说明:
Class-less enums (enumerize, SimpleEnum) are great for simple use cases where you just need a field to represent one of a fixed set of values. The main issue I have with this solution is that it encourages conditionals scattered throughout your models, controllers and views. It's tempting to use these gems because they are the simplest to implement, but the long term payoff just isn't there IMO for anything but the simplest cases.
ClassyEnum was designed to solve the problem of having scattered conditional logic related to the different enums. You can still use it for simple collections that don't have logic, but when you do need to add logic (and you almost certainly will), you can push that into the individual enum classes and take advantage of polymorphism.
无类枚举(enumerize、SimpleEnum)非常适用于您只需要一个字段来表示一组固定值之一的简单用例。我对这个解决方案的主要问题是它鼓励分散在你的模型、控制器和视图中的条件。使用这些 gem 很诱人,因为它们是最容易实现的,但除了最简单的情况外,IMO 没有任何长期回报。
ClassyEnum 旨在解决与不同枚举相关的分散条件逻辑的问题。您仍然可以将它用于没有逻辑的简单集合,但是当您确实需要添加逻辑时(您几乎肯定会),您可以将其推送到各个枚举类中并利用多态性。
回答by Mihai Tarnovan
Looking at the code for enum, you can do this (at least in 4.1+): https://github.com/rails/rails/blob/master/activerecord/lib/active_record/enum.rb#L96-98by passing a hash, for example:
查看枚举的代码,您可以这样做(至少在 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 with unexpected results when accessing it, see https://github.com/rails/rails/issues/16459
尽管访问时出现意外结果,请参阅https://github.com/rails/rails/issues/16459
foo_instance.foo!
foo_instance.name
=> "foo"
foo_instance[:name]
=> "myfoo"
Update
更新
This issue was fixed in Rails 5, see https://github.com/rails/rails/commit/c51f9b61ce1e167f5f58f07441adcfa117694301. Thanks Yuri.
此问题已在 Rails 5 中修复,请参阅https://github.com/rails/rails/commit/c51f9b61ce1e167f5f58f07441adcfa117694301。谢谢尤里。
回答by Jay Quigley
How about:
怎么样:
class Foo < ApplicationRecord
NAMES = [
:foo,
:bar
]
enum names: NAMES.zip(NAMES).to_h
end
回答by Benjamin J. Benoudis
It seems that with Rails 5 API only, an enum attribute of a model will be save in database as integer, but will be published in public API as a string(with ActiveModel::Serializer).
似乎仅使用 Rails 5 API,模型的 enum 属性将作为 integer保存在数据库中,但将作为字符串发布在公共 API中(使用 ActiveModel::Serializer)。
For example,
例如,
Article model:
文章型号:
class Article < ApplicationRecord
enum status: [ :visible, :hidden ]
end
Article serializer:
文章序列化器:
class ArticleSerializer < ActiveModel::Serializer
attributes :id, :status, :title, :body
end
Will publish the following json:
将发布以下json:
{
"id": "1",
"type": "articles",
"attributes": {
"status": "visible",
"title": "Enums are passed as string in a json API render",
"body": "Great!",
}
回答by pdobb
The short answer is no. You will need to use a gem (such as magic-enum) if you want to do anything but store integers.
最简洁的答案是不。如果您想执行除存储整数以外的任何操作,则需要使用 gem(例如magic-enum)。
In DHH's own words on this from the comments on the pull request that added this feature:
用 DHH 自己的话说,来自添加此功能的拉取请求的评论:
It's pretty inefficient to store enums as text. You're going to repeat the same text over and over and over again. I'd consider that an anti pattern. People are better off doing a migration to ints if they want to use this.
将枚举存储为文本是非常低效的。您将一遍又一遍地重复相同的文本。我认为这是一种反模式。如果人们想使用它,最好迁移到整数。

