Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

274
Vistas
Ruby: How to add validation for a class field's << method

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.

over 4 years ago · Santiago Trujillo
3 Respuestas
Responde la pregunta

0

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.

over 4 years ago · Santiago Trujillo Denunciar

0

Here is an alternate suggestion:

class Bla 
  # DO NOT DEFINE A READER:
  # attr_reader :item

  def initialize
    @items = []
  end

  def set_items(new_items)
    puts "Changing value to #{new_items}"
    # pretend that there is a conditional here
    @items = new_items
  end

  def remove_item(item)
    # pretend that there is a conditional here
    @items -= items
  end

  def add_item(item)
    # pretend that there is a conditional here
    @items += items
  end
end

By not exposing the @items object directly, you remain in full control of the interface for how the variable is manipulated.

(Unless a caller does something really hacky, like bla.instance_variable_get('@items')!!)

over 4 years ago · Santiago Trujillo Denunciar

0

class Pit
  def <<(dirt)
    puts 'shovel ' + dirt
  end
end
Pit.new << 'sandy loam'
# => shovel sandy loam
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda