rj487
rj487

Reputation: 4634

Rails: many to many Model, NoMethodError: undefined method

I am stuck with this question for a while.

Here is my model relationship.

class Game < ActiveRecord::Base
    has_many :participates , :dependent => :destroy
    has_many :players, through: :participates, :dependent => :destroy
end

class Player < ActiveRecord::Base
    has_many :participates , :dependent => :destroy
    has_many :games, through: :participates, :dependent => :destroy
end

class Participate < ActiveRecord::Base
  belongs_to :player
  belongs_to :game
end

And I put this in seed.rb

Player.destroy_all
Game.destroy_all
g1 = Game.create(game_name: "LOL")
g2 = Game.create(game_name: "DOTA")
p1 = Player.create(player_name: "Coda", games: [g1,g2]);
p2 = Player.create(player_name: "Nance", games: [g2]);

When I was using rails console, model Participate works fine. It can found game and player relatively, but following commands threw error.

[53] pry(main)> Game.first.players
  Game Load (0.4ms)  SELECT  `games`.* FROM `games`  ORDER BY `games`.`id` ASC LIMIT 1
    NoMethodError: undefined method `players' for #<Game:0x007fd0ff0ab7c0>
    from /Users/Coda/.rvm/gems/ruby-2.1.3@rails416/gems/activemodel-4.2.3/lib/active_model/attribute_methods.rb:433:in `method_missing'


[56] pry(main)> Player.first.games
      Player Load (0.4ms)  SELECT  `players`.* FROM `players`  ORDER BY `players`.`id` ASC LIMIT 1
    NoMethodError: undefined method `games' for #<Player:0x007fd0fd8a7cf0>
    from /Users/Coda/.rvm/gems/ruby-2.1.3@rails416/gems/activemodel-4.2.3/lib/active_model/attribute_methods.rb:433:in `method_missing'

Upvotes: 5

Views: 1158

Answers (1)

Richard Peck
Richard Peck

Reputation: 76774

Firstly, restart your console

If you make any model / code changes whilst running in the console, it will only work again when you restart.

Also, are you sure you seeded your db - with rake db:seed?


Your code looks okay; the two reasons why I presume this would be an issue would be the following:

  1. You're calling participates (maybe you'd be better calling it participants)
  2. You need to make sure you have data in your associative models

Here's what I'd do:

#app/models/game.rb
class Game < ActiveRecord::Base
   has_many :participants
   has_many :players, through: :participants
end

#app/models/participant.rb
class Participant < ActiveRecord::Base
   belongs_to :game
   belongs_to :player
end

#app/models/player.rb
class Player < ActiveRecord::Base
   has_many :participations, class_name: "Participant"
   has_many :games, through: :participations
end

This should avert any potential naming errors.


Next, you need to make sure you have the data in your models.

I've used many-to-many a number of times; each time I've found that you need to have data in the associative model in order for it to work.

$ rails c
$ g = Game.first
$ g.players

If this doesn't output any collection data, it will mean your associations are either empty or misrepresented.

This could be a cause of your issue but to be honest, I don't know. To make sure it works, you may wish to populate Participant directly:

$ rails c
$ g = Game.first
$ p = Player.first
$ new_participation = Participant.create(player: p, game: g)

If this doesn't work, it could be a deeper issue with ActiveRecord etc.

Upvotes: 6

Related Questions