-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Aisha's RPS Challenge #2128
base: main
Are you sure you want to change the base?
Aisha's RPS Challenge #2128
Conversation
|
||
|
||
feature "player has lost against the computer" do | ||
scenario "When player plays paper" do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tests look good and comprehensive, nice one!
def initialize | ||
@rules = { | ||
Rock: { Rock: :draw, Paper: :lose, Scissors: :win }, | ||
Paper: { Rock: :win, Paper: :draw, Scissors: :lose }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really like this way of going about determining the rules of the game
|
||
get '/play' do | ||
@username = session[:username] | ||
@game = $game |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is $game variable used or needed?
|
||
$final_result = FinalResult.new | ||
$final_result.calculate(@player_option, @computer_option) | ||
@final_result = $final_result.winner |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could the @final_result variable go into a separate get route and have /game redirect to it (either as a post or get)? The global $final_result can stay in /game if needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really nice work - I left a few comments here and there to improve mainly the testing and stubbing side of things, and some of the code design in a few places. Let me know if you have any questions on the feedback!
end | ||
|
||
def winner | ||
return "Congratulations! You won, you beat the computer!" if @result == :win |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than having human-readable messages returned by this class, it might be better to let this responsibility to the view (in the .erb file) to have all the content / text displayed to the user. This way, it becomes easier to change it, if we want to change the text displayed, translate it in other languages, etc. The method winner
could then return either the result directly (:win
, :lose
, etc), and the the message to display would be part of the view layer
session[:computer] = Computer.new(["Rock", "Paper", "Scissors"]) | ||
@computer_option = session[:computer].option | ||
|
||
$final_result = FinalResult.new |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the object FinalResult.new
doesn't need to be accessed in a different route (which seems to be the case, as it's used only to calculate the result and chose the winer), it's probably good to avoid making it a global variable (it's generally best to avoid using global variables unless there is a need to):
final_result = FinalResult.new
final_result.calculate(@player_option, @computer_option)
@final_result = $final_result.winner
Maybe the name of the class could be changed to FinalResultCalculator
as well, to avoid mixing up that object with the result value itself?
@@ -0,0 +1,5 @@ | |||
def sign_in_and_play | |||
visit('/') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice use of a helper method here - a way to make it better could be to pass the player name as an argument, this way it becomes more explicit, when used in tests, what name is going to be used:
sign_in_and_play('Aisha')
click_button 'Rock'
expect(page).to have_content "Aisha played Rock"
<html> | ||
<head> | ||
</head> | ||
<style> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's usually best to indent the HTML code, so it's easier to read - this becomes really useful when dealing with larger and more complex HTML pages! You can use a VS code extension (or similar) to auto indent the code when editing HTML files
@@ -0,0 +1,22 @@ | |||
feature "display computer's option" do | |||
scenario "when computer plays rock" do | |||
allow_any_instance_of(Array).to receive(:sample).and_return 'Rock' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than stubbing the return of Array.sample
(which could be dangerous, as this would modify the behaviour of the Array's sample
method for every single array used in your programs, even libraries, etc) - prefer stubbing a method of your own class you have more control of. For example, you could create a new method in Computer
, called get_random_move
, which would wrap the call to .sample
- and then stub this method's return value
context "and has won the game" do | ||
it "it returns winning message" do | ||
comp = Computer.new(["Rock", "Paper", "Scissors"]) | ||
allow(comp).to receive(:option).and_return("Scissors") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here, because you're passing directly the value of option
to the method .calculate
, it's not needed to stub the return value of comp.option
, because you could directly give the plain string value to .calculate
:
final_result.calculate(player.option, "Scissors")
Stubbing would be useful in the case we'd inject the whole instance comp
into that class, and then the method would be called by that class later on
Completed the first group of user stories, need to refactor code and add to README.md