Jonah Katz
Jonah Katz

Reputation: 5288

Single form for parent and all children in relationship?

In my RoR I have a table games, stats, and players. Each game has many players, each player has many 'stats,' and each games has many stats through players. What i want to be able to do is in on my edit games form, i want there to be a a row of fields to add a new stat row, one per each players the game has. Ive been reading a lot about nested_attributes, but found new good resources how to fully do this.

Upvotes: 0

Views: 120

Answers (2)

Cade
Cade

Reputation: 3181

UPDATE: Here's an updated set of classes based on the new associations you've stated in your comment

# models/game.rb
class Game < ActiveRecord::Base
  has_many :teams
  accepts_nested_attributes_for :teams
  attr_accessible :name, :teams_attributes
end

# models/team.rb
class Team < ActiveRecord::Base
  belongs_to :game
  has_many :players
  accepts_nested_attributes_for :players
  attr_accessible :name, :players_attributes
end

# models/player.rb
class Player < ActiveRecord::Base
  belongs_to :team
  has_many :stats
  accepts_nested_attributes_for :stats, reject_if: proc { |attributes| attributes['name'].blank? }
  attr_accessible :name, :stats_attributes
end

# models/stat.rb
class Stat < ActiveRecord::Base
  belongs_to :player
  attr_accessible :name
end

# controllers/games_controller.rb
class GamesController < ApplicationController
  def edit
    @game = Game.find(params[:id])
    @game.teams.each do |team|
      team.players.each do |player|
        player.stats.build
      end
    end
  end

  def update
    @game = Game.find(params[:id])
    if @game.update_attributes(params[:game])
      render "show"
    else
      render text: "epic fail"
    end
  end
end

# games/edit.html.erb
<%= form_for @game do |f| %>
  <%= f.fields_for :teams do |tf| %>
    <p>Team: <%= tf.object.name %></p>
    <%= tf.fields_for :players do |pf| %>
      <p>Player: <%= pf.object.name %></p>
      <%= pf.fields_for :stats do |sf| %>
        <%= sf.text_field :name %>
      <% end %>
    <% end %>
  <% end %>
  <%= f.submit %>
<% end %>

Note this doesn't do any sort of ajax "add another stat" or anything fancy. It just sticks one extra blank field at the end for each player. If you needed more, you could build more blank stat objects in the GamesController#edit action or implement some fancy pants javascript. Hopefully that will get you close enough to be able to get your real data working.

Upvotes: 1

DGM
DGM

Reputation: 26979

http://railscasts.com/episodes/196-nested-model-form-part-1

http://railscasts.com/episodes/197-nested-model-form-part-2

without seeing more of your own code, I can't be specific, but basically, you loop over all the players and "build" the stats... game.players.each {|p| p.build_stat} and then in the form, loop over all the players again, and display the stats (maybe limiting to the new_record? ones?) Or perhaps do the build right in the form so it shows a blank entry.

I think I see a potential problem though, with your models... If the stats are a specific representation of a specific game, then your model as you describe it doen't link them - you'd need a game_id and player_id in each stat record. If that were the case, you would build all the stats in the controller method, and loop over them in the view.

Upvotes: 0

Related Questions