2012-09-13 68 views
8

我有這樣一行:從Ruby on Rails中的collection.map排除選項?

<%= f.input :state_id, :input_html => {:value => (policy_address.state.name rescue nil)}, :required => true, :collection => states.map {|s| [ s.name, s.id] }, :include_blank => 'Please select'%> 

我想排除從states.map收藏價值。我認爲這會工作,但它並不:

<%= f.input :state_id, :input_html => {:value => (policy_address.state.name rescue nil)}, :required => true, :collection => states.map {|s| [ s.name, s.id] unless s.name == "excluded_state" }, :include_blank => 'Please select'%> 

我把unless s.name == "excluded_state,但同樣,它不工作:

我在做什麼錯?

回答

20

map不允許跳過值。你必須首先拒絕不需要的元素。

states.reject { |s| s.name == "excluded_state" }.map { |s| [s.name, s.id] } 

另一個(髒)解決方案是返回nil排除的元素,並且使用Array#compact所產生的陣列上,以消除那些nil元素:

states.map { |s| s.name == "excluded_state" ? nil : [s.name, s.id] }.compact 
+1

謝謝!完美工作 – Ryan

+0

這正是我需要的。謝謝 –

+4

'states.map {| s | [s.name,s.id] if s.name ==「excluded_state」} .compact' –

6

Eureka's答案是好的,但這裏只是一個簡要的解釋澄清發生了什麼事。

map返回一個新的數組,其結果爲運行一次塊,每元素在數組中。當你寫[s.name, s.id] unless s.name == "excluded_state"這將導致該塊返回nils.name == "excluded_state"即結果會是這樣的

[["NY", 1], nil, ["CA", 2]] 

所以,你可以使用reject先刪除不需要的狀態,或者你可以只使用compact 刪除您最初編寫的map的結果中的nil條目。


  1. Array#compact返回該數組的其中移除所有nil元素的副本。
+0

感謝您的解釋,現在讓我更加明白爲什麼當我嘗試我所做的事情時,我得到了錯誤。 – Ryan

+1

謝謝:條件順序固定,我的心理分析器在這一個上跑得太快;) – Eureka