Reputation: 5682
I have a line like this:
<%= 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'%>
I want to exclude a value from the states.map
collection. I thought that this would work but it doesn't:
<%= 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'%>
I put in unless s.name == "excluded_state
, but, again, it's not working:
What am I doing wrong?
Upvotes: 14
Views: 14225
Reputation: 90
Another alternative to the provided answers is to use each_with_item
in place of map
states.each_with_item([]) { |out, s| out << [s.name, s.id] unless s.name == "excluded_state" }
It's kind of a halfway between each
and reduce
/inject
. It takes an argument in, iterates over your enumerable providing the argument and the element, then returns the argument at the end. You can manipulate the argument in the loop (it wouldn't make much sense not to).
Upvotes: 0
Reputation: 6145
map
doesn't allow to skip values. You have to reject unwanted elements first.
states.reject { |s| s.name == "excluded_state" }.map { |s| [s.name, s.id] }
Another (dirtier) solution is to return nil
for excluded elements and use Array#compact
on the resulting array to remove those nil
elements:
states.map { |s| s.name == "excluded_state" ? nil : [s.name, s.id] }.compact
Upvotes: 31
Reputation: 66263
Eureka's answer is good but here is just a brief explanation to clarify what's going on.
map
returns a new array with the results of running block once for every element in the array. When you write [s.name, s.id] unless s.name == "excluded_state"
this causes the block to return nil
when s.name == "excluded_state"
i.e. the result would be something like
[["NY", 1], nil, ["CA", 2]]
So you could use reject
to remove the unwanted state first, or you could just use compact
1 to remove the nil
entry on the result of your map
as you originally wrote it.
Array#compact
returns a copy of the array with all nil
elements removed.Upvotes: 6