A saner alternative to SimpleForm's :grouped_select input type

Updated . Posted . Visible to the public.

SimpleForm Show archive.org snapshot is a great approach to simplifying your forms, and it comes with lots of well-defined input types. However, the :grouped_select type seems to be overly complicated for most use cases.

Example

Consider this example, from the documentation:

form.input :country_id, collection: @continents,
  as: :grouped_select, group_method: :countries

While that looks easy enough at a first glance, look closer. The example passes @continents for a country_id.\
SimpleForm actually expects :collection to be a somewhat grouped collection (array of arrays, hash, ...) that it can read from.

In "the real world" you usually already have your list of items to select from, like @countries. To make that work with SimpleForm, you'd have to do crazy things like the following.

form.input :country_id, collection: @countries.group_by(&:continent_name),
  as: :grouped_select, group_method: :last, group_label_method: :first

Solution

Often times, you would want to say something like

form.input :country_id, collection: @countries,
  as: :grouped_select, group_by: :continent_name # new option "group_by"

or

form.input :country_id, collection: @countries,
  as: :grouped_select, group_by: proc { |country| country.continent.name }

Here is an extension to :grouped_select which will allow you to do exactly that, yet keeping SimpleForm's API in case you need it.

class GroupedCollectionSelectInput < SimpleForm::Inputs::GroupedCollectionSelectInput

  def input
    group_by = options.delete(:group_by)
    if group_by
      grouped_collection = options[:collection].group_by(&group_by)

      options[:collection] = grouped_collection
      options[:group_method] = :last
      options[:group_label_method] = :first
    end

    super
  end

end

Put that file into a place like app/inputs/grouped_collection_select_input.rb (SimpleForm will pick it up automatically; if it does not, restart your Rails server) and use it in your form with that new :group_by option.

Note that this only works if you are grouping by something that should be the human-readable optgroup label which is almost always the case.

Arne Hartherz
Last edit
Michael Leimstädtner
License
Source code in this card is licensed under the MIT License.
Posted by Arne Hartherz to makandra dev (2014-05-23 10:54)