Home > Net >  Ruby: How to add validation for a class field's << method
Ruby: How to add validation for a class field's << method

Time:10-20

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:

  1. Implement << directly on your Bla class, then use b << 'two':

    # in class Bla
    def <<(value)
      # do validation here
      @item << value
    end
    
  2. Use some other, nicer-named wrapper method name like add_item:

    # in class Bla
    def add_item(value)
      # do validation here
      @item << value
    end
    
  3. 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
  • Related