Muitas vezes ao longo da carreira como desenvolvedor me deparei com situações em que precisei avaliar se uma consulta ao banco retornava apenas um objeto para executar uma determinada ação e para isso era necessário adicionar alguma validação com count
, first
ou last
Para simplificar essas verificações nasce o método sole
, que verifica a presença de exatamente um item na coleção. Vamos ver alguns exemplos:
irb > array = ['Ruby']
=> ["Ruby"]
irb > array.sole
=> "Ruby"
irb> array = ['Ruby', 'Rails']
=> ["Ruby", "Rails"]
irb> array.sole
Traceback (most recent call last):
Enumerable::SoleItemExpectedError (multiple items found)
irb > array = []
=> []
irb > array.sole
Traceback (most recent call last):
Enumerable::SoleItemExpectedError (no item found)
Como você pode notar, esse método apresenta mensagens de erro distintas para quando o resultado é zero ou maior que um.
Esse método também funciona para queries, podendo ser usado da seguinte forma:
irb > Product.where("price = %?", price).sole
# ActiveRecord::RecordNotFound (Se não encontrar nada)
# <Product ...> (Se encontrar exatamente um)
# ActiveRecord::SoleRecordExceeded (Se encontrar mais de um)
Esse novo método, que ficará disponível na versão 7 do Rails, foi o esforço de algumas contribuições:
Vale lembrar que a implementação do sole
usa o método first
, por essa razão, dependendo do caso, o retorno para alguns tipos de dados pode não ser interessante. Um exemplo com Hash:
irb > hash = { a: 1 }
=> {:a=>1}
irb > hash.sole
=> [:a, 1]
Esse método pode simplificar o entendimento de muitas queries que tem que incluir uma camada de lógica para verificar a quantidade de elementos.
Bom código!