SeattleDucati
SeattleDucati

Reputation: 293

Rails - NoMethodError in index view, trying to understand ActiveRecord associations

I will post all of relevent files below, first let me explain the problem. I have 3 models, Players, Teams and Ownerships. Players and Team both own Ownership. Players have a :team through their relationship with Ownerships (has_one :team, through: :ownership).

If I display a Player using the show action, I can access all of the attributes of Team, including the logo that is a paperclip attachment.

If I display all of the Players using the index action, I cannot access any of the Team attributes. If I display the team like this, <%= player.team %> , it displays an object reference like this #Team:0x007fef0b68cb10. If I try and access attributes for Team, <%= player.team.name %>, I get:

NoMethodError in Players#index undefined method `name' for nil:NilClass

My question is this: How can I create an index method for Players so that I can display the attributes for Team in the index view?

I have tried changing my index method to the following:

def index
@players = Player.all.sort_by{ |x| [x.position, x.last_name] }
@Team = Player.team  
end

but it fails with

 undefined method `team' for #

The models:

class Player < ActiveRecord::Base
has_one :team, through: :ownership
has_one :ownership

validates :name, presence: true
validates :position, presence: true

def last_name
self.name.split(' ')[1]
end
end

class Ownership < ActiveRecord::Base
belongs_to :player
belongs_to :team

validates :round, :pick, :team_id, presence: true
end

class Team < ActiveRecord::Base
has_many :ownerships
has_many :players, through: :ownerships 

validates :name, presence: true
validates :division, presence: true

 has_attached_file :logo , :styles => { :small => '10>', :medium => '40>', :large => '60>' }
 validates_attachment_content_type :logo, :content_type => ["image/jpg", "image/jpeg", "image/png", "image/gif"]
 end

The Players Controller:

 class PlayersController < ApplicationController
 def index
 @players = Player.all.sort_by{ |x| [x.position, x.last_name] }
 end

 def not_picked
 @players = Player.all.select { |m| m.team == nil}.sort_by{ |x| [x.position, x.last_name] }
 end

 def show
  @player = Player.find(params[:id])
 end

 private

 def player_params
 params.require(:player).permit(:name, :position)
 end
 end

The relevant part of the Players index.html.erb:

  <% @players.each do |player| %>
   <tr>
   <td></td>
    <td><%= link_to player.name, player %></td>
    <td><%= player.position %></td>
    <td><%= player.team.name %> </td> <!--This throws the error -->

The Players show.html.erb (works fine):

 <%= render 'welcome/menu' %>

 <%= @player.name %>

 <%= @player.team.name %>

 <%= @player.ownership.pick %>

 <%= @player.ownership.round %>

Upvotes: 1

Views: 196

Answers (1)

K M Rakibul Islam
K M Rakibul Islam

Reputation: 34338

Seems like, some of your players don't have an associated team, so player.team is nil for them. And, in that case it's failing to get the team name with the error message:

NoMethodError in Players#index undefined method `name' for nil:NilClass

Try to use try by changing:

<td><%= player.team.name %>

To:

<td><%= player.try(:team).try(:name) %>

And, Player.team is wrong, you can't do that as you did not define any class method team in Player class.

Upvotes: 1

Related Questions