Could anybody help me with this error in the Tic tac toe exercise.
Failures:
-
Game switch_players! updates the value of current_player
Failure/Error: expect(game.current_player).to be(player_two)
expected #RSpec::70104697677760:Mocks::Double => #<RSpec::Mocks::Double:0x3fc2859a27c0 @name=“player”>
got #RSpec::70104697679980:Mocks::Double => #<RSpec::Mocks::Double:0x3fc2859a306c @name=“player”>
Compared using equal?, which compares object identity,
but expected and actual are not the same object. Use
expect(actual).to eq(expected)
if you don’t care about
object identity in this example.
Diff:
@@ -1,2 +1,2 @@
-#<RSpec::Mocks::Double:0x3fc2859a27c0 @name=“player”>
+#<RSpec::Mocks::Double:0x3fc2859a306c @name=“player”>
./spec/game_spec.rb:59:in `block (3 levels) in <top (required)>’
Finished in 0.02095 seconds (files took 0.12929 seconds to load)
28 examples, 1 failure
This is the error that is coming up from game spec.
Post your code for switch_players!
class Game
attr_accessor :board, :current_player, :player_one, :player_two
def initialize(player_one,player_two)
@board=Board.new
@player_one=player_one
@player_two=player_two
player_one.mark=:X
player_two.mark=:O
@current_player=player_one
end
def play_turn
move_one=current_player.get_move
self.board.place_mark(move_one,current_player.mark)
switch_players!
current_player.display(board)
end
def switch_players!
if current_player==player_one
current_player=player_two
else
current_player=player_one
end
end
end
Be sure to use the ‘@’ prefix for a Class’s instance variables!
Since you’re using attr_accessor, you don’t need to use @ before your instance variables, but when you’re setting the value of current_player
you need to include self.
. If you don’t, Ruby thinks you are creating a new local variable rather than reassigning an instance variable. To reassign current_player
you have to do either
self.current_player =
or
@current_player =
It’s probably less confusing just to use @ before all your instance variables like Luke said.
Thank you so much @ThaBullfrog and @Luke_Dreyer
Got it.
Hi Jeremiah,
I ran into the same error/concern originally posted by Natasha on this thread.
Given that I have used attr_accessor with current_player, is it really just behaving equivalent to attr_reader ? Based on your explanation above, any attempt to write to current_player (w/o the @ or self prefix) creates a new local variable and doesn’t modify/write the instance variable.
No, attr_accessor
acts like a combination of attr_reader
and attr_writer
.
attr_accessor :current_player
writes the following code for you:
def current_player
@current_player
end
def current_player=(value)
@current_player = value
end
It’s just, in order to call current_player=
, you need to include self.
. This is because you have to remove ambiguity between creating a new local variable, current_player
, and calling the method, current_player=
. They have the same syntax unless you include self.
Here’s how you call it:
self.current_player = @player_one
So attr_accessor
does create the writer method. This allows you to access the variable from outside the class like this:
game = Game.new
game.current_player = some_player
And it also gives you a writer method inside the class, but you have to call it with self.
1 Like