Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is_a? returns false for Hash class?

Why is_a? returns false for a Hash class?

Example:

value = {"x" => 3, "y" => 2}

puts value.class
puts value.is_a?(Hash)

Output:

Hash
false

Im using Ruby 1.9.2

UPDATED: full source of my class:

class LatLng
  include Mongoid::Fields::Serializable

  attr_reader :lat, :lng

  def serialize(value)
    return if value.nil?

    puts value.class
    puts value.is_a?(Hash)

    if value.is_a?(self.class)
      puts "is geopoint" + value.to_json
      {'lng' => value.lng.to_f, 'lat' => value.lat.to_f}
    elsif value.is_a?(Hash)
      hash = value.with_indifferent_access
      puts "is hash" + value.to_json
      {'lng' => hash['lng'].to_f, 'lat' => hash['lat'].to_f}
    end
  end

  def deserialize(value)
    return if value.nil?

    value.is_a?(self.class) ? value : LatLng.new(value['lat'], value['lng'])
  end

  def initialize(lat, lng)
    @lat, @lng = lat.to_f, lng.to_f
  end

  def [](arg)
    case arg
      when "lat"
        @lat
      when "lng"
        @lng
    end
  end

  def to_a
    [lng, lat]
  end

  def ==(other)
    other.is_a?(self.class) && other.lat == lat && other.lng == lng
  end
end
like image 769
Alexey Zakharov Avatar asked Dec 21 '11 13:12

Alexey Zakharov


3 Answers

#irb
ruby-1.9.3-p0 :001 > value = {"x" => 3, "y" => 2}
 => {"x"=>3, "y"=>2} 
ruby-1.9.3-p0 :002 > value.is_a?(Hash)
 => true

try to disable any gems/extensions you have loaded, and try with clean ruby

UPDATE:

try value.is_a?(::Hash)

PS: try to read about Duck Typing in Ruby. Maybe you should call value.respond_to?(:key) instead of value.is_a?(Hash)

like image 71
zed_0xff Avatar answered Oct 31 '22 18:10

zed_0xff


When I added "::" before Hash class it starts working.

puts value.class
puts value.is_a?(::Hash)

Output:

Hash
true
like image 41
Alexey Zakharov Avatar answered Oct 31 '22 19:10

Alexey Zakharov


It doesn't.

dave@hpubuntu1:~ $ rvm list

rvm rubies

   ruby-1.8.7-p334 [ i386 ]
   jruby-1.6.2 [ linux-i386-java ]
   ruby-1.9.2-p0 [ i386 ]
   ruby-1.9.2-p290 [ i386 ]
   ruby-1.9.3-p0 [ i386 ]
=> ruby-1.9.2-p180 [ i386 ]

dave@hpubuntu1:~ $ pry
pry(main)> value = {"x" => 3, "y" => 2}
=> {"x"=>3, "y"=>2}
pry(main)> value.is_a? Hash
=> true

A Mongoid Hash isn't a pure-Ruby Hash, nor does it extend it. You should check the actual type, probably by using type.

Just because something prints out Hash doesn't mean (a) that it's part of the inheritance chain you think it is, and (b) that it's a Hash (witness ActiveRecord Array, which lies, to a degree).

like image 2
Dave Newton Avatar answered Oct 31 '22 19:10

Dave Newton