Skip to content

Commit

Permalink
Merge pull request #885 from dwbutler/master
Browse files Browse the repository at this point in the history
Add support for Sets and Symbols as collections for collections (check box, radio and select inputs).
  • Loading branch information
justinfrench committed Apr 1, 2014
2 parents 14f320e + 116f8b1 commit 3aecd12
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 2 deletions.
2 changes: 1 addition & 1 deletion lib/formtastic/inputs/base/collections.rb
Expand Up @@ -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

Expand Down
8 changes: 7 additions & 1 deletion lib/formtastic/inputs/check_boxes_input.rb
Expand Up @@ -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 %>
Expand Down Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions lib/formtastic/inputs/radio_input.rb
Expand Up @@ -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)
Expand Down
18 changes: 18 additions & 0 deletions spec/inputs/check_boxes_input_spec.rb
Expand Up @@ -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

Expand Down
18 changes: 18 additions & 0 deletions spec/inputs/radio_input_spec.rb
Expand Up @@ -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
20 changes: 20 additions & 0 deletions spec/inputs/select_input_spec.rb
Expand Up @@ -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
Expand Down

0 comments on commit 3aecd12

Please sign in to comment.