Verificando se uma variável não é nula e não é zero em ruby


271

Estou usando o código a seguir para verificar se uma variável não é nula e não é zero

if(discount != nil && discount != 0) 
  ...
end

Existe uma maneira melhor de fazer isso?


1
Provavelmente porque é uma cópia exata de stackoverflow.com/questions/209495/… .
David Nehme

1
O que deve fazer se discountfor falso?
Andrew Grimm

1
Eu acho que discount.in? [0, nil]a maneira mais limpa possível
intmarinoreturn0

Respostas:


428
a menos que discount.nil? || desconto == 0
  # ...
fim

31
Use 'ou' em vez de ||
Orion Edwards

93
@ orion-edwards por quê?
NARKOZ

39
Usar 'ou' é perigoso. 'ou' tem menor presendence operador de '=', então o seguinte tem um comportamento inesperado: A = falsa ou verdadeira #a é falsa após esta declaração
Tom G

20
@xiy atualmente o guia recomenda fingindo ou ee não existem (|| é que ou && e?)
user3125280

67
O "Guia de estilo Ruby" atual está disponível The and and or keywords are banned. It's just not worth it. Always use && and || instead.. E está certo, por razões de David e Tom.
Andre Figueiredo

40
class Object
  def nil_zero?
    self.nil? || self == 0
  end
end

# which lets you do
nil.nil_zero? # returns true
0.nil_zero?   # returns true
1.nil_zero?   # returns false
"a".nil_zero? # returns false

unless discount.nil_zero?
  # do stuff...
end

Cuidado com as isenções de responsabilidade usuais ... grande poder / responsabilidade, remendos de macacos levando ao lado sombrio etc.


28

ok, depois de 5 anos se passaram ....

if discount.try :nonzero?
  ...
end

É importante observar que isso tryé definido na gema do ActiveSupport, portanto não está disponível em ruby ​​comum.


7
Observe que esta é uma resposta específica dos trilhos . O rubi de baunilha não possui um trymétodo.
Tom Lord

Corrigir. Embora seja mais parecido com o ActiveSupport, que é uma dependência muito mais leve e amplamente usada que os trilhos completos. De qualquer forma, agora a resposta do @ ndn é a correta.
reescrito

Editado para usar a navegação segura
reescrito

1
A resposta agora duplica o stackoverflow.com/a/34819818/1954610 ... Acho tryque vale a pena deixá-lo como uma opção alternativa (por isso foi votado em primeiro lugar!), Desde que seja claro para o leitor que ActiveSupportnão é baunilha rubi.
Tom Lord

Ponto tomado, resposta revertida.
reescrito


23

A partir do Ruby 2.3.0 em diante, você pode combinar o operador de navegação segura ( &.) com Numeric#nonzero?. &.retorna nilse a instância foi nile nonzero?- se o número foi 0:

if discount&.nonzero?
  # ...
end

Ou postfix:

do_something if discount&.nonzero?

"foo"&.nonzero? # => NoMethodError: undefined method 'nonzero?' for "foo":String.... Isso não é seguro para uso em objetos arbitrários.
Tom Lord

2
O @TomLord, como declarado no comentário anterior, não tinha como objetivo trabalhar com objetos arbitrários. Em vez disso, trata-se do caso em que você tem algo que sabe que deve ser um número, mas também pode ser nil.
Ndnenkov 6/06

Eu deixaria esse fato claro na resposta, em vez de alguém ler isso sem avisar nos comentários.
Tom Lord

@ TomLord, é indicado na resposta " nonzero?- se o número for 0" . Além disso, a necessidade de verificar se um objeto completamente arbitrário 0surge muito raramente em comparação com o de verificar um número que pode ou não ser nil. Por isso, está quase implícito. Mesmo que alguém de alguma forma faça a suposição contrária, entenderá instantaneamente o que está acontecendo quando tentarem executá-lo.
Ndnenkov 06/06


15

Você pode fazer isso:

if (!discount.nil? && !discount.zero?)

A ordem é importante aqui, porque se discountfor nil, ela não terá um zero?método. A avaliação de curto-circuito de Ruby deve impedir que tente avaliar discount.zero?, no entanto, se discounté nil.


11

Você pode converter sua linha vazia em valor inteiro e marcar zero?

"".to_i.zero? => true
nil.to_i.zero? => true

cuidado: 0.1.to_i == 0
Simon B.

3
if discount and discount != 0
  ..
end

atualização, será falseparadiscount = false


2

Você pode tirar proveito do método NilClassfornecido #to_i, que retornará zero para nilvalores:

unless discount.to_i.zero?
  # Code here
end

Se discountpode ser um número fracionário, você pode usá-lo #to_fpara impedir que o número seja arredondado para zero.


Não é o mesmo que a resposta de @ oivoodo?
Cary Swoveland

Não funciona para objetos arbitrários . "".to_i == "foo".to_i == "0".to_i == 0. Seu método fará todo tipo de coerção não intencional. Também falhará com um NoMethodErrorse discountnão responder to_i.
Tom Lord

2
def is_nil_and_zero(data)
     data.blank? || data == 0 
end  

Se passarmos "", ele retornará falso, enquanto em branco? retorna verdadeiro. É o mesmo caso quando data = false em branco? retorna verdadeiro para nulo, falso, vazio ou uma cadeia de espaços em branco. Então é melhor usar branco? método para evitar string vazia também.


1
blank?é um método específico para trilhos e não está disponível no vanilla ruby.
Tom Lord

Você está certo!! Eu pensei que isso está relacionado à tag "ror", postada aqui. Meu erro. Isso não vai funcionar em baunilha rubi.
Saroj

1

Ao lidar com um registro de banco de dados , gosto de inicializar todos os valores vazios com 0, usando o assistente de migração:

add_column :products, :price, :integer, default: 0

0

Você pode inicializar o desconto para 0, desde que o seu código esteja garantido para não tentar usá-lo antes de ser inicializado. Isso removeria uma verificação, suponho, não consigo pensar em mais nada.



0

Eu prefiro usar uma abordagem mais limpa:

val.to_i.zero?

val.to_iretornará a 0se val for a nil,

Depois disso, tudo o que precisamos fazer é verificar se o valor final é zero .


-1

Solução alternativa é usar refinamentos, da seguinte forma:

module Nothingness
  refine Numeric do
    alias_method :nothing?, :zero?
  end

  refine NilClass do
    alias_method :nothing?, :nil?
  end
end

using Nothingness

if discount.nothing?
  # do something
end

-7

Eu acredito que o seguinte é bom o suficiente para o código ruby. Eu não acho que poderia escrever um teste de unidade que mostre alguma diferença entre isso e o original.

if discount != 0
end

8
Seria avaliar truese o desconto fosse nil.
Andrew Grimm
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.