I understand how to implement a (validating) setter (def item=
), but how do I intercept the <<
operation on a field?
class Bla
attr_reader :item
def initialize
@item = []
end
# only called for =, =, -= operations (not <<)
def item=(value)
puts "Changing value to #{value}"
# pretend that there is a conditional here
@item = value
end
# This is wrong:
#def item<<(value)
# puts "adding value #{value}"
# @item << value
#end
end
b = Bla.new
b.item = ['one'] # works
b.item = ['one'] # works
b.item << 'two' # bypasses my setter
I've tried def item<<(value)
, that doesn't seem to work.
CodePudding user response:
When you call b.item << 'two'
, you are calling the <<
method on item
directly. So you have a few options here:
Implement
<<
directly on yourBla
class, then useb << 'two'
:# in class Bla def <<(value) # do validation here @item << value end
Use some other, nicer-named wrapper method name like
add_item
:# in class Bla def add_item(value) # do validation here @item << value end
Use a special array class for
@item
which has a custom definition for<<
:class MyArray < Array def <<(item) # run validation here super end end # in Bla class def initialize @item = MyArray.new end
I would probably go with option 2, it's the most simple and readable.
CodePudding user response:
class Pit
def <<(dirt)
puts 'shovel ' dirt
end
end
Pit.new << 'sandy loam'
# => shovel sandy loam