Dileet
Dileet

Reputation: 2074

Rails associated model id on create

I have 2 models, a sport model and a team model. The team model belongs_to :sport and the sport model has_many :teams.

Sport model:

class Sport < ActiveRecord::Base
    has_many :teams
    has_many :competitions
    has_many :games

end

Team Model:

class Team < ActiveRecord::Base
    belongs_to :sport
    has_many :competition_teams
    has_many :competitions, :through => :competition_teams
    has_many :home_games, :foreign_key => "home_team_id", :class_name => "Game"
    has_many :visiting_games, :foreign_key => "visiting_team_id", :class_name => "Game"
end

When a new team is created it must always associate with a sport. So for example if Hockey has an ID of 1, the team that is created under hockey must contain the sport ID. Below is the current schema:

  create_table "sports", force: true do |t|
    t.string   "name"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "teams", force: true do |t|
    t.string   "name"
    t.integer  "sport_id"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

This is the teams controller:

class TeamsController < ApplicationController
        before_action :set_team, only: [:show, :edit, :update, :destroy]

  # GET /games
  # GET /games.json
  def index
    @teams = Team.all
  end

  # GET /games/1
  # GET /games/1.json
  def show
  end

  # GET /games/new
  def new
    @team = Team.new
  end

  # GET /games/1/edit
  def edit
  end

  # POST /games
  # POST /games.json
  def create
    @team = Team.new(team_params)

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

  # PATCH/PUT /games/1
  # PATCH/PUT /games/1.json
  def update
    respond_to do |format|
      if @team.update(team_params)
        format.html { redirect_to @team, notice: 'team was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: 'edit' }
        format.json { render json: @team.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /games/1
  # DELETE /games/1.json
  def destroy
    @team.destroy
    respond_to do |format|
      format.html { redirect_to sports_url }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_team
      @team = Team.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def team_params
      params[:team].permit(:name, :sport_id)
    end

end

I tried to do the following in the routes:

resources :sports do
  resources :teams
end

But get an error when trying to create a team from the the following URL: /sports/1/teams/new

The error is: undefined method `teams_path' for #<#:0x007fafb4b9b0c0>

app/views/teams/_form.html.erb where line #1 raised:

Upvotes: 0

Views: 142

Answers (1)

vee
vee

Reputation: 38645

For your route setup:

resources :sports do
  resources :teams
end

You will need to use new_sport_team_path which will map to sports/:sport_id/teams/:id/new.

And in your app/view/teams/_form.html.erb, since your route is sports/:sport_id/teams, your form_for declaration should be:

<%= form_for @comment, url: sport_teams_path ... %>
...
<% end %>

In this case sport_teams_path will route to /sports/:sport_id/teams with post method which will execute the create action in your TeamsController.

The form_for declaration above can also be written as:

<%= form_for([@sport, @team]) ... %>
...
<% end %>

In this case you'd need to define @sport and @team in your controller as follows:

# app/controllers/teams_controller.rb
def new
  @sport = Sport.find(params[:sport_id])
  @team = @sport.teams.build
  ...
end

For a list of routes defined in your application, you could run rake routes from within your application directory in the terminal.

Upvotes: 1

Related Questions