Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Grouped collection input #382

Merged
merged 3 commits into from

4 participants

@semaperepelitsa

I wanted to add grouped collection input so that you could do f.association :category, :collection => Category.roots, :group_method => :children. Rails has grouped_collection_select alongside with collection_select so it should be pretty similar to existing collection input.

The only thing I don't know how to deal with is how SimpleForm maps inputs to classes. Right now every input with collection option maps to select input type which maps to CollectionInput. I wish every input with group_method option map to the same select input type but also somehow map it to GroupedCollectionInput.

Do you like my idea and do you have any suggestions on the problem? Thanks.

@josevalim
Owner

Nice. I would just recommend that instead of checking :group_method, we could simply use :as to specify it:

f.input :authors, :as => :group_select, :collection => some_array

And then instead of having :group_method, we would simply use :value_method and :label_method which are already the official API used by collections.

lib/simple_form/inputs/grouped_collection_input.rb
@@ -0,0 +1,27 @@
+module SimpleForm
+ module Inputs
+ class GroupedCollectionInput < CollectionInput
+ def input
+ group_label_method, label_method, value_method = detect_collection_methods
+ @builder.send(:"grouped_collection_#{input_type}", attribute_name, collection,
@rafaelfranca Collaborator

We don't need this input_type here, neither send. You can call only

@builder.grouped_collection_select(attribute_name, collection,
                                   group_method, group_label_method, value_method, label_method,
                                   input_options, input_html_options)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@semaperepelitsa

Good point, I will do that. Do you think group_select is a good name? I would call it grouped_select because you can't select groups actually and also Rails calls it grouped_collection_select.

semaperepelitsa added some commits
@semaperepelitsa semaperepelitsa Map grouped_select, refactoring class so that method detections work
We need to detect label for group collection separately from child collections because they are probably different
96790f6
@semaperepelitsa semaperepelitsa Group label is now detected ab7cd70
@josevalim
Owner
@carlosantoniodasilva carlosantoniodasilva merged commit 5b2f067 into plataformatec:v1.5
@carlosantoniodasilva carlosantoniodasilva referenced this pull request from a commit
@carlosantoniodasilva carlosantoniodasilva Revert "Merge pull request #382 from semaperepelitsa/grouped_collection"
This reverts commit 5b2f067, reversing
changes made to 9ff998f.

This is going to be applied to master only, sorry.
c7c8461
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Dec 5, 2011
  1. @semaperepelitsa
Commits on Dec 6, 2011
  1. @semaperepelitsa

    Map grouped_select, refactoring class so that method detections work

    semaperepelitsa authored
    We need to detect label for group collection separately from child collections because they are probably different
  2. @semaperepelitsa
This page is out of date. Refresh to see the latest.
View
1  lib/simple_form/form_builder.rb
@@ -12,6 +12,7 @@ class FormBuilder < ActionView::Helpers::FormBuilder
map_type :integer, :decimal, :float, :to => SimpleForm::Inputs::NumericInput
map_type :range, :to => SimpleForm::Inputs::RangeInput
map_type :select, :radio, :check_boxes, :to => SimpleForm::Inputs::CollectionInput
+ map_type :grouped_select, :to => SimpleForm::Inputs::GroupedCollectionInput
map_type :date, :time, :datetime, :to => SimpleForm::Inputs::DateTimeInput
map_type :country, :time_zone, :to => SimpleForm::Inputs::PriorityInput
map_type :boolean, :to => SimpleForm::Inputs::BooleanInput
View
27 lib/simple_form/inputs.rb
@@ -1,17 +1,18 @@
module SimpleForm
module Inputs
- autoload :Base, 'simple_form/inputs/base'
- autoload :BlockInput, 'simple_form/inputs/block_input'
- autoload :BooleanInput, 'simple_form/inputs/boolean_input'
- autoload :CollectionInput, 'simple_form/inputs/collection_input'
- autoload :DateTimeInput, 'simple_form/inputs/date_time_input'
- autoload :FileInput, 'simple_form/inputs/file_input'
- autoload :HiddenInput, 'simple_form/inputs/hidden_input'
- autoload :NumericInput, 'simple_form/inputs/numeric_input'
- autoload :PasswordInput, 'simple_form/inputs/password_input'
- autoload :PriorityInput, 'simple_form/inputs/priority_input'
- autoload :RangeInput, 'simple_form/inputs/range_input'
- autoload :StringInput, 'simple_form/inputs/string_input'
- autoload :TextInput, 'simple_form/inputs/text_input'
+ autoload :Base, 'simple_form/inputs/base'
+ autoload :BlockInput, 'simple_form/inputs/block_input'
+ autoload :BooleanInput, 'simple_form/inputs/boolean_input'
+ autoload :CollectionInput, 'simple_form/inputs/collection_input'
+ autoload :GroupedCollectionInput, 'simple_form/inputs/grouped_collection_input'
+ autoload :DateTimeInput, 'simple_form/inputs/date_time_input'
+ autoload :FileInput, 'simple_form/inputs/file_input'
+ autoload :HiddenInput, 'simple_form/inputs/hidden_input'
+ autoload :NumericInput, 'simple_form/inputs/numeric_input'
+ autoload :PasswordInput, 'simple_form/inputs/password_input'
+ autoload :PriorityInput, 'simple_form/inputs/priority_input'
+ autoload :RangeInput, 'simple_form/inputs/range_input'
+ autoload :StringInput, 'simple_form/inputs/string_input'
+ autoload :TextInput, 'simple_form/inputs/text_input'
end
end
View
8 lib/simple_form/inputs/collection_input.rb
@@ -58,9 +58,7 @@ def detect_collection_methods
[label, value]
end
- def detect_common_display_methods
- collection_classes = detect_collection_classes
-
+ def detect_common_display_methods(collection_classes = detect_collection_classes)
if collection_classes.include?(Array)
{ :label => :first, :value => :last }
elsif collection_includes_basic_objects?(collection_classes)
@@ -73,8 +71,8 @@ def detect_common_display_methods
end
end
- def detect_collection_classes
- collection.map { |e| e.class }.uniq
+ def detect_collection_classes(some_collection = collection)
+ some_collection.map { |e| e.class }.uniq
end
def collection_includes_basic_objects?(collection_classes)
View
38 lib/simple_form/inputs/grouped_collection_input.rb
@@ -0,0 +1,38 @@
+module SimpleForm
+ module Inputs
+ class GroupedCollectionInput < CollectionInput
+ def input
+ label_method, value_method = detect_collection_methods
+ @builder.grouped_collection_select(attribute_name, group_collection,
+ group_method, group_label_method, value_method, label_method,
+ input_options, input_html_options)
+ end
+
+ private
+
+ def group_collection
+ @group_collection ||= options.delete(:collection)
+ end
+
+ # Sample collection
+ def collection
+ @collection ||= group_collection.first.try(:send, group_method)
+ end
+
+ def group_method
+ @group_method ||= options.delete(:group_method)
+ end
+
+ def group_label_method
+ label = options.delete(:group_label_method)
+
+ unless label
+ common_method_for = detect_common_display_methods( detect_collection_classes(group_collection) )
+ label = common_method_for[:label]
+ end
+
+ label
+ end
+ end
+ end
+end
View
18 test/inputs_test.rb
@@ -976,6 +976,24 @@ def with_input_for(object, attribute_name, type, options={})
assert_no_select 'select[required]'
end
+ # GroupedCollectionInput
+ test 'input should have grouped options' do
+ with_input_for @user, :name, :grouped_select,
+ :collection => [['Authors', ['Jose', 'Carlos']], ['General', ['Bob', 'John']]],
+ :group_method => :last
+ assert_select 'select.grouped_select#user_name' do
+ assert_select 'optgroup[label=Authors]' do
+ assert_select 'option', 'Jose'
+ assert_select 'option', 'Carlos'
+ end
+
+ assert_select 'optgroup[label=General]' do
+ assert_select 'option', 'Bob'
+ assert_select 'option', 'John'
+ end
+ end
+ end
+
# With no object
test 'input should be generated properly when object is not present' do
with_input_for :project, :name, :string
Something went wrong with that request. Please try again.