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 Exit fullscreen mode

And that's it!

You'll get something that looks like this in your form:

<select name="user[newsletter_send_day]" id="user_newsletter_send_day">
  <option value="Sunday">Sunday</option>
  <option value="Monday">Monday</option>
  <option value="Tuesday">Tuesday</option>
  <option value="Wednesday">Wednesday</option>
  <option value="Thursday">Thursday</option>
  <option value="Friday">Friday</option>
  <option value="Saturday">Saturday</option>
</select>
Enter fullscreen mode Exit fullscreen mode

You can use any combination of the weekday_options_for_select arguments to modify your selects options.

You can try weekday_select and weekday_options_for_select for yourself in Rails 7, which at the time of this writing is in an alpha prerelease. Let me know what you think about these new form options and if you get a chance to use them in any of your projects!

Discussion (1)

Collapse
pandademic profile image
Pandademic • Edited

Great Job!