O que é uma maneira simples / elegante em Ruby para dizer se uma variável específica é um Hash ou um Array?

Para verificar o que é @some_var , estou fazendo um

 if @some_var.class.to_s == 'Hash' 

Tenho certeza de que existe uma maneira mais elegante de verificar se @some_var é uma Hash ou uma Array .

Você pode apenas fazer:

 @some_var.class == Hash 

ou também algo como:

 @some_var.is_a?(Hash) 

Vale a pena notar que o “is_a?” O método é verdadeiro se a class estiver em qualquer lugar na tree de ancestralidade dos objects. por exemplo:

 @some_var.is_a?(Object) # => true 

o acima é verdadeiro se @some_var for uma instância de um hash ou outra class derivada de Object. Então, se você quiser uma correspondência estrita no tipo de class, usando == ou instance_of? método é provavelmente o que você está procurando.

Primeiro de tudo, a melhor resposta para a questão literal é

 Hash === @some_var 

Mas a questão realmente deveria ter sido respondida mostrando como fazer a digitação de pato aqui. Isso depende um pouco do tipo de pato que você precisa.

 @some_var.respond_to?(:each_pair) 

ou

 @some_var.respond_to?(:has_key?) 

ou até mesmo

 @some_var.respond_to?(:to_hash) 

pode estar certo, dependendo da aplicação.

Geralmente em ruby ​​quando você está procurando por “type” você está realmente querendo o “duck-type” ou “does is quack like a duck?”. Você veria se ele responde a um determinado método:

 @some_var.respond_to?(:each) 

Você pode iterar em @some_var porque responde a: cada

Se você realmente quer saber o tipo e se é Hash ou Array então você pode fazer:

 ["Hash", "Array"].include?(@some_var.class) #=> check both through instance class @some_var.kind_of?(Hash) #=> to check each at once @some_var.is_a?(Array) #=> same as kind_of 
 Hash === @some_var #=> return Boolean 

isso também pode ser usado com a declaração de caso

 case @some_var when Hash ... when Array ... end 

Eu uso isso:

 @var.respond_to?(:keys) 

Ele funciona para Hash e ActiveSupport :: HashWithIndifferentAccess.

Você pode usar instance_of?

por exemplo

 @some_var.instance_of?(Hash) 

Na prática, muitas vezes você vai querer agir de forma diferente, dependendo se uma variável é uma matriz ou um hash, e não apenas um mero tell. Nesta situação, um idioma elegante é o seguinte:

 case item when Array #do something when Hash #do something else end 

Note que você não chama o método .class no item .

Se você quiser testar se um object é estritamente ou estende um Hash , use:

 value = {} value.is_a?(Hash) || value.is_a?(Array) #=> true 

Mas, para valorizar a tipificação de pato de Ruby, você poderia fazer algo como:

 value = {} value.respond_to?(:[]) #=> true 

É útil quando você deseja acessar apenas algum valor usando a syntax do value[:key] .

Por favor note que Array.new["key"] irá gerar um TypeError .

 irb(main):005:0> {}.class => Hash irb(main):006:0> [].class => Array