From 592570f1bfefaf48deac2f264112bc5bbcc64955 Mon Sep 17 00:00:00 2001 From: Drew Bragg Date: Thu, 5 Aug 2021 20:44:29 -0400 Subject: [PATCH] Add `weekday_options_for_select` method Add `weekday_select` method Create `Tags::WeekdaySelect` class Add `weekday_select` to `FromBuilder` Add Documentation Allow `WeekdaySelect` to use selected option if value is nil Doc fix Add tests Use kwrd args Update CHANGELOG Fix `Tags::WeekdaySelect` for updated kwrd args Update CHANGELOG format Condense `weekday_options_for_select` method Update tests for kwargs --- actionview/CHANGELOG.md | 4 ++ .../helpers/form_options_helper.rb | 34 +++++++++ actionview/lib/action_view/helpers/tags.rb | 1 + .../helpers/tags/weekday_select.rb | 27 +++++++ .../test/template/form_options_helper_test.rb | 70 +++++++++++++++++++ 5 files changed, 136 insertions(+) create mode 100644 actionview/lib/action_view/helpers/tags/weekday_select.rb diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md index f2547d3f70..7955bb155a 100644 --- a/actionview/CHANGELOG.md +++ b/actionview/CHANGELOG.md @@ -1,3 +1,7 @@ +* Add `weekday_options_for_select` and `weekday_select` helper methods. Also adds `weekday_select` to `FormBuilder`. + + *Drew Bragg*, *Dana Kashubeck*, *Kasper Timm Hansen* + * Add `caching?` helper that returns whether the current code path is being cached and `uncacheable!` to denote helper methods that can't participate in fragment caching. *Ben Toews*, *John Hawthorn*, *Kasper Timm Hansen*, *Joel Hawksley* diff --git a/actionview/lib/action_view/helpers/form_options_helper.rb b/actionview/lib/action_view/helpers/form_options_helper.rb index a253ee4363..6e37022bb5 100644 --- a/actionview/lib/action_view/helpers/form_options_helper.rb +++ b/actionview/lib/action_view/helpers/form_options_helper.rb @@ -297,6 +297,12 @@ def time_zone_select(object, method, priority_zones = nil, options = {}, html_op Tags::TimeZoneSelect.new(object, method, self, priority_zones, options, html_options).render end + # Returns select and option tags for the given object and method, using + # #weekday_options_for_select to generate the list of option tags. + def weekday_select(object, method, options = {}, html_options = {}, &block) + Tags::WeekdaySelect.new(object, method, self, options, html_options, &block).render + end + # Accepts a container (hash, array, enumerable, your type) and returns a string of option tags. Given a container # where the elements respond to first and last (such as a two-element array), the "lasts" serve as option values and # the "firsts" as option text. Hashes are turned into this form automatically, so the keys become "firsts" and values @@ -593,6 +599,22 @@ def time_zone_options_for_select(selected = nil, priority_zones = nil, model = : zone_options.safe_concat options_for_select(convert_zones[zones], selected) end + # Returns a string of option tags for the days of the week. + # + # Options: + # * :index_as_value - Defaults to false, set to true to use the index of the weekday as the value. + # * :day_format - The I18n key of the array to use for the weekday options. + # Defaults to :day_names, set to :abbr_day_names for abbreviations. + # + # NOTE: Only the option tags are returned, you have to wrap this call in + # a regular HTML select tag. + def weekday_options_for_select(selected = nil, index_as_value: false, day_format: :day_names) + day_names = I18n.translate("date.#{day_format}") + day_names = day_names.map.with_index.to_h if index_as_value + + options_for_select(day_names, selected) + end + # Returns radio button tags for the collection of existing return values # of +method+ for +object+'s class. The value returned from calling # +method+ on the instance +object+ will be selected. If calling +method+ @@ -859,6 +881,18 @@ def time_zone_select(method, priority_zones = nil, options = {}, html_options = @template.time_zone_select(@object_name, method, priority_zones, objectify_options(options), @default_html_options.merge(html_options)) end + # Wraps ActionView::Helpers::FormOptionsHelper#weekday_select for form builders: + # + # <%= form_for @user do |f| %> + # <%= f.weekday_select :weekday, include_blank: true %> + # <%= f.submit %> + # <% end %> + # + # Please refer to the documentation of the base helper for details. + def weekday_select(method, options = {}, html_options = {}) + @template.weekday_select(@object_name, method, objectify_options(options), @default_html_options.merge(html_options)) + end + # Wraps ActionView::Helpers::FormOptionsHelper#collection_check_boxes for form builders: # # <%= form_for @post do |f| %> diff --git a/actionview/lib/action_view/helpers/tags.rb b/actionview/lib/action_view/helpers/tags.rb index bf289be7b2..39621bbb29 100644 --- a/actionview/lib/action_view/helpers/tags.rb +++ b/actionview/lib/action_view/helpers/tags.rb @@ -38,6 +38,7 @@ module Tags # :nodoc: autoload :TimeZoneSelect autoload :UrlField autoload :WeekField + autoload :WeekdaySelect end end end diff --git a/actionview/lib/action_view/helpers/tags/weekday_select.rb b/actionview/lib/action_view/helpers/tags/weekday_select.rb new file mode 100644 index 0000000000..cb7279c429 --- /dev/null +++ b/actionview/lib/action_view/helpers/tags/weekday_select.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +module ActionView + module Helpers + module Tags # :nodoc: + class WeekdaySelect < Base # :nodoc: + def initialize(object_name, method_name, template_object, options, html_options) + @html_options = html_options + + super(object_name, method_name, template_object, options) + end + + def render + select_content_tag( + weekday_options_for_select( + value || @options[:selected], + index_as_value: @options.fetch(:index_as_value, false), + day_format: @options.fetch(:day_format, :day_names) + ), + @options, + @html_options + ) + end + end + end + end +end diff --git a/actionview/test/template/form_options_helper_test.rb b/actionview/test/template/form_options_helper_test.rb index 952f05b7ec..93e6efce3e 100644 --- a/actionview/test/template/form_options_helper_test.rb +++ b/actionview/test/template/form_options_helper_test.rb @@ -31,6 +31,7 @@ def secret Continent = Struct.new("Continent", :continent_name, :countries) Country = Struct.new("Country", :country_id, :country_name) Album = Struct.new("Album", :id, :title, :genre) + Digest = Struct.new("Digest", :send_day) end class Firm @@ -1507,6 +1508,75 @@ def test_grouped_collection_select_under_fields_for ) end + def test_weekday_options_for_select_with_no_params + assert_dom_equal( + "\n\n\n\n\n\n", + weekday_options_for_select + ) + end + + def test_weekday_options_for_select_with_index_as_value + assert_dom_equal( + "\n\n\n\n\n\n", + weekday_options_for_select(index_as_value: true) + ) + end + + def test_weekday_options_for_select_with_abberviated_day_names + assert_dom_equal( + "\n\n\n\n\n\n", + weekday_options_for_select(day_format: :abbr_day_names) + ) + end + + def test_weekday_options_for_select_with_selected_value + assert_dom_equal( + "\n\n\n\n\n\n", + weekday_options_for_select("Friday") + ) + end + + def test_weekday_select + assert_dom_equal( + "", + weekday_select(:model, :weekday) + ) + end + + def test_weekday_select_with_selected_value + assert_dom_equal( + "", + weekday_select(:model, :weekday, selected: "Friday") + ) + end + + def test_weekday_select_under_fields_for + @digest = Digest.new + + output_buffer = fields_for :digest, @digest do |f| + concat f.weekday_select(:send_day) + end + + assert_dom_equal( + "", + output_buffer + ) + end + + def test_weekday_select_under_fields_for_with_value + @digest = Digest.new + @digest.send_day = "Monday" + + output_buffer = fields_for :digest, @digest do |f| + concat f.weekday_select(:send_day) + end + + assert_dom_equal( + "", + output_buffer + ) + end + private def dummy_posts [ Post.new(" went home", "", "To a little house", "shh!"),