web-dev-qa-db-ja.com

列挙値を整数ではなく文字列型にマッピングする可能性

Enum属性は素晴らしいので、それらを使用したいと思います。ただし、列挙値を整数にマッピングすると、コードとデータベースの両方を維持することが難しくなります。また、私のデータベースは私のコードと高度に結びついているので、それは悪いことだと考えるべきです。

ハッシュを使用してキーと値のペアを持つ列挙型属性を整理できることはわかっていますが、配列を使用してデータベース内の文字列値にマップできる方がはるかに優れています。

デフォルトで列挙型を文字列にマップする方法はありますか?

20
Eren CAY

私の知る限り、Active Recordの組み込み列挙型機能では不可能です。ただし、これを行う人気のあるサードパーティの宝石がいくつかあります。 Active Recordに付属するものに最も近いものは、おそらく enumerizeSimpleEnum です。

ただし、少し違うものを探している場合は、 ClassyEnum をお勧めします(完全な開示:私が作成しました)。これが 私のメモの一部 で、enumerizeとSimpleEnumとClassyEnumの違いについて:

クラスのない列挙型(enumerize、SimpleEnum)は、固定された値のセットの1つを表すためにフィールドが必要なだけの単純なユースケースに最適です。このソリューションで私が抱えている主な問題は、モデル、コントローラー、ビュー全体に散在する条件を奨励することです。これらのgemは実装が最も簡単なため、使いたくなりますが、長期的な見返りは、最も単純なケース以外のIMOにはありません。

ClassyEnumは、さまざまな列挙型に関連する条件付きロジックが散在しているという問題を解決するために設計されました。ロジックを持たない単純なコレクションでも引き続き使用できますが、ロジックを追加する必要がある場合(そしてほぼ間違いなく)、それを個々の列挙クラスにプッシュして、ポリモーフィズムを利用できます。

8
Peter Brown

列挙型のコードを見て、これを行うことができます(少なくとも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 を参照してください。ありがとうYuri。

23
Mihai Târnovan

どうですか:

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

  enum names: NAMES.Zip(NAMES).to_h
end
5
Jay Quigley

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!",
}

短い答えはノーです。整数を格納する以外のことをしたい場合は、gem( magic-enum など)を使用する必要があります。

この機能を追加したプルリクエスト のコメントからのDHH自身の言葉で:

列挙型をテキストとして保存するのはかなり非効率的です。同じテキストを何度も何度も繰り返します。アンチパターンだと思います。これを使用したい場合は、intへの移行を行う方がよいでしょう。

4
pdobb