Skip to content

Commit 394dbac

Browse files
authored
Merge pull request rails#43567 from shunichi/date-select-day-format
Add :day_format option to date_select
2 parents 7bf2075 + e9fa24f commit 394dbac

File tree

3 files changed

+72
-1
lines changed

3 files changed

+72
-1
lines changed

actionview/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
* Add `:day_format` option to `date_select`
2+
3+
date_select("article", "written_on", day_format: ->(day) { day.ordinalize })
4+
# generates day options like <option value="1">1st</option>\n<option value="2">2nd</option>...
5+
6+
*Shunichi Ikegami*
7+
18
* Allow `link_to` helper to infer link name from `Model#to_s` when it
29
is used with a single argument:
310

actionview/lib/action_view/helpers/date_helper.rb

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ def time_ago_in_words(from_time, options = {})
206206
# you are creating new record. While editing existing record, <tt>:end_year</tt> defaults to
207207
# the current selected year plus 5.
208208
# * <tt>:year_format</tt> - Set format of years for year select. Lambda should be passed.
209+
# * <tt>:day_format</tt> - Set format of days for day select. Lambda should be passed.
209210
# * <tt>:discard_day</tt> - Set to true if you don't want to show a day select. This includes the day
210211
# as a hidden field instead of showing a select field. Also note that this implicitly sets the day to be the
211212
# first of the given month in order to not create invalid dates like 31 February.
@@ -279,6 +280,9 @@ def time_ago_in_words(from_time, options = {})
279280
# # Generates a date select with custom year format.
280281
# date_select("article", "written_on", year_format: ->(year) { "Heisei #{year - 1988}" })
281282
#
283+
# # Generates a date select with custom day format.
284+
# date_select("article", "written_on", day_format: ->(day) { day.ordinalize })
285+
#
282286
# The selects are prepared for multi-parameter assignment to an Active Record object.
283287
#
284288
# Note: If the day is not included as an option but the month is, the day will be set to the 1st to ensure that
@@ -811,7 +815,7 @@ def select_day
811815
if @options[:use_hidden] || @options[:discard_day]
812816
build_hidden(:day, day || 1)
813817
else
814-
build_options_and_select(:day, day, start: 1, end: 31, leading_zeros: false, use_two_digit_numbers: @options[:use_two_digit_numbers])
818+
build_select(:day, build_day_options(day))
815819
end
816820
end
817821

@@ -899,6 +903,27 @@ def translated_month_names
899903
I18n.translate(key, locale: @options[:locale])
900904
end
901905

906+
# Looks up day names by number.
907+
#
908+
# day_name(1) # => 1
909+
#
910+
# If the <tt>use_two_digit_numbers: true</tt> option is passed to DateTimeSelector:
911+
#
912+
# day_name(1) # => "01"
913+
#
914+
# If the <tt>day_format: ->(day) { day.ordinalize }</tt> option is passed to DateTimeSelector:
915+
#
916+
# day_name(1) # => "1st"
917+
def day_name(number)
918+
if day_format_lambda = @options[:day_format]
919+
day_format_lambda.call(number)
920+
elsif @options[:use_two_digit_numbers]
921+
"%02d" % number
922+
else
923+
number
924+
end
925+
end
926+
902927
# Looks up month names by number (1-based):
903928
#
904929
# month_name(1) # => "January"
@@ -1011,6 +1036,35 @@ def build_options(selected, options = {})
10111036
(select_options.join("\n") + "\n").html_safe
10121037
end
10131038

1039+
# Build select option HTML for day.
1040+
# build_day_options(2)
1041+
# => "<option value="1">1</option>
1042+
# <option value="2" selected="selected">2</option>
1043+
# <option value="3">3</option>..."
1044+
#
1045+
# If <tt>day_format: ->(day) { day.ordinalize }</tt> option is passed to DateTimeSelector
1046+
# build_day_options(2)
1047+
# => "<option value="1">1st</option>
1048+
# <option value="2" selected="selected">2nd</option>
1049+
# <option value="3">3rd</option>..."
1050+
#
1051+
# If <tt>use_two_digit_numbers: true</tt> option is passed to DateTimeSelector
1052+
# build_day_options(2)
1053+
# => "<option value="1">01</option>
1054+
# <option value="2" selected="selected">02</option>
1055+
# <option value="3">03</option>..."
1056+
def build_day_options(selected)
1057+
select_options = []
1058+
(1..31).each do |value|
1059+
tag_options = { value: value }
1060+
tag_options[:selected] = "selected" if selected == value
1061+
text = day_name(value)
1062+
select_options << content_tag("option", text, tag_options)
1063+
end
1064+
1065+
(select_options.join("\n") + "\n").html_safe
1066+
end
1067+
10141068
# Build select option HTML for year.
10151069
# If <tt>year_format</tt> option is not passed
10161070
# build_year_options(1998, start: 1998, end: 2000)

actionview/test/template/date_helper_test.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,16 @@ def test_select_day_with_two_digit_numbers
251251
assert_dom_equal expected, select_day(2, use_two_digit_numbers: true)
252252
end
253253

254+
def test_select_day_with_day_fomat
255+
expected = +%(<select id="date_day" name="date[day]">\n)
256+
expected << %(<option value="1">1st</option>\n<option selected="selected" value="2">2nd</option>\n<option value="3">3rd</option>\n<option value="4">4th</option>\n<option value="5">5th</option>\n<option value="6">6th</option>\n<option value="7">7th</option>\n<option value="8">8th</option>\n<option value="9">9th</option>\n<option value="10">10th</option>\n<option value="11">11th</option>\n<option value="12">12th</option>\n<option value="13">13th</option>\n<option value="14">14th</option>\n<option value="15">15th</option>\n<option value="16">16th</option>\n<option value="17">17th</option>\n<option value="18">18th</option>\n<option value="19">19th</option>\n<option value="20">20th</option>\n<option value="21">21st</option>\n<option value="22">22nd</option>\n<option value="23">23rd</option>\n<option value="24">24th</option>\n<option value="25">25th</option>\n<option value="26">26th</option>\n<option value="27">27th</option>\n<option value="28">28th</option>\n<option value="29">29th</option>\n<option value="30">30th</option>\n<option value="31">31st</option>\n)
257+
expected << "</select>\n"
258+
259+
day_format = ->(day) { ActiveSupport::Inflector.ordinalize(day) }
260+
assert_dom_equal expected, select_day(Time.mktime(2011, 8, 2), day_format: day_format)
261+
assert_dom_equal expected, select_day(2, day_format: day_format)
262+
end
263+
254264
def test_select_day_with_html_options
255265
expected = +%(<select id="date_day" name="date[day]" class="selector">\n)
256266
expected << %(<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="4">4</option>\n<option value="5">5</option>\n<option value="6">6</option>\n<option value="7">7</option>\n<option value="8">8</option>\n<option value="9">9</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16" selected="selected">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n)

0 commit comments

Comments
 (0)