Customizing the items from a select field using Set operators

I had to customize the items of a select input field for timezones in a form. I needed to show some preferred US timezones first and then list the remaining below them. My mentor sent me this link to help me and I want to share it with you.

It turns out, this is something that you probably saw in a Math class: Set theory. What we need here is what we call Union:

A union is essentially used to combine the unique values of two sets, or in this case, arrays. To perform a union on two arrays you use the pipe as an operator. For example:

[1, 2, 1, 2, 3] | [1, 2, 3, 4] #=> [1, 2, 3, 4]

Mike Farmer

Or visually:

image from mathscrunch

Now that we are a little more familiar with set operators, let’s move to our problem. To keep our code organized, let’s move our code to a helper:

 # we use helpers to extract logic from our views
  
def timezones
  priorities =
    [ ActiveSupport::TimeZone['Eastern Time (US & Canada)'],
     ActiveSupport::TimeZone['Central Time (US & Canada)'],
     ActiveSupport::TimeZone['Mountain Time (US & Canada)'],
     ActiveSupport::TimeZone['Pacific Time (US & Canada)'] ]
    
  priorities | ActiveSupport::TimeZone.us_zones
end

So first we have a list of the preferred timezones, then we use the | operator to show those first and after that, show all the US time zones that aren’t included on the priorities list.

Now we just need to call our helper method on our form:

# html.slim

= f.collection_select :time_zone, timezones, :name, :to_s, {}, { class: "form-control" }

And voilà, that’s the result:

ta-da!

Whenever you have a similar problem, you can follow this approach. Hope you liked it!