2016-01-22 37 views
0

我有一個散列數組。這裏是典型值的小樣本:供應紅寶石陣列選擇一個動態塊

[{"id"=>1, 
    "context"=>"r178", 
    "asset"=>"Art Schools Hub", 
    "campaign"=>"Fashion Careers", 
    "contact_email"=>"[email protected]", 
    "notes"=>"", 
    "user_first_name"=>"Agustin", 
    "user_last_name"=>"Welch", 
    "status"=>"Completed", 
    "date_collected"=>"01/22/16"}, 
{"id"=>4, 
    "context"=>"r178", 
    "asset"=>"Art Schools Hub", 
    "campaign"=>"Graphic Design Careers", 
    "contact_email"=>"[email protected]", 
    "notes"=>"", 
    "user_first_name"=>"Agustin", 
    "user_last_name"=>"Welch", 
    "status"=>"In Progress", 
    "date_collected"=>"01/22/16"}, 
{"id"=>15, 
    "context"=>"r178", 
    "asset"=>"Art Schools Hub", 
    "campaign"=>"Art Education", 
    "contact_email"=>"[email protected]", 
    "notes"=>"", 
    "user_first_name"=>"Jermaine", 
    "user_last_name"=>"Wilkinson", 
    "status"=>"Open", 
    "date_collected"=>"01/22/16"}] 

我知道做一個選擇是這樣的:

results = @network.select { |x| x["campaign"] == "Art Education" && x["status"] == "Open" } 

濾光器陣列返回哈希數組,其中所選擇的按鍵具有搜索到的值。

但是,用戶必須能夠基於任何或所有具有用戶提交的值的鍵過濾此數組。

雖然我可以替代從表單的PARAMS的值代入這樣的塊:

results = @network.select { |x| x[params[1]["column"]] == params[1]["search"] && x[params[2]["column"]] == params[2]["search"] } 

每一選擇的邏輯可以不同。可以有多達10個不同的條件,列值和搜索值的形式爲params。

我需要一種方法來根據用戶提交的條件動態地在選擇的塊部分中創建表達式。

不幸的是,我試圖爲塊構造表達式的每種方式都會導致無法通過select進行評估的字符串值。

我已經爲此工作了好幾天了,所以如果有人能給我一個解決方案,我將非常感激。

編輯: 由於魔杖製作的優雅的解決方案,我做了如下修改,根據他的代碼,允許用戶散列的基於鍵,其搜索值與用戶提交的值開始濾鏡陣列,而不是等於該值:

pm = params.map { |h| {h["column"] => h["search"].downcase} }.reduce(&:merge) 

result = @network.select do |h| 
    temp = h.slice(*pm.keys) 
    new_temp = Hash.new 
    temp.each do |k,v| 
      new_temp[k]=v.downcase.slice(0..pm[k].length - 1) 
    end 
    new_temp == pm 
end 

這現在工作的很好。

+1

我認爲你會更好在數據庫級別過濾。這就是它的目的。 – seph

+0

用戶可以提交什麼樣的東西? –

+0

您能否詳細說明每個選擇的邏輯可能不同。可能有多達10種不同的條件 - 在你的示例代碼中,你使用'&&'運算符來表示條件,你是否暗示可以有'||'和這些條件的混合? –

回答

1

以下是一種可能的方法。

讓我們來定義params是:

params = [{"column" => "context", "search" => "r178"}, 
      {"column" => "campaign", "search" => "Art Education"}] 

我們將它處理到@network結構上類似的元素。

pm = params.map { |h| {h["column"] => h["search"]} }.reduce(&:merge) 
#=> {"context"=>"r178", "campaign"=>"Art Education"} 

現在,我們將選擇處理PARAMS散列pm存在於該鑰匙,並用它來從@network陣列獲得的各元素的切片,並且如果處理PARAMS散列和切片散列都相等,那麼,我們有一場比賽,我們可以選擇該項目。

result = @network.select {|h| h.slice(*pm.keys) == pm} 

完整代碼示例中,我添加require "active_support/core_ext/hash"使得下面的程序可以運行作爲用於說明的目的獨立紅寶石程序。在Rails代碼中不需要它。

require "pp" 
require "active_support/core_ext/hash" 

@network = [{"id"=>1, "context"=>"r178", "asset"=>"Art Schools Hub", "campaign"=>"Fashion Careers", "contact_email"=>"[email protected]", "notes"=>"", "user_first_name"=>"Agustin", "user_last_name"=>"Welch", "status"=>"Completed", "date_collected"=>"01/22/16"}, 
{"id"=>4, "context"=>"r178", "asset"=>"Art Schools Hub", "campaign"=>"Graphic Design Careers", "contact_email"=>"[email protected]", "notes"=>"", "user_first_name"=>"Agustin", "user_last_name"=>"Welch", "status"=>"In Progress", "date_collected"=>"01/22/16"}, 
{"id"=>15, "context"=>"r178", "asset"=>"Art Schools Hub", "campaign"=>"Art Education", "contact_email"=>"[email protected]", "notes"=>"", "user_first_name"=>"Jermaine", "user_last_name"=>"Wilkinson", "status"=>"Open", "date_collected"=>"01/22/16"}] 

params = [{"column" => "context", "search" => "r178"}, 
      {"column" => "campaign", "search" => "Art Education"}] 

pm = params.map { |h| {h["column"] => h["search"]} }.reduce(&:merge) 
pp result = @network.select {|h| h.slice(*pm.keys) == pm} 

#=> [{"id"=>15, 
#  "context"=>"r178", 
#  "asset"=>"Art Schools Hub", 
#  ... 
#  "status"=>"Open", 
#  "date_collected"=>"01/22/16"}] 

對於澄清評價尋求,溶液可適於以及用於starts_with類型的條件。一個可以使用:

pp result = @network.select {|h| pm.keys.all?{|k| h[k].starts_with? pm[k]}} 
+0

這對於篩選等於用戶提交的搜索值的值時效果很好(儘管在Rails中我似乎不需要'pp')。但是,這是另一個皺紋。他們希望價值從用戶提交的角色開始,而不是平等。這可以修改以處理這個問題嗎? – Doug366

+0

@ Doug366我已經更新了答案,希望它能滿足您的需求。 –