Вопрос по ruby-on-rails-4, enumeration, ruby-on-rails – Возможность отображения значений перечисления в строковый тип вместо целого

19

Атрибуты enum великолепны, и я хочу их использовать. Но сопоставление значений перечисления с целым числом затруднит поддержку как кода, так и базы данных. Кроме того, моя база данных будет тесно связана с моим кодом, который, я думаю, я считаю плохим.

Я знаю, что могу использовать хеш для организации атрибута enum с парами ключ / значение, но все же было бы намного лучше иметь возможность использовать массив и сопоставлять строковые значения в базе данных.

Есть ли способ сопоставить enum со строками по умолчанию?

Ваш Ответ

5   ответов
4

нет. Вам нужно будет использовать драгоценный камень (например,магия-перечисление) если вы хотите делать что-либо, кроме хранения целых чисел.

В собственных словах DHH об этом из комментариевзапрос на добавление, который добавил эту функцию:

Хранить перечисления в виде текста довольно неэффективно. Вы будете повторять один и тот же текст снова и снова и снова. Я бы посчитал это анти паттерном. Людям лучше переходить на целые, если они хотят это использовать.

У DHH есть смысл, но я бы не стал использовать однозначные и сложные в обслуживании целые числа лучше, чем повторять одно и то же - простое и удобное в обслуживании строки снова и снова. Eren CAY
Хах! Он такой лицемерный. Почему тогда DHH не реализует полиморфные ассоциации с целыми числами?type: 'CompanyAddress' занимает кучу места ... Volte
хранение строки не так уж далеко от базы, учитывая, что логические значения часто хранятся как символы. SirWolfgang
DHH также сказал: «Я был бы рад видеть, что это подтверждается перечислениями базы данных», что ближе к использованию строк, чем к целым числам. Не уверен, что что-нибудь случилось с этим, хотя. Peter Brown
5

Как насчет:

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

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

что только с Rails 5 API атрибут enum модели будет сохранен в базе данныхкак целое число, но будет опубликован в публичном 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!",
}
8

это невозможно с помощью встроенной функции перечисления Active Record. Тем не менее, есть несколько популярных сторонних жемчужин, которые делают это. Наиболее близким совпадением с Active Record являются, вероятно,enumerize а такжеSimpleEnum.

Однако, если вы ищете что-то немного другое, я бы порекомендовалClassyEnum (полное раскрытие: я написал это). Вотнекоторые из моих заметок о разнице между перечислением и SimpleEnum против ClassyEnum:

Перечисления без классов (enumerize, SimpleEnum) отлично подходят для простых случаев использования, когда вам просто нужно поле для представления одного из фиксированного набора значений. Основная проблема, с которой я сталкиваюсь в этом решении, заключается в том, что оно поддерживает условные выражения, разбросанные по вашим моделям, контроллерам и представлениям. Соблазнительно использовать эти драгоценные камни, потому что они наиболее просты в реализации, но долгосрочная отдача просто не в IMO ни для чего, кроме простейших случаев.

ClassyEnum был разработан для решения проблемы разброса условной логики, связанной с различными перечислениями. Вы по-прежнему можете использовать его для простых коллекций, в которых нет логики, но когда вам нужно добавить логику (а вы почти наверняка) добавите ее, вы можете добавить ее в отдельные классы enum и использовать преимущества полиморфизма.

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'
  }

Хотя неожиданные результаты при доступе к нему, см.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, Спасибо Юрий.

Было исправлено:github.com/rails/rails/commit/... Yuri Ghensev

Похожие вопросы