1
1

More than 3 years have passed since last update.

[Rails]ユーザー情報にenumを使った実装

Last updated at Posted at 2020-05-15

はじめに

初めまして、Railsを勉強中のものです。
現在SNSアプリを開発中です。

よくある投稿機能や出品機能などに持たせるカラムとして、あらかじめ用意した値の中から選択させる属性を扱う場合enumが便利だと色んな記事で見てたのですが、
思っていたよりすんなり実装できなかったので初めてenumを使う方の参考になればと思い記録しておきます。

あくまで私が実装した内容を載せるだけなので、細かい説明は参考にしたリンクを貼っておきますのでそちらをご参照ください。

実装する内容

ユーザー情報に持たせるカラムとして、性別と年齢をenumを使って実装していきます。
Railsのバージョンは5.2.4です。今回はhamlで書いてます。

それではやってみましょう。

enumで値を定義する

まずはマイグレーションファイルから。
enumを使うカラムはinteger型で用意します。

db/migrate/xxxx_devise_create_users.rb
class DeviseCreateUsers < ActiveRecord::Migration[5.2]
  def change
    create_table :users do |t|

      t.string :nickname,            null: false
      t.string :email,               null: false, default: ""
      t.string :encrypted_password,  null: false, default: ""
      t.string :profile,             null: false
      # 型はintegerにする
      t.integer :gender,             default: 0
      t.integer :age,                default: 0

      # .省略
  end
end

初めオプションはnull :falseにしてました。今回はそれでも問題はなかったのですが、他の記事を見るとどれもdefault: 0で設定してたのと、公式ではこちらが推奨されてるみたいなので直しました。

次にモデルで実際にデータを用意します。

app/models/user.rb
class User < ApplicationRecord
  enum gender: { gender_private: 0, male: 1, female: 2, others: 3 }
  enum age: { age_private: 0, teens: 1, twenties: 2, thirties: 3, forties: 4, fifties: 5, over_sixties: 6 }
end

配列で定義してる方もいました。

app/models/user.rb
class User < ApplicationRecord
  enum gender: [ :gender_private, :male, :female, :others ]
  enum age: [ :age_private, :teens, :twenties, :thirties, :forties, :fifties, :over_sixties ]
end

どちらでも大丈夫ですが、配列の場合対応する数字が自動で0から順になるということだけ注意が必要です。
他のカラムと区別したり、わかりやすくするために1、10、20などの数字にする方もいるみたいです。その場合はハッシュで書くしかないですね。

viewでフォームを実装する

次にフォームの実装です。
私はセレクトボックス で用意しました。

app/views/devise/registrations/new.html.haml
= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f|

  .field
    = f.label :gender
    %br/
    = f.select :gender, options_for_select_from_enum(User, :gender)
  .field
    = f.label :age
    %br/
    = f.select :age, options_for_select_from_enum(User, :age)

フォームの実装はいろいろな書き方があると思いますが、私の場合
ArgumentError ('2' is not a valid gender):
というエラーが出てしまい、色々試した結果最終的に上の書き方になりました。
同じエラーに当たった方は、こちらの記事が詳しく書いてありました。

enumを使うとArgumentError in TasksController#create => '2' is not a valid status_id

これでenumを使って性別と年齢を登録できるようになりましたが、現状セレクトボックスに表示されるのは英語のままになっています(age_private、teens、twenties ...)

プルダウンの表示を日本語化する

こちらもいくつかやり方があるみたいです。
gemを使う方法もあるみたいですが今回は別の方法で実装します。

【Rails】Enumってどんな子?使えるの?

こちらの記事を参考にさせてもらいました。
というかまんまこの通りやりました。

ちなみにgemを使う方法はこちらに書いてあります。
【初心者向け】i18nを利用して、enumのf.selectオプションを日本語化する[Rails]

ja.ymlファイルの作成

まず、i18機能で日本語設定をしていない場合はファイルを用意する必要があります。

Gemfile
#rails5系
gem 'rails-i18n', '~> 5.1'

#rails4系
gem 'rails-i18n', '~> 4.0' 

こちらのgemを導入、もしくは

svenfuchs/rails-i18n
こちらのファイルをコピーして、config/locales/ja.ymlファイルを作ります。

そのファイルにenumで定義した値を日本語に変換させるのための記述をします。

config/locales/ya.yml
:ja
  #省略
  enums:
    user:
      gender:
        gender_private: "非公開"
        male: "男性"
        female: "女性"
        others: "他"
        #省略

デフォルトの言語を日本語化

次にapplication.rbでデフォルトの言語を日本語化するための設定です。

config/application.rb
module SnsApp
  class Application < Rails::Application
    #省略

    #追記
    config.i18n.default_locale = :ja
    config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]

   #省略
  end
end

これで先程のja.ymlファイルが読み込まれます。

そしてもう一つファイルを作ります。

Helperメソッドを用意する

app/helpersの下にファイルを作ります。

app/helpers/enum_helper.rb
module EnumHelper
  # クラスオブジェクトとカラム名を引数として呼ばれるコールバック関数です
  def options_for_select_from_enum(klass,column)
    #該当クラスのEnum型リストをハッシュで取得
    enum_list = klass.send(column.to_s.pluralize)
    #Enum型のハッシュリストに対して、nameと日本語化文字列の配列を取得(valueは使わないため_)
    enum_list.map do | name , _value |
      # selectで使うための組み合わせ順は[ 表示値, value値 ]のため以下の通り設定
      [ t("enums.#{klass.to_s.downcase}.#{column}.#{name}") , name ]
    end
  end
end

上の記事から丸ごと頂きました。

これでプルダウンの日本語も完了です!

最後に

今回はenumを使った実装方法を書きましたが、他に都道府県のカラムも欲しかったのでそちらはactive_hashで実装しました。

使い勝手も実装のしやすさもactive_hashの方が楽なのですが、性別など2個か3個しかない値のためにモデルをいっぱい作るのも無駄なような感じがしたのと、
大体皆さん性別はenumで実装してる方が多いみたいなので今回使ってみました。
実際覚えてしまえば使う場面はいっぱいあると思うので、必要に応じて積極的に使っていこうと思います。

私が書いたやり方でうまくいかなかった方は、今回参考にした記事をまとめておきますので色々見て見てください!

また、無駄な記述や間違った認識などがありましたらご指摘いただけるとありがたいです!

参考にした記事

【Rails】Enumってどんな子?使えるの?

Ruby on Rails:ModelのプロパティにEnumを使う※おまけ:ラジオボタンでEnumを扱う

enumを使うとArgumentError in TasksController#create => '2' is not a valid status_id

【初心者向け】i18nを利用して、enumのf.selectオプションを日本語化する[Rails]

[初学者]Railsのi18nによる日本語化対応

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1