1

I have a basketball app, where a Roster has many Players, and a Player can be on multiple Rosters.(Reason for many-to-many is for a Player-Roster archive)

Roster.rb

class Roster < ActiveRecord::Base
      belongs_to :team
      has_many :rosterizes
      has_many :players, :through => :rosterizes
      accepts_nested_attributes_for :players
      attr_accessible :jersey_number, :team_id, :class_year, :players
    end

Rosterizes.rb(poorly named I know...)

class Rosterize < ActiveRecord::Base
  belongs_to :player
  belongs_to :roster
  attr_accessible :player_id, :roster_id
end

Player.rb

class Player < ActiveRecord::Base
  has_many :rosterizes
  has_many :rosters, :through => :rosterizes
  validates_presence_of :first_name, :last_name
  attr_accessible :first_name, :last_name, :active
end

The View

<div class="well">
    <h2>New Player</h2>
    <%= simple_form_for @roster, :url =>player_added_team_path, :html => { :class => 'form-horizontal' } do |f| %>
        <%= f.simple_fields_for @new_player do |x| %>
            <%= x.input :first_name %>
            <%= x.input :last_name %>
        <%end%>
        <%=f.input :class_year %>       
        <%=f.input :jersey_number %>
        <%=f.input :team_id, :as => :hidden, :input_html => {:value => params[:id]}%>

        <div class="well">
        <%= f.button :submit, :class => 'btn-primary icon-plus-sign btn-success', :value => "Add To Team" %>
        </div>
    <%end%>
</div>

The paramaters I am sending to the controller:

"roster"=>{"player"=>{"first_name"=>"first name", "last_name"=>"last name"}, "class_year"=>"freshman", "jersey_number"=>"23", "team_id"=>"1"}, "commit"=>"Add To Team", "id"=>"1"}

Controller that is handling the Saving:

def player_added
   @team = Team.find(params[:id])

   #where the issue is happening
   @roster = @team.rosters.build(params[:roster])
   @roster.save
   ...

end

I have a work around using using the parameters, BUT I would like to understand what I am doing wrong here for future/learning purposes and why it is giving me: Can't mass-assign protected attributes

My work around(kinda hacky):

def player_added

    @team = Team.find(params[:id])
    @roster = @team.rosters.build(:class_year => params[:roster][:class_year], :jersey_number => params[:roster][:jersey_number])
    @new_player = @roster.players.build(:first_name => params[:roster][:player][:first_name], :last_name => params[:roster][:player][:last_name])

    @roster.save
    @new_player.save

    ...

end

I am using Simple_Form 2.0...

I know this is a lot of information, but thanks you in advance!

SOLUTION

Just incase anyone else is having same the same/similar issue I am...

I installed this plug in => https://github.com/ryanb/nested_form

So this is the changes I made:

Roster.rb

class Roster < ActiveRecord::Base
  belongs_to :team
  has_many :rosterizes
  has_many :players, :through => :rosterizes
  accepts_nested_attributes_for :players
  attr_accessible :jersey_number, :class_year, :players, :player_attributes
end

I also made the change to the view to:

 <%= simple_nested_form_for @roster, :url =>player_added_team_path, :html => { :class => 'form-horizontal' } do |f| %>
      <%= f.simple_fields_for :players, @roster.players.build do |x| %>
           # nested form
           ...
      <%end%>
      # form
      ...
<%end%>

Controller to save def player_added

@team = Team.find(params[:id])
@roster = @team.rosters.build(params[:roster])
@roster.save

...

end

This was a pain in the butt for me to understand, Hopefully this will cut down the time for any of you looking for answers/learning nested_forms!

mrcolombo
  • 587
  • 4
  • 19

1 Answers1

3

The problem is with the way you are naming your nested association attribute, and with the parameters you are sending:

The attribute for nested :players should be :players_attributes, and :team_id should not be listed (because that overrides the team association rails magic):

attr_accessible :jersey_number, :class_year, :players_attributes

And the parameters should have this format:

"roster"=>{"players_attributes"=>[{"first_name"=>"first name", "last_name"=>"last name"}], "class_year"=>"freshman", "jersey_number"=>"23"}, "commit"=>"Add To Team", "id"=>"1"}

To accomplish this, you should probably change simple_form_for @roster to simple_nested_form_for @roster

Note that you don't need to include the "team_id" attribute in the parameters for "roster" because that you are already loading and associating the roster to it.

PinnyM
  • 35,165
  • 3
  • 73
  • 81
  • I made the changes but now I am getting a new error, check out my edit. Sorry if my issues/questions are naive, my experience with rails is beginner to moderate, first time working with nested forms as well. Thanks for your input and help! – mrcolombo Apr 20 '12 at 03:53
  • accepts_nested_attributes_for :players should have remained unchanged, only the attr_accessible portion needed to change – PinnyM Apr 20 '12 at 03:58
  • Made the change, doest seem to recognize the `simple_nested_from_for` call http://i.stack.imgur.com/hU7Dx.png, also fixed my Edit above to what you originally meant. – mrcolombo Apr 20 '12 at 04:13
  • Are you using the latest version? See http://stackoverflow.com/questions/8195107/undefined-method-simple-nested-form-for – PinnyM Apr 20 '12 at 04:17
  • I am using SimpleForm 2.0, this gem => https://github.com/plataformatec/simple_form, on the github wiki, there is a nested model example, and that is what I used to get myself started on nested forms. Should I move over to the gem you listed? – mrcolombo Apr 20 '12 at 04:23
  • The nested_form plugin doesn't replace SimpleForm - it provides support for nested associations on top of SimpleForm (or FormTastic). It simplifies what you need to do in this case. If you prefer not to use it, you can just create the input fields manually so the post data will match the expected parameter format. – PinnyM Apr 20 '12 at 14:16
  • Thanks for all your help and insight, will up vote when i have enough rep. – mrcolombo Apr 20 '12 at 15:05