Csteele5
Csteele5

Reputation: 1292

Rails has_many undefined method for association

I have two objects: Team and Player. As you could probably guess, a Team has many Players and a Player belongs to a team.

I understand that we can model this relationship with another model, Team_Players but I want to focus on the raw relationship here, as shown by many of the guides I'm seeing online.

When creating Players, it's easy to assign them a Team.id, since they only have one, but the reverse -has_many- is more complicated. The Rails guide on associations only shows the model file, so this is what mine looks like in reflection:

class Team < ActiveRecord::Base
  has_many :players
end

Now, I would expect to be able to do something like Team.first.players and be given an array or something, but instead I just get undefined method player for #<Team:0x> and in fact in this video, I do see a developer doing something just like that. So what am I missing? Do I have to make an intersection model here? I would imagine not since has_many is inherent in Rails.

After creating the tables, I added the reference for Team to Player in this migration:

def change
  add_reference :players, :team, index: true
  add_foreign_key :players, :team
end

Again, since the has many relationship can't be modeled with a single column, I avoided that part in the migration. Is that what's necessary for the desired functionality of Team.first.players returning an array or something?

Upvotes: 2

Views: 4343

Answers (1)

Ryan Clark
Ryan Clark

Reputation: 764

Here's what I did to get this to work:

rails new teams - followed by bundle

rails g model Team name:string player_count:integer

rails g model Player player_name:string player_number:integer

rails g migration add_team_id_to_players:

class AddTeamIdToPlayers < ActiveRecord::Migration
  def change
    add_column :players, :team_id, :integer
  end
end

rake db:migrate

Here are my models:

class Player < ActiveRecord::Base
  belongs_to :team
end

class Team < ActiveRecord::Base
  has_many :players
end

Then, in the console:

Team.create(name: "Cats", player_count:1).save

Player.create(player_name: "Ryan", player_number:1, team_id:1).save

Then voila:

Team.first.players returns:

Team Load (0.2ms)  SELECT  "teams".* FROM "teams"  ORDER BY "teams"."id" ASC LIMIT 1
Player Load (0.1ms)  SELECT "players".* FROM "players" WHERE "players"."team_id" = ?  [["team_id", 1]]
=> #<ActiveRecord::Associations::CollectionProxy [#<Player id: 2, player_name: "ryan", player_number: 1, created_at: "2015-12-18 19:32:39", updated_at: "2015-12-18 19:32:56", team_id: 1>]>

Upvotes: 1

Related Questions