私はハッシュを持っています
foo = {'bar'=>'baz'}
foo.bar #=> 'baz'
に電話をかけたい
私の動機は、アクティブレコードクエリを生のSQLクエリに書き換えることです(Model#find_by_sqlを使用)。これは、SELECT句の値をキーとして持つハッシュを返します。ただし、私の既存のコードは、object.methodドット表記に依存しています。最小限のコード書き換えを行いたいのですが。ありがとう。
編集:Luaにこの機能があるようです:
point = { x = 10, y = 20 } -- Create new table
print(point["x"]) -- Prints 10
print(point.x) -- Has exactly the same meaning as line above
>> require 'ostruct'
=> []
>> foo = {'bar'=>'baz'}
=> {"bar"=>"baz"}
>> foo_obj = OpenStruct.new foo
=> #<OpenStruct bar="baz">
>> foo_obj.bar
=> "baz"
>>
あなたが探しているものは OpenStruct と呼ばれます。これは標準ライブラリの一部です。
良い解決策:
class Hash
def method_missing(method, *opts)
m = method.to_s
if self.has_key?(m)
return self[m]
elsif self.has_key?(m.to_sym)
return self[m.to_sym]
end
super
end
end
注:この実装には既知のバグが1つだけあります。
x = { 'test' => 'aValue', :test => 'bar'}
x.test # => 'aValue'
文字列の検索よりもシンボルの検索を希望する場合は、2つの「if」条件を入れ替えます
ハッシュからすべてのものをコピーするのではなく、いくつかの動作をハッシュに追加してルックアップを行うことができます。
この定義を追加する場合、Hashを拡張して、すべての不明なメソッドをハッシュルックアップとして処理します。
class Hash
def method_missing(n)
self[n.to_s]
end
end
これは、ハッシュに対して間違ったメソッドを呼び出してもエラーが発生しないことを意味します。対応するハッシュルックアップが返すものは何でも取得できます。
メソッドを特定のハッシュにのみ配置する-または必要な数のハッシュによって、これが引き起こす可能性があるデバッグの問題を大幅に減らすことができます。
a={'foo'=>5, 'goo'=>6}
def a.method_missing(n)
self[n.to_s]
end
もう1つの観察は、method_missing
がシステムによって呼び出されると、Symbol
引数を提供することです。私のコードはそれをString
に変換しました。ハッシュキーが文字列でない場合、このコードはこれらの値を返しません。文字列ではなく記号でキーを入力する場合は、上記のn.to_s
をn
に置き換えてください。
これにはいくつかの宝石があります。私の最近の宝石 hash_dot と dot_hash を含む、RubyGemsで私のものをリリースしたときに私が発見した同様の名前のいくつかの宝石があります。
HashDotはドット表記構文を許可しますが、@ avdiによって対処されるNoMethodErrorsに関する懸念に対処します。これは、OpenStructで作成されたオブジェクトよりも速く、トラバース可能です。
require 'hash_dot'
a = {b: {c: {d: 1}}}.to_dot
a.b.c.d => 1
require 'open_struct'
os = OpenStruct.new(a)
os.b => {c: {d: 1}}
os.b.c.d => NoMethodError
また、非メソッドが呼び出されたときに予期される動作を維持します。
a.non_method => NoMethodError
HashDotに改善やバグを送信してください。