3

How do I implement the '<<' to have the same behavior when used as a chainable method?

class Test
  attr_accessor :internal_array

  def initialize
    @internal_array = []
  end

  def <<(item)
    @internal_array << :a
    @internal_array << item
  end
end

t = Test.new
t << 1
t << 2
t << 3
#t.internal_array => [:a, 1, :a, 2, :a, 3]
puts "#{t.internal_array}" # => a1a2a3

t = Test.new
t << 1 << 2 << 3
#t.internal_array => [:a, 1, 2, 3]
puts "#{t.internal_array}" # => a123 , Why not a1a2a3?

I want both cases giving the same result.

2 Answers 2

4

Add self as the last line in the << method to return it. As is, you're implicitly returning the array, not the instance.

Sign up to request clarification or add additional context in comments.

Comments

0

Explanation of the answer above:

When a method is chained, the next method is applied to the result of the first method.

For exemplo:

class A
  def method1
    B.new
  end
end

class B
  def method2
    C.new
  end
end

class C
  def method3
    puts "It is working!!!"
  end
end

The code below will work

A.new.method1.method2.method3

but the this will not

A.new.method1.method3.method2

because an instance of class B, which is the result of A.new.method1 doesn't implement method3. This is the same of:

(((A.new).method1).method3).method2

The code used in the question above, was a little bit more trick, because both, Test and Array had the method <<. But I want Test#<< to return self, and not the @internal_array that was being returned.

2 Comments

Is this supposed to be an answer to your question? I'm confused.
It is the explanation of the answer above. The short answer was given by Matthew: add self at the...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.