Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

272
Visualizações
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 Respostas
Responde à pergunta

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 Relatório

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 Relatório

0

class Pit
  def <<(dirt)
    puts 'shovel ' + dirt
  end
end
Pit.new << 'sandy loam'
# => shovel sandy loam
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda