【Rails】Enumerizeで複数選択できるカラムを実装する

業務でEnumerizeを使って複数選択可能なカラムを実装する必要があったんですが、パッとやり方がわからなかったので、備忘録としてまとめます。

最後まで読めばEnumerizeで複数選択できるカラムを実装する方法や、その際の注意点を理解できるかなと思います。

目次

Enumerizeとは

EnumerizeはRailsのActiveRecordでenumを使えるようにするためのgemです。

Enumerizeを導入するとデフォルト値やバリデーション、複数選択やスコープ・I18n対応などenumよりも豊富なオプションを提供してくれます。

今回の場合、enumを用いて複数選択できるカラムを実装したかったため、Enumerizeを利用しています。

Enumerizeで複数選択可能なカラムを作る手順

ここではオンラインストアで商品を管理するシステムを例にします。

各商品に複数のタグを割り当てると仮定し、Productモデルにtagsカラムを実装します。

①マイグレーションファイルの作成

まずはマイグレーションファイルを作成します。

対象のカラムに array: true を設定する方法もあるみたいですが、ここでは公式ドキュメントを参考にタグのデータをシリアライズされた形式で管理することにします。

class CreateProducts < ActiveRecord::Migration[6.1]
  def change
    create_table :products do |t|
      t.string :name
      t.text :tags  # タグのデータをシリアライズされた形式で保存する

      t.timestamps
    end
  end
end

②モデルファイルの設定

マイグレーションが完了したら、次はモデルファイルにEnumerizeの設定を記述します。

以下のようにモデル内でserializeを指定し、multiple: trueを付与する必要があります。

class Product < ApplicationRecord
    extend Enumerize

    serialize :tags, Array
    enumerize :tags, in: [:book, :clothing, :food, :electronics], multiple: true
end

これで複数選択可能な列挙型カラムが実装できました。

なおEnumerizeはデフォルトでinclusionバリデーションをかけてくれるので、わざわざ書く必要はありません。

列挙型カラムの注意点

1つのカラムに複数の値を格納するのはSQLアンチパターンの「ジェイウォーク」に該当します。

なのでEnumerizeに限らず、できれば正規化して複数選択できるカラムの実装を避けた方が賢明です。

上記の例だと、tagsカラムではなくTagモデルを別途作成し、中間テーブルによってProductモデルと関連づけるのが教科書どおりのやり方です。

ぼくの現場では、以下の理由により原則から外れていると認識しつつも実装することとなりました。

  • 検索・集計のニーズが低い(インデックスもなし)
  • データの更新がめったに発生しない
  • 複雑なクエリ操作を行わない
  • 管理画面なのでパフォーマンスの懸念が小さい

まとめ

今回の内容から以下の学びが得られました。

  • Enumerizeで複数選択できるカラムを作るには、モデルファイル内にserializemultiple: trueを記述すればよい
  • ただし、そもそもSQLのアンチパターンに該当するので、原則的には避けるべき
  • 原則は認識しつつも、実情に応じた逸脱はかならずしも「悪」ではない
参考文献
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

未経験でSESから従業員300名以上の自社開発企業に転職しました。業務や個人開発で直面した問題や、転職・学習の経験を発信していきます。

コメント

コメントする

目次