1
votes

I have a test class and a box class, in the test class i have a var called boxHolder, which is an array, i want to override the << method for this array. Inside the singleton how can i access moski_call ?

class Test
  attr_accessor :boxHolder

  def initialize()
   super
   self.boxHolder = Array.new

   class << @boxHolder
     def <<(box)
       box.setPositionWithinColumn(moski_call)
       super(box)
     end
   end
  end   

  def moski_call
    "YAAAAAAAAAAAAAAAAAAAA"
  end
end

class Box
  def initialize
  end

  def setPositionWithinColumn(str)
    puts "got a string #{str}"
  end
end

# test
box = Box.new
test = Test.new
test.boxHolder 
3
By convention, rubyists don't use camelCase; it's box_holder, not boxHolder, etc...Marc-André Lafortune

3 Answers

0
votes

What about:

def self.boxHolder.<< (box)
   box.setPositionWithinColumn(moski_call)
   super(box)
end     

This would declare a method for your instance boxHolder. But boxHolder does not have access to the method moski_call

0
votes

like this:

# need this or else `moski_call` method is looked up in context of @boxholder
moski_call_output = moski_call

class << @boxholder; self; end.send(:define_method, :<<) { |box| 
     box.setPositionWithinColumn(moski_call_output)
     super(box)
}
0
votes

You need to maintain access to the "parent" Test object. This can be done using the fact that blocks are closures:

parent = self # to be accessible in the closure

@boxHolder.define_singleton_method(:<<) do |box|
  box.setPositionWithinColumn(parent.moski_call)
  super(box)
end

Note: define_singleton_method is new in Ruby 1.9, so either upgrade, require 'backports/1.9.1/kernel/define_singleton_method' or do class << @boxHolder; define_method(:<<){ "..." } end if using an older Ruby.