2

我正在尝试使用这样的常规类方法访问哈希:

哈希键

但我得到这个错误:

{:key1=>"value1", :key2=>"value2"}:Hash 的未定义方法 `key1'

我按照这里的建议在 Hash 类中定义了一个“method_missing” :

class Hash
  def method_missing(method, *params)
    method = method.to_sym
    return self[method] if self.keys.collect(&:to_sym).include?(method)
    super
  end
end

我肯定知道,当我调用“aHash.key”时,它不使用我定义的哈希。如果我查看我的宝石上的一个,它会显示:

需要“activerecord-postgres-hstore/hash”

所以我检查了这个文件,确实他们已经实现了另一个哈希。我相信我应该在其中添加“method_missing”,但可以在不修改 gem 的情况下完成吗?

也许我不明白类重载如何与 ruby​​ 一起工作,所以答案可能是别的。

4

1 回答 1

4

就像 SporkInventor 说的那样,你所做的是非常危险和不好的做法,你不应该修补 Hash。相反,就像他说的,使用 Ruby 标准库中的 OpenStruct。如果需要,请更改代码以在返回时将 Hash 包装到 OpenStruct 中。

require 'ostruct'
result = OpenStruct.new({ :a => 1, :b => 2 })
result.a # => 1

因此,如果您真的需要猴子补丁,而不是猴子补丁返回哈希的方法以将结果包装在 OpenStruct 中,而不是修补哈希。或者,如果您需要它真正成为一个哈希(obj.is_a?哈希 #=> true),然后使用您的 method_missing 实现创建哈希的子类,然后对返回哈希的方法进行猴子补丁以返回您的 OpenHash(或您调用的任何内容)它)。

class OpenHash < Hash
  def self.from_hash(hash)
    h = OpenHash.new
    h.merge!(hash)
    h
  end

  def method_missing(method, *params)
    method = method.to_sym
    return self[method] if self.keys.collect(&:to_sym).include?(method)
    super
  end
end

对于(组成)示例,您有一个 Hstore 类,该类具有返回哈希的方法 return_hash。然后像这样修补它:

class Hstore
  def return_hash_with_ostruct
    OpenStruct.new(return_hash_without_ostruct)
  end
  alias_method_chain :return_hash, :ostruct
end
Hstore.new.return_hash.class # => OpenStruct

猴子补丁标准库是非常糟糕的做法!

于 2012-12-04T22:20:24.203 回答