Search code examples
rubyoopblackjack

Method behaving differently for 2 classes using same module method


I had a previous question that I asked here: I (think) I'm getting objects returned when I expect my array to have just 2 properties available that may give some background. Having received a solution for that, I immediately moved to showing each player hand. The below module is included in both the Dealer and Player classes.

module Hand
   def show_hand
      if self.class == Dealer
         #Need to cover up 1 of the 2 cards here. Dealer doesn't show both!
         print "The dealer is showing: "
         print self.hand[0].show_card
         puts ''
      elsif self.class == Player
         print "You have: "
         self.hand.each do |item|
            item.show_card
         end
         puts ''
      else
         puts "A Random person is showing their hand."
      end
   end
end

I know this customization defeats the purpose of the module, just using it to reinforce the concept of modules. The above solution worked fine for the Dealer portion. But when the Player portion was called it printed a blank block. On a .inspect of each "item" in the Player block it confirmed that the items were in fact Card objects as expected. Here was the previous show_card method:

def show_card
    "[#{@card_type} of #{@suit}]"
end

So it just returned a string with the card_type and suit. I was able to fix the problem for the Player object portion just by changing the method to this:

def show_card
    print "[#{@card_type} of #{@suit}]"
end

Why was this happening? I'm assuming it has something to do with the call the "each" on the Player Hand. Really just curious what the difference was and why these Card objects wouldn't print without the explicit "print" in there vice returning via String object.

Hope I was descriptive enough. This one just baffles me and I'm really trying to grasp these little things since I know it will prevent future errors like this. Thanks!


Solution

  • In Ruby you must print with puts or print. Just returning the string doesn't print it. The reason your Dealer class prints is because you did a print, but in your Player class, as you noted, you had no print. You only returned the string without printing.

    As you noted, you were able to fix it by including the print:

    def show_card
      print "[#{@card_type} of #{@suit}]"
    end
    

    You could do this instead:

    def show_card
      "[#{@card_type} of #{@suit}]"
    end
    
    ...
    
    module Hand
      def show_hand
        if self.class == Dealer
          #Need to cover up 1 of the 2 cards here. Dealer doesn't show both!
          print "The dealer is showing: "
          puts self.hand[0].show_card   # PRINT THE CARD
        elsif self.class == Player
          print "You have: "
          self.hand.each do |item|
            print item.show_card  # PRINT THE CARD
          end
          puts ''
        else
          puts "A Random person is showing their hand."
        end
      end
    end
    

    Which would be a little more "symmetrical" and prints what you want.

    A slightly more compact would be:

    def show_card
      "[#{@card_type} of #{@suit}]"
    end
    
    ...
    
    module Hand
      def show_hand
        if self.class == Dealer
          #Need to cover up 1 of the 2 cards here. Dealer doesn't show both!
          puts "The dealer is showing: #{self.hand[0].show_card}"
        elsif self.class == Player
          print "You have: "
          self.hand.each { |item| print item.show_card }
          puts ''
        else
          puts "A Random person is showing their hand."
        end
      end
    end