【问题标题】:Why is_a? returns false for Hash class?为什么是_a? Hash 类返回 false?
【发布时间】:2011-12-21 13:04:58
【问题描述】:

为什么is_a?Hash 类返回false

例子:

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

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

输出:

Hash
false

我使用的是 Ruby 1.9.2

已更新:我的课程的完整来源:

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

【问题讨论】:

  • 在 ruby​​ 1.9.2p290 (2011-07-09) 上一切正常(我得到了真正的价值)
  • 也适用于此。你能检查Hash.new.is_a?(Hash) 是否也返回假吗?那会很奇怪。
  • 可能是某些 gem 覆盖了 Hash
  • 它适用于 irb,但不适用于我的示例。我列出了整个班级的来源

标签: ruby database mongoid


【解决方案1】:
#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

尝试禁用您已加载的任何 gem/扩展,并尝试使用 clean ruby​​

更新:

试试value.is_a?(::Hash)

PS:尝试阅读 Ruby 中的 Duck Typing。也许你应该打电话给value.respond_to?(:key) 而不是value.is_a?(Hash)

【讨论】:

  • 它适用于 irb,但不适用于我的示例。我列出了整个班级的来源
  • 只是出于好奇,为什么会这样? (::Hash)。阅读有关 Ruby 中双冒号的帖子,但我不明白为什么它适用于这种情况。
  • Zed,谢谢。 =) 找到了相同的解决方案。
  • 通过包含模块 Mongoid::Fields::Serializable 意味着 Ruby 将首先在 Mongoid::Fields::Serializable 中查找任何名为 Hash 的内容,然后在 Mongoid::Fields 中查找 Hash,直到它找到哈希。 ::Hash 表示在全局命名空间中查找 Hash。另请参阅this SO question
  • 刚刚使用 Resque Status 插件在 Resque Job 类中遇到了同样的问题。原来插件添加了Resque::Plugins::Status::Hash
【解决方案2】:

当我在 Hash 类之前添加“::”时,它开始工作。

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

输出:

Hash
true

【讨论】:

  • 与其回答您自己的问题,为什么不接受来自 zed_oxff 的更新答案?
  • Zed,我接受了你的回答。事实是,我同时找到了答案。 =) 谢谢
【解决方案3】:

没有。

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

Mongoid Hash 不是纯 Ruby Hash,也没有扩展它。您应该检查实际类型,可能使用type

仅仅因为打印出Hash 并不意味着(a)它是您认为它是继承链的一部分,并且(b)它是Hash(见证ActiveRecord Array,这是谎言,一定程度上)。

【讨论】:

  • 它适用于 irb,但不适用于我的示例。我列出了整个班级的来源
  • @AlexeyZakharov 如果它是 Mongoid 散列,您可能应该明确检查完整的类—— Mongoid 散列不是 Ruby 散列,也没有扩展它。 docs
猜你喜欢
  • 2019-08-15
  • 2014-02-25
  • 1970-01-01
  • 1970-01-01
  • 2017-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多