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.