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 tonil
) 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>"
-
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>"
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>"
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]
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>"
-
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 toDate.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>"
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 %>
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>
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!
Top comments (1)
Great Job!