Hmejia in the Bay
Hmejia in the Bay

Reputation: 23

Why do I get an extra trailing space and how to get rid of it?

I am new to ruby and I can't understand why I after running this code I get an extra empty line as a result as a part of the output. I am using Ruby 2.5.3

class Card
  attr_accessor :rank, :suit

  def initialize(rank,suit)
    @rank = rank
    @suit = suit
  end

  def output_card
    puts "#{self.rank} of #{self.suit}"
  end

  def self.random_card
    suit = ["hearts", "spades", "clubs", "diamonds"]
    Card.new(rand(1..13), suit.sample)
  end
end

class Deck
  def initialize
    d = 0
    @cards =[]
    while d < 13
      @cards << Card.random_card
      d += 1
    end
  end

  def shuffle
    @cards.shuffle!
  end

  def output
    @cards.each do |card|
      card.output_card
    end
  end

  def deal
    self.shuffle
    dealing = @cards.shift
    puts "#{dealing.output_card}"
  end
end

deck = Deck.new
deck.deal

The above will give me this result:

[ENV]:/vagrant/OOP $ ruby card.rb
6 of clubs

[ENV]:/vagrant/OOP $

As you can see there is an extra line, and I don't understand why.

Upvotes: 0

Views: 39

Answers (1)

fphilipe
fphilipe

Reputation: 10054

From the docs of puts:

Writes a newline after any that do not already end with a newline sequence.

In Deck.deal you have puts "#{dealing.output_card}". Card#output_card is defined as:

def output_card
  puts "#{self.rank} of #{self.suit}"
end

I.e., Card#output_card is already printing with a new line at the end. The return value of this method, which is the return value of puts, which in turn per the docs is nil, is then printed in Deck.deal, resulting in an empty line being printed.

In short, you're printing twice, where the second puts results in the additional line.

I suggest you remove puts from Card as it should not have a notion of printing itself. That's the job of Deck. I would change Card#output_card to be Card#to_s and just return the string you're constructing rather than putsing it. Then you can rely on the fact that puts will call #to_s on the object being printed.

class Card
  # ...

  def to_s
    "#{self.rank} of #{self.suit}"
  end

  # ...
end

class Deck
  # ...

  def output
    @cards.each do |card|
      puts card
    end
  end

  def deal
    self.shuffle
    puts @cards.shift
  end
end

Upvotes: 0

Related Questions