2009-05-27 19 views
0

コレクションが文字列のインデックス付けをサポートしているかどうかをテストする効率的なRubyqueの方法はありますか?コレクションのインデックス型(つまり、[]メソッドの引数)のテスト

ロングバージョン: 特定の値を正規化するクラスがあります。これを実現するために、インスタンスは 'values'属性として値のコレクションを取ります。 values=は、リスト(組み込み配列を含む整数インデックス付きコレクション)と結合配列(Hashなどのオブジェクトインデックス付きコレクション)の両方を受け入れるようにしたいと思います。リストを渡すと、キー&の値を反転することによってリストを連想配列に変換します。これは、メソッドが連想配列からリストを区別する必要があることを意味します。 ArrayやHashの子孫だけではなく、インデックスされたコレクションでも動作するはずです。コレクションタイプを盗聴するような種類のものは、醜いものと誤ったものとみなされます。しかし、インデックスタイプを盗聴するタイプ...

現在、私は違いを伝えるために例外を使用していますが、一般的な制御構造ではなく、例外的な状況に対して例外を使用することを好みます。それは単なる個人的な好みです、私はあまりにも付いていないです。この問題を解決するために例外がルビーの方法である場合は、教えてください。

def values=(values) 
    begin 
     values[''] 
     @values = values.dup 
    rescue TypeError 
     @values = Hash[ values.zip((0..values.length-1).to_a) ] 
    end 
    @values.each_value { |v| @values[v] = v} 
end 

注:完全なソリューションをvaluesの推移閉包を取るだろうが、今の私はvaluesの&値が異なるドメインからある鍵をとることができます。

toggle.values = [:off, :on] 
toggle.normalise(:off) == 0 
toggle.normalise(1) == 1 

bool.values = {:off => 0, :false => 0, :no => 0, 
       :on => 1, :true => 1, :yes => 1} 
bool.normalise(:yes) == 1 
bool.normalise(0) == 0 

PS:

このすべての点のようなコードを可能にすることです。これは個人的なプロジェクトのため、優雅さとRubyのやり方が最優先です。私は面白いアプローチを探しています。特に、興味深い概念を説明する場合(「例外は行動テストとして使用できます」など)

答えて

2

レスキューにダックタイピング!

hash = if collection.respond_to? :to_hash 
      collection.to_hash 
     elsif collection.respond_to? :to_ary 
      collection.to_ary.inject({}) { |_hash,(key,value)| _hash.merge!(key => value) } 
     else if collection.respond_to? :inject 
      collection.inject({}) { |_hash,(key,value)| _hash.merge!(key => value) } 
     else 
      raise ArgumentError, "not a collection type I understand" 
     end 
if want_dupe and collection.object_id == hash.object_id 
    hash = hash.dup 
end 
+0

ヤイダックタイピング! collection.to_hashが中間で一時的な複製を作成せずに(collection.to_hash.dupが行うかもしれないように)、collection.to_hashが複製であることを保証するきれいな方法はありますか? – outis

+0

"空を見上げてください、それは鳥です。それは飛行機です。いいえ、初めてでした、それは鳥です。" – outis

+0

object_idsを比較できます。それは魔法のように清潔ではありませんが、それは動作します。 – rampion

関連する問題