0

I'm using Rails 4, and with it Strong Params. For some reason I can't save my nested parameters. I've looked at how to do it and even might've gotten it working in a different Rails app before. I know to permit draft_players_attributes and list all of it's accepted params in an array.

Here are the params coming in:

Started POST "/draft_groups" for 127.0.0.1 at 2013-12-04 22:55:32 -0500
  User Load (1.6ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 1 ORDER BY "users"."id" ASC LIMIT 1
Processing by DraftGroupsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"2W3bs1U7+CEzsWl+jDi3xZi5CyldYeZXCz3KU6c+sYY=", "draft_group"=>{"name"=>"Best Group Ever", "draft_id"=>"3", "captain_id"=>"1"}, "draft_players"=>{"player_id"=>"1", "position"=>"Handler", "rating"=>"10", "info"=>"Smart"}, "commit"=>"Update"}
   (0.3ms)  BEGIN
  SQL (2.6ms)  INSERT INTO "draft_groups" ("captain_id", "created_at", "draft_id", "name", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id"  [["captain_id", 1], ["created_at", Thu, 05 Dec 2013 03:55:32 UTC +00:00], ["draft_id", 3], ["name", "Best Group Ever"], ["updated_at", Thu, 05 Dec 2013 03:55:32 UTC +00:00]]
   (0.5ms)  COMMIT
Redirected to http://lvh.me:3000/drafts/3
Completed 302 Found in 8ms (ActiveRecord: 3.3ms)

Here's my controller:

class DraftGroupsController < ApplicationController
  def create
    @draft_group = DraftGroup.create(draft_group_params)
    redirect_to :back, :notice => "Draft Group successfully created."
  end

  def update
    @draft_group = DraftGroup.find(params[:id])
    @draft_group.update(draft_group_params)
    redirect_to :back, :notice => "Draft Group successfully updated."
  end

  def destroy
    @draft_group = DraftGroup.find(params[:id]).destroy
    redirect_to :back, :notice => "Draft Group successfully destroyed."
  end

  private
  def draft_group_params
    params.require(:draft_group).permit(:name,
                                        :draft_id,
                                        :captain_id,
                                        draft_players_attributes:
                                          [
                                            :_destroy,
                                            :id,
                                            :player_id,
                                            :position,
                                            :rating,
                                            :info
                                          ]
                                       )
  end
end

And my models:

class DraftGroup < ActiveRecord::Base
  has_many :draft_players, :dependent => :destroy
  belongs_to :captain, :class_name => "User"

  accepts_nested_attributes_for :draft_players
end

class DraftPlayer < ActiveRecord::Base
  belongs_to :draft_group
  belongs_to :player, class_name: "User"
end

And my view:

<% @groups.each do |group| %>
  <div class="span6 group">
    <h4><%= "#{group.name}" %></h4>
    <%= simple_form_for(group, :html => { :class => "auto-width" } ) do |f| %>
      <div class="row">
        <%= f.input :name, :label => false %>
        <%= f.hidden_field :draft_id %>
        <%= f.hidden_field :captain_id %>
      </div>
      <table>
        <tr>
          <th>Player</th>
          <th>Position</th>
          <th>Rating</th>
          <th>Info</th>
        </tr>
        <%= simple_fields_for :draft_players do |player| %>
          <tr>
            <td><%= player.input :player_id, :label => false, :as => :select, :collection => User.active %></td>
            <td><%= player.input :position, :label => false %></td>
            <td><%= player.input :rating, :label => false %></td>
            <td><%= player.input :info, :label => false %></td>
          </tr>
        <% end %>
      </table>
      <div class="row">
        <%= f.button :submit, "Update", :class => "btn btn-primary" %>
      </div>
    <% end %>
  </div>
<% end %>

EDIT: Added view code, and will probably take table out, shifting it into using bootstraps columns layout.

Tom Prats
  • 7,364
  • 9
  • 47
  • 77
  • 2
    I can't reproduce nested form myself to recheck the structure of params... Two things confuse me. #1 Why `draft_players` params are NOT in `draft_group` params? #2 It seems to me that `draft_players` should have name `draft_players_attributes`. PS post your view with the nested form. – gotva Dec 05 '13 at 06:18
  • That might actually be my solution, I'll try to post my view code soon but I think it's having part of the form within a table ruining it. – Tom Prats Dec 09 '13 at 16:38

1 Answers1

1

To make sure parameters are nested correctly (and so Rails can understand nested model attributes) you should call f.simple_fields_for(:draft_players) rather than simple_fields_for(:draft_players).

In other words, call simple_fields_for on the FormBuilder object f rather than calling the helper directly.

That way Rails can look up and validate the nested association correctly.

piersadrian
  • 1,653
  • 12
  • 12