Collections - support for sets and symbols #885

Merged
merged 8 commits into from Apr 1, 2014
@@ -124,7 +124,7 @@ def send_or_call(duck, object)
# Avoids an issue where `send_or_call` can be a String and duck can be something simple like
# `:first`, which obviously String responds to.
def send_or_call_or_object(duck, object)
- return object if object.is_a?(String) || object.is_a?(Integer) # TODO what about other classes etc?
+ return object if object.is_a?(String) || object.is_a?(Integer) || object.is_a?(Symbol) # TODO what about other classes etc?
send_or_call(duck, object)
end
@@ -46,6 +46,9 @@ module Inputs
# <%= f.input :categories, :as => :check_boxes, :collection => [["Ruby", 1], ["Rails", 2]] %>
# <%= f.input :categories, :as => :check_boxes, :collection => [["Ruby", 1, {'data-attr' => 'attr-value'}]] %>
# <%= f.input :categories, :as => :check_boxes, :collection => 1..5 %>
+ # <%= f.input :categories, :as => :check_boxes, :collection => [:ruby, :rails] %>
+ # <%= f.input :categories, :as => :check_boxes, :collection => [["Ruby", :ruby], ["Rails", :rails]] %>
+ # <%= f.input :categories, :as => :check_boxes, :collection => Set.new([:ruby, :rails]) %>
#
# @example `:hidden_fields` can be used to skip Rails' rendering of a hidden field before every checkbox
# <%= f.input :categories, :as => :check_boxes, :hidden_fields => false %>
@@ -182,7 +185,10 @@ def input_name
def make_selected_values
if object.respond_to?(method)
- selected_items = [object.send(method)].compact.flatten
+ selected_items = object.send(method)
+
+ # Construct an array from the return value, regardless of the return type
+ selected_items = [*selected_items].compact.flatten
[*selected_items.map { |o| send_or_call_or_object(value_method, o) }].compact
else
@@ -83,6 +83,8 @@ module Inputs
# <%= f.input :author, :as => :radio, :collection => [["Justin", "justin"], ["Kate", "kate"]] %>
# <%= f.input :author, :as => :radio, :collection => [["Justin", "1"], ["Kate", "3"]] %>
# <%= f.input :author, :as => :radio, :collection => [["Justin", 1], ["Kate", 3]] %>
+ # <%= f.input :author, :as => :radio, :collection => [["Justin", :justin], ["Kate", :kate]] %>
+ # <%= f.input :author, :as => :radio, :collection => [:justin, :kate] %>
# <%= f.input :author, :as => :radio, :collection => 1..5 %>
#
# @example The `:member_label` can be used to call a different method (or a Proc) on each object in the collection for rendering the label text (it'll try the methods like `to_s` in `collection_label_methods` config by default)
@@ -373,6 +373,24 @@
output_buffer.should have_tag("form li fieldset ol li label input[@value='biography'][@checked='checked']")
end
end
+
+ describe 'when :collection is a set' do
+ before do
+ @output_buffer = ''
+ mock_everything
+ @fred.stub(:roles) { Set.new([:reviewer, :admin]) }
+
+ concat(semantic_form_for(@fred) do |builder|
+ concat(builder.input(:roles, :as => :check_boxes, :collection => [['User', :user], ['Reviewer', :reviewer], ['Administrator', :admin]]))
+ end)
+ end
+
+ it 'should check the correct checkboxes' do
+ output_buffer.should have_tag("form li fieldset ol li label input[@value='user']")
+ output_buffer.should have_tag("form li fieldset ol li label input[@value='admin'][@checked='checked']")
+ output_buffer.should have_tag("form li fieldset ol li label input[@value='reviewer'][@checked='checked']")
+ end
+ end
describe "when namespace is provided" do
@@ -279,4 +279,22 @@
end
end
+ describe "when collection contains symbols" do
+ before do
+ @output_buffer = ''
+ mock_everything
+
+ concat(semantic_form_for(:project) do |builder|
+ concat(builder.input(:author_id, :as => :radio, :collection => Set.new([["A", :a], ["B", :b], ["C", :c]])))
+ end)
+ end
+
+ it 'should output the correct labels' do
+ output_buffer.should have_tag("li.choice label", /A/)
+ output_buffer.should have_tag("li.choice label", /B/)
+ output_buffer.should have_tag("li.choice label", /C/)
+ end
+ end
+
+
end
@@ -30,6 +30,26 @@
end
end
end
+
+ describe 'using a set of values' do
+ before do
+ @set_with_values = Set.new(["Title A", "Title B", "Title C"])
+ @set_with_keys_and_values = [["Title D", :d], ["Title E", :e], ["Title F", :f]]
+ concat(semantic_form_for(@new_post) do |builder|
+ concat(builder.input(:title, :as => :select, :collection => @set_with_values))
+ concat(builder.input(:title, :as => :select, :collection => @set_with_keys_and_values))
+ end)
+ end
+
+ it 'should have a option for each key and/or value' do
+ @set_with_values.each do |v|
+ output_buffer.should have_tag("form li select option[@value='#{v}']", /^#{v}$/)
+ end
+ @set_with_keys_and_values.each do |v|
+ output_buffer.should have_tag("form li select option[@value='#{v.second}']", /^#{v.first}$/)
+ end
+ end
+ end
describe "using a related model without reflection's options (Mongoid Document)" do
before do