Topic: Foreign key in belongs_to is not saved

Hi,

I'm a newbie to rails and this problem is driving me nuts!

I know I'm missing something (perhaps very obvious) but I just don't seem to get it.
Upon successful creation of a 'game', I want to route to a form that creates a new scorecard.
But my foreign key in the scorecard table 'game_id' is always null.

I have the following two models:

class Game < ActiveRecord::Base  
   has_one :scorecard, :dependent => :destroy
end

class Scorecard < ActiveRecord::Base    
   belongs_to :game    
   has_many :skins, :dependent => :destroy    
   accepts_nested_attributes_for :skins
end

Scorecards has a foreign_key: 'game_id'

Here are my controllers:

class GamesController < ApplicationController
   def new
    @game = Game.new
    @game.build_scorecard
   end

   def create
     @game = Game.new(params[:game])
     
    respond_to do |format|
      if @game.save
        format.html { redirect_to :controller=>'scorecards', :action => 'new' }
      else
        format.html { render action: "new" }
        format.json { render json: @game.errors, status: :unprocessable_entity }
      end
    end
  end
class ScorecardsController < ApplicationController
   def new
    @scorecard = Scorecard.new
    8.times do
        skin = @scorecard.skins.build
        4.times { skin.overs.build }
    end
    
    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @scorecard }
    end
  end

def create
    @scorecard = Scorecard.new(params[:scorecard])    

    respond_to do |format|
      if @scorecard.save
        format.html { redirect_to @scorecard, notice: 'Scorecard was successfully created.' }
        format.json { render json: @scorecard, status: :created, location: @scorecard }
      else
        format.html { render action: "new" }
        format.json { render json: @scorecard.errors, status: :unprocessable_entity }
      end
    end
  end

At a point in time I tried the following lines in my ScorecardsController - create method:

@game = Game.find(params[:game_id])
@scorecard = @game.scorecard.create(params[:scorecard])

But that gave me errors on finding ID for Game

Here is what my routes.rb file looks like:

  resources :scorecards

  resources :games 

I tried:

    resources :games do
          resource :scorecard
    end

But that gave me errors on Get /assets which confused me even more sad

Can anyone please tell me what I'm doing wrong? I am so lost.

Last edited by aysh (2012-03-29 03:48:40)

Re: Foreign key in belongs_to is not saved

1. When you use the routes like that:

resources :games do
          resource :scorecard
    end

it means that you will be able to create a scorecard only in the context of a game.

2. When you are in 'create' action of ScorecardsController:

@scorecard = Scorecard.new(params[:scorecard]) 

doing like that, you get everything (all the parameters) you have in the form for scorecard object. If you do not have a game_id value in the 'params' hash, of course your game_id will never be set. So check it out first and come back with what you get from 'params' hash when saving a scorecard as well as with the code of scorecard 'new' view.

Last edited by Javix (2012-03-29 06:54:10)

Re: Foreign key in belongs_to is not saved

Hi Javix - so I'm trying to use routes like you have described in (1) and updated it accordingly.

To create the scorecard in context of a game I have edited my controllers as follows:

class GamesController < ApplicationController
  def new
    @game = Game.new
  
    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @game }
    end
  end

  def create
    @game = Game.new(params[:game])

    respond_to do |format|
      if @game.save
        format.html { redirect_to @game, notice: 'Game was successfully created.' }
        format.json { render json: @game, status: :created, location: @game }
      else
        format.html { render action: "new" }
        format.json { render json: @game.errors, status: :unprocessable_entity }
      end
    end
  end
end

And Scorecards controller create method looks like this:

def create
    @game = Game.find(params[:game_id])
    @scorecard = @game.create_scorecard(params[:scorecard])
    redirect_to game_path(@game)
end

And in the file: /app/views/games/show.html.erb file I have the following:

<p id="notice"><%= notice %></p>

<p>
  <b>Date played:</b>
  <%= @game.date_played %>
</p>

<p>
  <b>Opposition:</b>
  <%= @game.opposition %>
</p>

  <%= render "scorecards/form" %>

<%= link_to 'Edit', edit_game_path(@game) %> |
<%= link_to 'Back', games_path %>

and the /app/views/scorecards/_form.html.erb looks like this:

<%= form_for([@game, @game.build_scorecard]) do |f| %>
<div class="field">
    <%= f.label :team %>
    <%= f.text_field :team %>
  </div>
  <% count=0 %>
  <%= f.fields_for :skins do |builder| %>
    <% count += 1 %>
    <% team2 = :team2 %>
    <% render 'skins_fields', :f => builder, :count=>count%>
  <% end %>

  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

Updating all this results in an error that says:

NoMethodError in Games#show
undefined method `game_scorecards_path'


Extracted source (around line #1):
1: <%= form_for([@game, @game.build_scorecard]) do |f| %>
.....

Looking further down the page, I can see that the request parameters has {"id"=>"77"} - this must be the game_id right?

Can you please help me understand what I'm doing wrong now?
Is it something to do with plurals and singular?

Re: Foreign key in belongs_to is not saved

Ryan Bates explained very nice in his 2 screen casts how the nested forms work:

http://railscasts.com/episodes/196-nest … orm-part-1
http://railscasts.com/episodes/197-nest … orm-part-2

Just adapt it to your environment.

You can also see some explanations on Rails guides: http://guides.rubyonrails.org/association_basics.html