railsのgemであるcocoonを用いて1対nのネストした投稿フォームを作る

railsのgemであるcocoonを用いて1対nのネストした投稿フォームを作る:


はじめに

一つのフォームで親子関係のある複数モデルのレコード作成かつ子モデルのレコードを複数挿入したい場合にgemのcocoonを使うと簡単に実装できます。

今回はタイトルしか挿入しない投稿フォームに子モデルのタグを複数挿入する機能を実装します。

(タイトルカラムのあるPostモデルとタグカラムのあるTagモデルは1対Nの関連付けがあることが前提で進めます。)


実装


シンプルな投稿フォームの作成

scaffoldを使い、親モデルのレコードを作成できるようにします。

$ rails new cocoon_sample 
 
$ cd cocoon_sample 
$ rails g scaffold Post title:string 
 
$ rails db:migrate 
子モデルを作成します。

今回は子モデル名をTagにします。(カラムはタグを格納するためのnameカラムpost_idが必要)

$ rails g model Tag name:string post_id:integer 
 
$ rails db:migrate 
PostモデルとTagモデルに関連付けを行います。

post.rb
...(追加) 
  has_many :tags, dependent: :destroy 
  accepts_nested_attributes_for :tags, allow: true 
tag.rb
belongs_to :post 
ネストしたフォームを作成するためにposts_controller.rbのnewアクションと_form.html.erbを編集します。

posts_controller.rb
def new 
    @post = Post.new 
    @post.tags.build 
  end 
  ...(省略) 
 
  def post_params 
    params.require(:post).permit(:title, tags_attributes: [:id, :name, :_destroy]) 
  end 
_form.html.erb
...(省略) 
  <%= form.fields_for :tags do |f| %> 
    <%= f.label :name %> 
    <%= f.text_field :name %> 
  <% end %> 
 
  <div class="actions"> 
    <%= form.submit %> 
  </div> 
ここまでの記述でPostモデルとその子モデルのTagモデルのレコードの挿入を一つのフォームでできるはずです。

次に一つの親モデルに対し複数の子モデルのレコードを挿入できるように編集していきます。

_form.html.erb
<div class="tags"> 
    <%= form.fields_for :tags do |f| %> 
      <%= f.label "タグ" %> 
      <%= render "tag_fields", f: f %> 
    <% end %> 
    <div class="links"> 
      <%= link_to_add_association "タグを追加", form, :tags %> 
    </div> 
  </div> 
タグのフォームを部分テンプレートにするためファイルを作成します

views/posts/_tag_fields.html.erb
<div class="nested-fields"> 
    <%= f.text_field :name %> 
    <%= link_to_remove_association "remove task", f %> 
  </div> 
動的に要素を増やすためjsも変更します。

application.js
...(省略) 
  //= require rails-ujs 
  //= require activestorage 
  //= require jquery ...(追加) 
  //= require cocoon ...(追加) 
  //= require turbolinks 
  //= require_tree . 


最後に

cocoonを使うと簡単にネストしたフォームを作成できます。

便利ですが正しい記述をしないと投稿や要素の追加や削除ができない場合があります。

要素(DOM)の操作はjqueryが便利です。

cocoonを使わずjqueryで実装するのも良いと思います。

コメント

このブログの人気の投稿

投稿時間:2021-06-17 05:05:34 RSSフィード2021-06-17 05:00 分まとめ(1274件)

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2020-12-01 09:41:49 RSSフィード2020-12-01 09:00 分まとめ(69件)