ホーム > カテゴリ > Ruby・Ruby on Rails >

1つのフォームで複数のモデルを扱う [Ruby on Rails]

1つのフォームで複数のモデルを扱う方法です。

例として「掲示板システム」の機能である、新規質問の登録に焦点を当てます。新規質問の際には「questions」(質問テーブル)、「answers」(回答テーブル)に各1レコードが作成される仕様とします。

モデル(テーブル構成)

questions - 質問テーブル

項目名備考
idinteger
titlestringタイトル

answers - 回答テーブル

項目名備考
idinteger
question_idintegerquestionsテーブルのid
namestring名前
urlstringURL
bodystring本文

今回はテーブルを1:Nの親子関係にしていますが、全く無関係の複数モデルでもOKです。

コントローラー側

newは新規質問の登録画面。createでテーブルの登録処理を行います。question_params及びanswer_paramsはストロングパラメータで不正なパラメータを防ぎます。

def new
  @question  = Question.new     
  @answer = Answer.new   
end
 
def create
  @question = Question.new(question_params) 
  @answer = Answer.new(answer_params[:answer]) 
  
  ・・・登録処理 ・・・
end

private

def question_params
  params.require(:question).permit(:title)
end      

def answer_params
  params.require(:question).permit(answer:[:name, :url, :body])
end  

ビュー側

SlimとBootstrap4を使用しています。※erbの方は後述するHTMLを参考。

= form_with model: @question, local: true do |f|
  .form-group
    = f.label :title
    = f.text_field :title, class: 'form-control', id: 'question_title' 
    
  = f.fields_for @answer do |i| 
    .form-group
      = i.label :name
      = i.text_field :name, class: 'form-control', id: 'question_answer_name'
    .form-group
      = i.label :url 
      = i.text_field :url, class: 'form-control', id: 'question_answer_url'
    .form-group
      = i.label :body
      = i.text_area :body, rows: 5, class: 'form-control', id: 'question_answer_body'
 
  = f.submit '作成する', class: 'btn btn-primary'  

form_withのモデルが親で、fields_forは子の扱いです。

このフォームがPOSTで送信するパラメータは次のような形式になります。

{
  "utf8"=>"✓", 
  "question"=>
    {
      "title"=>"質問のタイトル", 
      "answer"=>
        {
         "name"=>"名前", 
         "url"=>"https://www.petitmonte.com/",
         "body"=>"本文です。"
        }
    },
  "commit"=>"作成する"
}

HTML(ビューの出力例)

<form action="/questions" accept-charset="UTF-8" method="post">
  <div class="form-group">
    <label for="question_title">タイトル</label><input class="form-control" id="question_title" type="text" name="question[title]" />
  </div>
  <div class="form-group">
    <label for="question_answer_name">名前</label><input class="form-control" id="question_answer_name" type="text" name="question[answer][name]" />
  </div>
  <div class="form-group">
    <label for="question_answer_url">URL</label><input class="form-control" id="question_answer_url" type="text" name="question[answer][url]" />
  </div>
  <div class="form-group">
    <label for="question_answer_body">本文</label><textarea rows="5" class="form-control" id="question_answer_body" name="question[answer][body]">
  </textarea>
  </div>
  <input type="submit" name="commit" value="作成する" class="btn btn-primary" data-disable-with="作成する" />
</form>

以上です。





関連記事



公開日:2019年10月18日
記事NO:02794