【问题标题】:How to add a method to an existing class in a gem?如何将方法添加到 gem 中的现有类?
【发布时间】:2012-12-04 21:55:09
【问题描述】:

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

aHash.key

但我收到此错误:

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

我按照here 的建议在 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​​ 一起工作,所以答案可能是别的。

【问题讨论】:

  • 你为什么不直接做hash[:key1]
  • 发现了我的问题,我在我的模型上添加了 'require "hash"' 并完成了。
  • 与其对 Hash 类进行猴子修补(危险!),不如考虑使用开放结构。 ruby-doc.org/stdlib-1.9.3/libdoc/ostruct/rdoc/OpenStruct.html
  • @SporkInventor 我知道猴子补丁不是很整洁,但我正在将 HSTORE 用于非 SQL 对象,目前我没有太多选择。我不希望我的程序员一直抱怨非 SQL 哈希“复杂”。如果创建了一个使用 OpenStruct 而不是哈希的 gem,我会加入。

标签: ruby-on-rails


【解决方案1】:

就像 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

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

【讨论】:

  • 谢谢,我要求能够调用像“contact_information.someKey”这样的 hstore 哈希。我发现很多人都在谈论使用 method_missing 来方便地满足需求。我只使用了一段时间的导轨。这些家伙创建了 gem 路径 'Hash' 相当多github.com/softa/activerecord-postgres-hstore
  • 就像我说的,找到返回 Hash 的方法,并将该 Hash 包装到 OpenStruct 中。您可以使用 alias_method_chain 很好地修补该方法。我更新了我的答案,向您展示了如何修补它的示例,您现在只需要找到要修补的类和方法名称。
  • 如果可以的话,我会给你更多的声誉。感谢您的完整简报。我试试看。
  • +1 对于你的帖子@mrbrdo,你在这方面做得很好!
猜你喜欢
  • 2012-07-24
  • 2012-03-21
  • 2023-02-10
  • 1970-01-01
  • 1970-01-01
  • 2018-04-20
  • 1970-01-01
  • 1970-01-01
  • 2015-02-02
相关资源
最近更新 更多