I have revised the question yet again to include the controller files.
In our app we have three models. A User model, Scoreboard model, Team model. A User has_many scoreboards and a scoreboard belongs_to a User. The code in the scoreboards controller for the create action that associated the two is "@scoreboard = current_user.scoreboards.build". This code works perfectly fine.
Now, the problem arises with the third model. The scoreboard model has_many teams and each team belongs_to a scoreboard. It is a has_many, belongs_to relationship. Therefore, the foreign key is on the teams table. The scoreboard and team migration and model files are given below respectively.
Scoreboard Model
class Scoreboard < ActiveRecord::Base
belongs_to :user
has_many :teams, dependent: :destroy
default_scope -> { order(created_at: :desc) }
end
Scoreboard Migration
class CreateScoreboards < ActiveRecord::Migration
def change
create_table :scoreboards do |t|
t.string :name_of_scoreboard
t.string :name_of_organization
t.string :name_of_activity
t.references :user, index: true
t.timestamps null: false
end
add_foreign_key :scoreboards, :users
add_index :scoreboards, [:user_id, :created_at]
end
end
Team Model
class Team < ActiveRecord::Base
belongs_to :scoreboard
end
Team Migration
class CreateTeams < ActiveRecord::Migration
def change
create_table :teams do |t|
t.string :name
t.integer :win
t.integer :loss
t.integer :tie
t.references :scoreboard, index:true
t.timestamps null: false
end
add_foreign_key :teams, :scoreboards
end
end
I think I have associated the models correctly. Therefore, the code in my Teams controller for the create action should create the associations correctly. The controllers are as follows:
Scoreboard controller:
class ScoreboardsController < ApplicationController
before_action :logged_in_user, only: [:new, :create, :show, :index]
before_action :correct_user, only: [:destroy, :edit, :update]
def new
@scoreboard = Scoreboard.new
end
def create
@scoreboard = current_user.scoreboards.build(scoreboard_params)
if @scoreboard.save
flash[:scoreboard] = "Scoreboard created successfully"
redirect_to scoreboard_path(@scoreboard)
else
render 'new'
end
end
def show
@scoreboard = Scoreboard.find_by_id(params[:id])
end
def index
if params[:search]
@scoreboards = Scoreboard.all.search(params[:search])
else
@scoreboards = current_user.scoreboards
end
end
def edit
@scoreboard = Scoreboard.find_by_id(params[:id])
end
def update
@scoreboard = Scoreboard.find_by_id(params[:id])
if @scoreboard.update_attributes(scoreboard_params)
flash[:success] = "Updated Successfully"
redirect_to scoreboard_path(@scoreboard)
else
render 'edit'
end
end
def destroy
@scoreboard = Scoreboard.find_by_id(params[:id])
@scoreboard.destroy
flash[:success] = "Deleted Successfully."
redirect_to scoreboards_path
end
private
def scoreboard_params
params.require(:scoreboard).permit(:name_of_scoreboard, :name_of_organization,
:name_of_activity, :starts_at, :ends_at, :cities, :states, :country, :picture )
end
def correct_user
@user = Scoreboard.find(params[:id]).user
redirect_to scoreboards_path unless current_user?(@user)
end
end
And this is the teams controller:
class TeamsController < ApplicationController
def new
@team = Team.new
end
def create
@scoreboard= current_user.scoreboards.build
@team = @scoreboards.teams.build(team_params)
if @team.save
flash[:success] = "Saved Successfully"
redirect_to scoreboard_path
else
render 'new'
end
end
def index
end
def show
end
private
def team_params
params.require(:team).permit(:name, :win, :loss, :tie)
end
end
However, I get an error "undefined method `teams' for nil:NilClass" when I submit my form which applies the create action. I am not sure why this is happening because I did the exact same thing with the Users and Scoreboard model.
There are many ways in Rails to create associated records via user input. Let's assume in this case that you only want to create teams in the context of a scoreboard.
The first thing we want to do is nest the teams routes under a scoreboard:
This will give us routes to create teams which are nested:
Why?, because this gives a RESTful design where it is very obvious that you are creating a nested resource. Nesting the index route is really optional.
If you want a non nested index which displays all the teams regardless of scoreboard you would define the routes as such:
As you alread have guessed we want to build a
Team
instance inScoreboards#show
We also need to add a team form to the scoreboard. Let's use a reusable partial for this:
Notice
@team.new_record? ? [@scoreboard, @team] : @team
. We use the ternary operator (a compact if statement) so that the form routes correctly both for a new record and when editing a record.So in our
TeamsController
we want to setup a callback to load the Scoreboard fromparams[:schoolboard_id]
so that we can use it our new and create action.I fixed up my answer in response to your question:
I think that your associations are correct and maybe try using @scoreboard instead of scoreboard. So something like this maybe?