如何将方法添加到gem中的现有类?

时间:2012-12-04 21:55:09

标签: ruby-on-rails

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

  

aHash.key

但是我收到了这个错误:

  

未定义方法`key1'代表{:key1 =>“value1”,:key2 =>“value2”}:哈希

我在Hash类中定义了'method_missing',如建议here

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'时,它不会使用我定义的Hash。如果我看一下我的宝石,就会显示出来:

  

要求“activerecord-postgres-hstore / hash”

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

也许我没有得到类重载如何与ruby一起工作,所以答案可能是别的。

1 个答案:

答案 0 :(得分:4)

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

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

因此,如果你真的需要猴子补丁,而不是猴子补丁返回哈希的方法将结果包装在OpenStruct中,而不是修补哈希。或者如果你需要它真的是一个Hash(obj.is_a?Hash#=> true)然后用你的method_missing实现创建一个hash的子类,然后猴子补丁方法返回哈希以返回你的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

Monkey-patching标准库是非常糟糕的做法!