web-dev-qa-db-ja.com

hash ['key']をhash.keyにRuby

私はハッシュを持っています

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
45
user94154
>> require 'ostruct'
=> []
>> foo = {'bar'=>'baz'}
=> {"bar"=>"baz"}
>> foo_obj = OpenStruct.new foo
=> #<OpenStruct bar="baz">
>> foo_obj.bar
=> "baz"
>>
81
Hooopo

あなたが探しているものは OpenStruct と呼ばれます。これは標準ライブラリの一部です。

35
Avdi

良い解決策:

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」条件を入れ替えます

22
Gabor Garami

ハッシュからすべてのものをコピーするのではなく、いくつかの動作をハッシュに追加してルックアップを行うことができます。

この定義を追加する場合、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_snに置き換えてください。

6
Dafydd Rees

これにはいくつかの宝石があります。私の最近の宝石 hash_dotdot_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に改善やバグを送信してください。

5
steel