diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md index 5386f506dc..21af906bcc 100644 --- a/actionview/CHANGELOG.md +++ b/actionview/CHANGELOG.md @@ -1,3 +1,10 @@ +* Add `:day_format` option to `date_select` + + date_select("article", "written_on", day_format: ->(day) { day.ordinalize }) + # generates day options like \n... + + *Shunichi Ikegami* + * Allow `link_to` helper to infer link name from `Model#to_s` when it is used with a single argument: diff --git a/actionview/lib/action_view/helpers/date_helper.rb b/actionview/lib/action_view/helpers/date_helper.rb index 24a0784353..1a416c109d 100644 --- a/actionview/lib/action_view/helpers/date_helper.rb +++ b/actionview/lib/action_view/helpers/date_helper.rb @@ -206,6 +206,7 @@ module ActionView # you are creating new record. While editing existing record, :end_year defaults to # the current selected year plus 5. # * :year_format - Set format of years for year select. Lambda should be passed. + # * :day_format - Set format of days for day select. Lambda should be passed. # * :discard_day - Set to true if you don't want to show a day select. This includes the day # as a hidden field instead of showing a select field. Also note that this implicitly sets the day to be the # first of the given month in order to not create invalid dates like 31 February. @@ -279,6 +280,9 @@ module ActionView # # Generates a date select with custom year format. # date_select("article", "written_on", year_format: ->(year) { "Heisei #{year - 1988}" }) # + # # Generates a date select with custom day format. + # date_select("article", "written_on", day_format: ->(day) { day.ordinalize }) + # # The selects are prepared for multi-parameter assignment to an Active Record object. # # 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 @@ module ActionView if @options[:use_hidden] || @options[:discard_day] build_hidden(:day, day || 1) else - build_options_and_select(:day, day, start: 1, end: 31, leading_zeros: false, use_two_digit_numbers: @options[:use_two_digit_numbers]) + build_select(:day, build_day_options(day)) end end @@ -899,6 +903,27 @@ module ActionView I18n.translate(key, locale: @options[:locale]) end + # Looks up day names by number. + # + # day_name(1) # => 1 + # + # If the use_two_digit_numbers: true option is passed to DateTimeSelector: + # + # day_name(1) # => "01" + # + # If the day_format: ->(day) { day.ordinalize } option is passed to DateTimeSelector: + # + # day_name(1) # => "1st" + def day_name(number) + if day_format_lambda = @options[:day_format] + day_format_lambda.call(number) + elsif @options[:use_two_digit_numbers] + "%02d" % number + else + number + end + end + # Looks up month names by number (1-based): # # month_name(1) # => "January" @@ -1011,6 +1036,35 @@ module ActionView (select_options.join("\n") + "\n").html_safe end + # Build select option HTML for day. + # build_day_options(2) + # => " + # + # ..." + # + # If day_format: ->(day) { day.ordinalize } option is passed to DateTimeSelector + # build_day_options(2) + # => " + # + # ..." + # + # If use_two_digit_numbers: true option is passed to DateTimeSelector + # build_day_options(2) + # => " + # + # ..." + def build_day_options(selected) + select_options = [] + (1..31).each do |value| + tag_options = { value: value } + tag_options[:selected] = "selected" if selected == value + text = day_name(value) + select_options << content_tag("option", text, tag_options) + end + + (select_options.join("\n") + "\n").html_safe + end + # Build select option HTML for year. # If year_format option is not passed # build_year_options(1998, start: 1998, end: 2000) diff --git a/actionview/test/template/date_helper_test.rb b/actionview/test/template/date_helper_test.rb index bef10e6c54..10e4077771 100644 --- a/actionview/test/template/date_helper_test.rb +++ b/actionview/test/template/date_helper_test.rb @@ -251,6 +251,16 @@ class DateHelperTest < ActionView::TestCase assert_dom_equal expected, select_day(2, use_two_digit_numbers: true) end + def test_select_day_with_day_fomat + expected = +%(\n" + + day_format = ->(day) { ActiveSupport::Inflector.ordinalize(day) } + assert_dom_equal expected, select_day(Time.mktime(2011, 8, 2), day_format: day_format) + assert_dom_equal expected, select_day(2, day_format: day_format) + end + def test_select_day_with_html_options expected = +%(