2

次のような通常のクラス メソッドを使用してハッシュにアクセスしようとしています。

aHash.key

しかし、私はこのエラーが発生します:

{:key1="value1", :key2="value2"}:Hash の未定義のメソッド `key1'

ここで提案されているように、ハッシュクラスで「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」を呼び出すと、定義したハッシュが使用されないことは確かです。宝石の 1 つを見ると、次のように表示されます。

"activerecord-postgres-hstore/hash" が必要

このファイルを確認したところ、別のハッシュが実装されていました。そこに「method_missing」を追加する必要があると思いますが、gem を変更せずに実行できますか?

クラスのオーバーロードがルビーでどのように機能するかを理解していないので、答えは別のものかもしれません。

4

1 に答える 1

4

SporkInventor が言ったように、あなたがしていることは非常に危険で悪い習慣です。ハッシュにパッチを当てるべきではありません。代わりに、彼が言ったように、Ruby の標準ライブラリの OpenStruct を使用してください。必要に応じて、ハッシュを返すときにハッシュを OpenStruct にラップするようにコードを変更します。

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

したがって、本当にモンキー パッチを適用する必要がある場合は、ハッシュにパッチを適用する代わりに、ハッシュを返すメソッドにモンキー パッチを適用して、結果を OpenStruct にラップします。または、本当にハッシュにする必要がある場合 (obj.is_a? Hash #=> 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

(構成された)例では、ハッシュを返すメソッド return_hash を持つ Hstore クラスがあります。次に、次のようにパッチします。

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 に答える