2

I try to update the has_many :through association with strong parameters in Rails 4 without success. This is my model :

User
  has_many :group_owner, :class_name => "Group"
  has_many :group_memberships
  has_many :memberships, :through => :group_memberships, :class_name => "Group"
end

Group
  belongs_to :owner, :class_name => "User", :foreign_key => "user_id"
  has_many :user_members
  has_many :members, :through => :user_members, :class_name => "User"
end 

in the Group view (create/edit)

    <%= form_for(:group, :url => {:action => 'update', :group_id => @group.id}) do |f| %>   

        <th>New participant</th>
        <td><%= f.collection_select(:members, @users, :id, :first_name) %></td>

        <%= submit_tag("Update Group") %>
    <% end %>

Then, in the controller, I try to use strong parameters to save the new member in the DB:

def groupe_params
  params.require(:group).permit(:user_id, :group_name, members: [:id])
end

But the user is not saved in the DB, and I don't have any error message. When I try to do

 group.members << user

via the ruby console, it succeeds.

I'm looking for a solution since few hours already. I've tried to understand the solution from this question (How to use Rails 4 strong parameters with has_many :through association?) but I'm still stuck.

I tried to check what is the value of :members variable in my controller :

 member_id = params[:members]
 flash[:notice] = "member id = #{member_id} !!" 

and it is always empty :

 member id = !!

But, when I replaced in strong parameters :

def group_params
  params.require(:group).permit(:user_id, :group_name, members: [:id])
end

by

def group_params
  params.require(:group).permit(:user_id, :group_name, :members)
end

I get the following error :

undefined method `each' for "1":String

{"utf8"=>"✓",
 "authenticity_token"=>"GxCd==",
 "group"=>{"name"=>"G7",
 "members"=>"1"},
 "commit"=>"Update Group",
 "group_id"=>"4"}

that show me that the :members variable is not empty !

Any help is welcome. Thank you.

Community
  • 1
  • 1
BlackMat
  • 41
  • 2
  • 7

1 Answers1

1

According to your incoming parameters, params[:members] does not exist - it's in params[:group][:members]. That's why your attempt to print member_id is not working. I suspect you meant to use group_params[:members]:

member_id = group_params[:members]
flash[:notice] = "member id = #{member_id} !!"

Your second problem is that members is not a list of objects, so specifying members: [:id] will not work. That expects parameters like

group: {
  members: [
    {id: 1},
    {id: 2}
  ]
}

You're only passing in a list of IDs, so you want members: [], which expects a list of scalar values the way the question you linked to describes.

Lastly, your has_many association is going to expect an attribute called member_ids, not members. So your final strong parameter definition should be:

def group_params
  params.require(:group).permit(:user_id, :group_name, member_ids: [])
end

This will let you set the Group's members via group.member_ids = [1,2,3] from the has_many relationship.


It looks like there might be an issue other than parameters, because your Users have many Groups through group_memberships, but your Groups have many Users through user_members. Unless you have other configuration compensating, you want to be using the same table there with :user_id and :group_id columns to get the relationship working correctly in both directions.

Kristján
  • 18,165
  • 5
  • 50
  • 62