DEV Community

Drew Bragg
Drew Bragg

Posted on

Using the new `weekday_select` in Rails 7

In most of the Rails apps I've built over the years I've had to add my own helpers for a weekday select. Normally Rails is great at providing most of the helpers you could ever want, so this omission has always been a little surprising to me. At Within3 I recently had to work on this again, and another engineer on my team shared my surprise at the omission. So I thought it was time for a Rails PR.

The bulk of this PR adds the weekday_options_for_select method but you'll still need to wrap that in a select tag so I also added a weekday_select tag to the form builder. Now there are a few ways to build your weekday select so let start with an overview of the weekday_options_for_select method.

weekday_options_for_select accepts a few arguments, all of which have a default, for you to customize your options:

  • selected (defaults to nil) if you provide this argument the value passed will be used to mark that option as selected:
weekday_options_for_select("Friday")
# => "<option value=\"Sunday\">Sunday</option>\n
# <option value=\"Monday\">Monday</option>\n
# <option value=\"Tuesday\">Tuesday</option>\n
# <option value=\"Wednesday\">Wednesday</option>\n
# <option value=\"Thursday\">Thursday</option>\n
# <option selected=\"selected\" value=\"Friday\">Friday</option>\n
# <option value=\"Saturday\">Saturday</option>"
Enter fullscreen mode Exit fullscreen mode
  • index_as_value (defaults to false) if true will set the value of each option to the index of that day
weekday_options_for_select(index_as_value: true)
# => "<option value=\"0\">Sunday</option>\n
# <option value=\"1\">Monday</option>\n
# <option value=\"2\">Tuesday</option>\n
# <option value=\"3\">Wednesday</option>\n
# <option value=\"4\">Thursday</option>\n
# <option value=\"5\">Friday</option>\n
# <option value=\"6\">Saturday</option>"
Enter fullscreen mode Exit fullscreen mode

NOTE: "Sunday" will always be 0 even if you start on a different day (more on that in a minute) to stay consistent. In Ruby, if you call wday on a Date "Sunday" will always return 0 and I18n.translate("date.day_names") will return an array where "Sunday" is the first item. So we keep the value of "Sunday" 0 regardless of where it falls in the array.

  • day_format (defaults to :day_names) passing this a different I18n key will use different formats for the option display names and values.
weekday_options_for_select(day_format: :abbr_day_names)
# => "<option value=\"Sun\">Sun</option>\n
# <option value=\"Mon\">Mon</option>\n
# <option value=\"Tue\">Tue</option>\n
# <option value=\"We\">Wedn</option>\n
# <option value=\"Thu\">Thu</option>\n
# <option value=\"Fri\">Fri</option>\n
# <option value=\"Sat\">Sat</option>"
Enter fullscreen mode Exit fullscreen mode

NOTE: :abbr_day_names is built into Rails but you could define your own Array and use that key if desired. Example:

en:
  date:
    alt_day_names: [Sun, Mon, Tues, Weds, Thurs, Fri, Sat]
Enter fullscreen mode Exit fullscreen mode
weekday_options_for_select(day_format: :alt_day_names)
# => "<option value=\"Sun\">Sun</option>\n
# <option value=\"Mon\">Mon</option>\n
# <option value=\"Tues\">Tues</option>\n
# <option value=\"Weds\">Weds</option>\n
# <option value=\"Thurs\">Thurs</option>\n
# <option value=\"Fri\">Fri</option>\n
# <option value=\"Sat\">Sat</option>"
Enter fullscreen mode Exit fullscreen mode
  • Bonus Option I recently made another PR that adds a beginning_of_week option so you can specify which day the select starts on. This defaults to Date.beginning_of_week so as long as you have that set you're good to go, if you don't or you want to override it, here's how:
Date.beginning_of_week
# => :sunday
weekday_options_for_select(beginning_of_week: :monday)
# => "<option value=\"Monday\">Monday</option>\n
# <option value=\"Tuesday\">Tuesday</option>\n
# <option value=\"Wednesday\">Wednesday</option>\n
# <option value=\"Thursday\">Thursday</option>\n
# <option value=\"Friday\">Friday</option>\n
# <option value=\"Saturday\">Saturday</option>\n
# <option value=\"Sunday\">Sunday</option>"
Enter fullscreen mode Exit fullscreen mode

Like I said you'll still need to wrap weekday_options_for_select in a select tag so I also added a weekday_select tag to the form builder. Lets take a look at how to use that.

Lets say we have a newsletter that we send our to our users and we want our users to be able to set what day they receive that newsletter. We can add a newsletter_send_day column to our User and then update the form to look a little something like this:

<%= form_with model: @user do |form| %>
  <%= form.label :newsletter_send_day %>
  <%= form.weekday_select :newsletter_send_day %>
<% end %>
Enter fullscreen mode