アラサーからのエンジニア転身blog

プログラミングの勉強や転職に関して記事にしていきます。

fields_for、check_box、enumで使用し、別モデルに複数レコードを作成する方法

f:id:sakurai-chan:20181009195218p:plain

実現したこと

  1. questionモデルのform内で別のモデルquestion_tagにレコードを保存する
  2. 1度のsubmitでquestion_id に対して複数のtagを付ける(複数レコード生成)
  3. enumで定義したタグをcheck_boxで表示する

・question_tags table こんな感じ
f:id:sakurai-chan:20181009194251p:plain

・Viewイメージ
(questionのレコードと同時にquestion_tagのレコードを複数生成する)f:id:sakurai-chan:20181009195015p:plain

・questionsとquestion_tagsの関係
f:id:sakurai-chan:20181009195218p:plain

どうやったのか?

gemfile

18nでenumを日本語化

gem 'enum_help'
application.rb

localeを:ja(日本語)に設定する

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

require_relative 'boot'

require 'rails/all'

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

module Stuttering
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 5.2


    config.time_zone = 'Tokyo'
    config.active_record.default_timezone = :local
    config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}').to_s]
  #I18nのload_pathにlacalesディレクトリ配下のrb,ymlを全て読む
    config.i18n.default_locale = :ja
 #localeを:ja(日本語)に設定する。
  end
end
locales/ja.yml

これでenumの英語を日本語と紐付けられる。

ja:
  enums:
    question_tag:
      tag:
        school: '学校'
        work: '仕事'
        job_hunting: '就活'
        relationship: '恋愛'
        improvement: '改善'
        hospital: '病院'
        other: 'その他'
question.rb

form_forの中で別のモデルに保存するためにaccepts_nested_attributes_for を記述します。

class Question < ApplicationRecord

  has_many :questionTags, dependent: :destroy
  accepts_nested_attributes_for :questionTags 

end
question_tag.rb

enumでtagを定義します。

class QuestionTag < ApplicationRecord
  belongs_to :question

  enum tag: { school: 0, work: 1, job_hunting: 2, relationship: 3,
improvement: 4, hospital: 5, other: 10, }

end
questions_controller.rb

@question.questionTags.buildを定義することでview内で f.fields_for のインスタンスを生成する。

保存するテーブル名_attributes: [:カラム]をストロングパラメータに追加することでform_forから別のモデルのパラメータを取得できる。

.
.
.

  def new
    @question = Question.new
    @question.questionTags.build

  end
.
.
.
  private
    def question_params
      params.require(:question).permit(:title, :body, questionTags_attributes: [:tag]).merge(user_id: current_user.id)
    end
end
new.html.haml

form_forの中にf.fields_forを定義することで、QuestionTagsテーブルにレコードを保存できる。

- QuestionTag.tags_i18n.map do |k, v|
= f.fields_for :questionTags do |qt|
= qt.label :tag, v
= qt.check_box(:tag,{:checked=>false}, k ,false)

QuestionTag.tags_i18nこちらで、enumで定義した英語と日本語の組み合わせがvalueとkeyのセットでハッシュとして取得できる。それぞれ、k、vのブロックに定義して、mapで繰り返すことで、enum分の数だけcheck_boxを生成し、更にチェックした分だけf.fields_forが繰り返されるので、チェック数だけレコードが保存される。

= form_for @question do |f|
  .form-group
    %h5.main-color-bottom-border タイトル
    =f.text_field :title, class: "form-control ",placeholder: "タイトル"
    .form-group.mt-2
      %h5.main-color-bottom-border 質問のジャンルを選択
      - QuestionTag.tags_i18n.map do |k, v|
        = f.fields_for :questionTags do |qt|
          = qt.label :tag, v
          = qt.check_box(:tag,{:checked=>false}, k ,false)

参考にさせていただきました。
【Rails 5.2】i18nでenumを日本語化 & モデル(model)別にYMLファイルを管理
Rails国際化 (I18n) API | Rails ガイド