Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Collections - support for sets and symbols #885

Merged
merged 8 commits into from
Apr 1, 2014
2 changes: 1 addition & 1 deletion lib/formtastic/inputs/base/collections.rb
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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