ruby-on-railsrubyactiverecordform-forfields-for

Rails: nested form, create multiple child records


I'm trying to create a Group in SNS app which has several users. Group has_many Users through Groups_users.

Here I've got a form to create a group, and I want to add members(Groups_users) to the group at the same time. I succeeded in adding one member to the group at the same time I create a group, but I just can't add several members to the group.

Here's my code:

Models:

group.rb

class Group < ApplicationRecord
  validates :name, presence: true, uniqueness: true
  validates :owner_user_id, presence: true
  has_many :groups_users, inverse_of: :group
  has_many :users, through: :groups_users
  accepts_nested_attributes_for :groups_users
  has_many :group_posts
end

groups_user.rb

class GroupsUser < ApplicationRecord
  belongs_to :group, inverse_of: :groups_users
  belongs_to :user
  validates :group, presence: true
  validates :user_id, presence: true
end

Controllers:

groups_controller.rb

module Users
  module Users
    class GroupsController < BaseController
      def index
        @group = Group.new
        @group.groups_users.build
        @groups = Group.all
      end

      def create
        group = Group.new(group_params)
        if group.save!
          redirect_to users_groups_path, notice: 'a new group created!'
        else
          redirect_to users_groups_path, notice: 'The selected group name has already been taken.'
        end
      end

      private

        def group_params
          params.require(:group).permit(:name, :owner_user_id, groups_users_attributes: [:user_id])
        end
    end
  end
end

Views:

groups/index.html.slim

= form_for [:users, @group] do |f|
  .field
    = f.label :name, 'group name:'
    = f.text_field :name, size: 15, maxlength: 20
    = f.hidden_field :owner_user_id, value: current_user.id
  .field
    = f.fields_for :groups_users do |g|
      = g.label :user_id, 'user name you want to add'
      = g.select :user_id, options_for_select(current_user.mutual_followers.map { |user| [user.name, user.id] }), {  }, { multiple: true }

  .actions
    = f.submit

Note:

I think my code doesn't work because I insert an array of user_ids as one user_id, but I don't know how to solve this problem.

P.S. I found a similar question here: Nested Simple Form in Rails4 - has many through, save multiple records

However, I couldn't find out how to solve my problem as I'm not using simple_form, and I couldn't figure out how to make up for that difference in form_for.


Solution

  • One simple way to solve this problem is to use the nested_form gem. https://github.com/ryanb/nested_form

    If you use it, you can add or remove nested_forms just by coding like below.

    <%= f.fields_for :tasks do |task_form| %>
      <%= task_form.text_field :name %>
      <%= task_form.link_to_remove "Remove this task" %>
    <% end %>
    <p><%= f.link_to_add "Add a task", :tasks %></p>
    

    The gem's README is quite easy to understand so you should check that as well.

    Also, if you look at the wiki the gem provides, you can know how to customize your forms as you like.