Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exclude option from collection.map in Ruby on Rails?

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?

like image 514
Ryan Avatar asked Sep 13 '12 14:09

Ryan


2 Answers

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
like image 153
Eureka Avatar answered Nov 05 '22 05:11

Eureka


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 compact1 to remove the nil entry on the result of your map as you originally wrote it.


  1. Array#compact returns a copy of the array with all nil elements removed.
like image 38
mikej Avatar answered Nov 05 '22 04:11

mikej