Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Grouped collection input #382

Merged
merged 3 commits into from

4 participants

Semyon Perepelitsa José Valim Rafael Mendonça França Carlos Antonio da Silva
Semyon Perepelitsa

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.

José Valim
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,
Rafael Mendonça França Owner

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
Semyon Perepelitsa

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
Semyon Perepelitsa 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
Semyon Perepelitsa semaperepelitsa Group label is now detected ab7cd70
José Valim
Owner
Carlos Antonio da Silva carlosantoniodasilva merged commit 5b2f067 into from
Carlos Antonio da Silva carlosantoniodasilva referenced this pull request from a commit
Carlos Antonio da Silva 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. Semyon Perepelitsa
Commits on Dec 6, 2011
  1. Semyon Perepelitsa

    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. Semyon Perepelitsa
This page is out of date. Refresh to see the latest.
1  lib/simple_form/form_builder.rb
View
@@ -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
27 lib/simple_form/inputs.rb
View
@@ -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
8 lib/simple_form/inputs/collection_input.rb
View
@@ -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)
38 lib/simple_form/inputs/grouped_collection_input.rb
View
@@ -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
18 test/inputs_test.rb
View
@@ -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.