Marco Song Marco Song - 1 month ago 6
Ruby Question

Why << method explicitly returns self helps method chaining?

I am reading Programming Ruby charpter of expressions.

class ScoreKeeper
def initialize
@total_score = @count = 0
end
def <<(score)
@total_score += score
@count += 1
self
end
def average
fail "No scores" if @count.zero?
Float(@total_score) / @count
end
end

scores = ScoreKeeper.new
scores << 10 << 20 << 40
puts "Average = #{scores.average}"


This produces

Average = 23.333333333333332


The book expains


Note that there’s a subtlety in this code—the << method explicitly
returns self. It does this to allow the method chaining in the line
scores << 10 << 20 << 40. Because each call to << returns the scores
object, you can then call << again, passing in a new score.


I still do not understand why return self to allow method chaining.

Anybody could help?

Answer

If you would not have returned self after @count += 1, having written scores << 2 << 1 you would end up in an error saying

undefined method << for Fixnum

This

scores = ScoreKeeper.new
scores << 10 << 20

works because scores << 10 returns the receiver, i.e. the object which has defined method << on it, eg scores. So it is possible to chain method calls.

Without self you would not be able to chain method calls, because the return value of << method would be a number.

EDIT

As per comment by Jörg W Mittag (assuming you are on Ruby 2.4.x):

Actually, it's even worse: << is defined for Integers, so you will not get an error, but rather a non-obviously wrong result. (Or more precisely, you will get an error later, when trying to call the non-existing Integer#average method.)