2011-07-20 58 views
2

我有一個接受參數的方法,該參數可以是數組/類似對象或哈希。該方法的要點是一樣的東西:如何檢測類似數組或類似的值,同時避免類型檢查

def find(query = {}) 
    if Array === query or Set === query 
    query = {:_id => {'$in' => query.to_a}} 
    end 
    mongo_collection.find(query) 
end 

的方法將接受一組ID的對象,並把它變成了MongoDB的哈希條件。

兩個問題上面的代碼:

  1. 如果「設置」未從標準庫需要它將會失敗。我不想僅僅依靠執行檢查。
  2. 我不想做嚴格的類型比較。我想接受任何數組或類似值,並將其轉換爲to_a的值數組。

您將如何執行此檢查?一些注意事項有記:

  1. 我可以檢查to_ary方法,但設置並不to_ary迴應。實現這個方法的對象應該基本上是數組,我同意Set不是一個基本的數組。見Consequences of implementing to_int and to_str in Ruby
  2. 我無法檢查to_a因爲哈希響應它
  3. 的方法是共同的陣列和設置,而不是哈希是:

    [:&, :+, :-, :<<, :collect!, :flatten!, :map!, :|] 
    

我決定去像這樣:

query = {:_id => {'$in' => query.to_a}} if query.respond_to? :& 

因爲相交可能是一個集合類對象將具有的運算符。但我不確定這一點。

+0

基本上你說的是鴨子打字。如果它可以像數組一樣操作,則不關心對象是什麼。因此,將'.to_a'添加到對象並查看它是否可以轉換爲數組。如果你想要一個散列,你可能想轉換爲一個數組,然後構造一個散列:'Hash [* array.to_a.flatten]'。那時,呼叫者的工作就是要求適當的班級,而不是你。 –

回答

1

如何試圖找出查詢是否哈希什麼樣的?

def find(query = {}) 
    query = {:_id => {'$in' => query.to_a}} unless query.respond_to?(:has_key?) 
    mongo_collection.find(query) 
end 

如果對象響應has_key,那麼期望該對象是散列或哈希是合理的。

+1

這似乎是這個具體問題最優雅的解決方案,但並沒有回答原始的一般問題:「如何檢測數組或類似值」。好吧 – mislav

0

檢查以查看Set是否定義將解決您的第一個問題。對於第二種情況,您可能會檢查查詢類的祖先以查看數組是否在其中,但這可能不會捕獲所有「類似數組」的對象。我可能不會檢查是否存在用於測試數組的方法,因爲您正在測試名稱而不是行爲。 Arel特別響應(或者在它被棄用之前)&,但是這種類型的對象不會像你想要的那樣工作。

4

這是我的看法:

if not Hash === query and query.respond_to? :to_a 

我只是檢查to_a,這是我感興趣的,而且確保它不是一個Hash對象的唯一方法。我使用嚴格的哈希類型檢查,但只是因爲這是最不可能的對象被傳遞爲一個完全獨立的類,它基本上是一個哈希。

0

個人而言,我在想......

def find(query = {})  
    mongo_collection.find(query_formatter(query)) 
end 

def query_formatter(query) 
    if query.respond_to?(:to_a) && !query.kind_of?(Hash) 
    {:_id => {'$in' => query.to_a}} 
    else 
    query 
    end 
end