Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
haines committed Nov 19, 2011
2 parents 401e86d + 45ec7a7 commit 6f4b9a3
Show file tree
Hide file tree
Showing 32 changed files with 730 additions and 27 deletions.
1 change: 1 addition & 0 deletions lib/formtastic/inputs/base/choices.rb
Expand Up @@ -71,6 +71,7 @@ def choice_input_dom_id(choice)
[
builder.custom_namespace,
sanitized_object_name,
builder.options[:index],
association_primary_key || method,
choice_html_safe_value(choice)
].compact.reject { |i| i.blank? }.join("_")
Expand Down
13 changes: 9 additions & 4 deletions lib/formtastic/inputs/base/collections.rb
Expand Up @@ -54,18 +54,23 @@ def collection_from_options

def collection_from_association
if reflection
raise PolymorphicInputWithoutCollectionError.new("A collection must be supplied for #{method} input. Collections cannot be guessed for polymorphic associations.") if reflection.options && reflection.options[:polymorphic] == true
if reflection.respond_to?(:options)
raise PolymorphicInputWithoutCollectionError.new(
"A collection must be supplied for #{method} input. Collections cannot be guessed for polymorphic associations."
) if reflection.options[:polymorphic] == true
end

find_options_from_options = options[:find_options] || {}
conditions_from_options = find_options_from_options[:conditions] || {}
conditions_from_reflection = reflection.options && reflection.options[:conditions] || {}
conditions_from_reflection = (reflection.respond_to?(:options) && reflection.options[:conditions]) || {}
conditions_from_reflection = conditions_from_reflection.call if conditions_from_reflection.is_a?(Proc)

scope_conditions = conditions_from_reflection.empty? ? nil : {:conditions => conditions_from_reflection}
if conditions_from_options.any?
reflection.klass.scoped(:conditions => conditions_from_reflection).where(conditions_from_options)
reflection.klass.scoped(scope_conditions).where(conditions_from_options)
else
find_options_from_options.merge!(:include => group_by) if self.respond_to?(:group_by) && group_by
reflection.klass.scoped(:conditions => conditions_from_reflection).where(find_options_from_options)
reflection.klass.scoped(scope_conditions).where(find_options_from_options)
end
end
end
Expand Down
10 changes: 9 additions & 1 deletion lib/formtastic/inputs/base/timeish.rb
Expand Up @@ -156,10 +156,18 @@ def value
end

def fragment_input_html(fragment)
opts = input_options.merge(:prefix => object_name, :field_name => fragment_name(fragment), :default => value, :include_blank => include_blank?)
opts = input_options.merge(:prefix => fragment_prefix, :field_name => fragment_name(fragment), :default => value, :include_blank => include_blank?)
template.send(:"select_#{fragment}", value, opts, input_html_options.merge(:id => fragment_id(fragment)))
end

def fragment_prefix
if builder.options.key?(:index)
object_name + "[#{builder.options[:index]}]"
else
object_name
end
end

# TODO extract to BlankOptions or similar -- Select uses similar code
def include_blank?
options.key?(:include_blank) ? options[:include_blank] : builder.include_blank_for_select_by_default
Expand Down
9 changes: 8 additions & 1 deletion lib/formtastic/inputs/base/validations.rb
Expand Up @@ -183,7 +183,14 @@ def autofocus?
end

def column_limit
column.limit if column? && column.respond_to?(:limit)
if column? && column.respond_to?(:limit)
case column.type
when :integer
(2 ** (column.limit * 8)).to_s.length + 1
else
column.limit
end
end
end

def limit
Expand Down
13 changes: 10 additions & 3 deletions lib/formtastic/inputs/base/wrapping.rb
Expand Up @@ -14,9 +14,16 @@ def input_wrapping(&block)
end

def wrapper_html_options
opts = options[:wrapper_html] || {}
opts[:class] ||= []
opts[:class] = [opts[:class].to_s] unless opts[:class].is_a?(Array)
opts = (options[:wrapper_html] || {}).dup
opts[:class] =
case opts[:class]
when Array
opts[:class].dup
when nil
[]
else
[opts[:class].to_s]
end
opts[:class] << as
opts[:class] << "input"
opts[:class] << "error" if errors?
Expand Down
10 changes: 9 additions & 1 deletion lib/formtastic/inputs/boolean_input.rb
Expand Up @@ -84,7 +84,15 @@ def responds_to_global_required?
end

def input_html_options
{:name => "#{object_name}[#{method}]"}.merge(super)
{:name => input_html_options_name}.merge(super)
end

def input_html_options_name
if builder.options.key?(:index)
"#{object_name}[#{builder.options[:index]}][#{method}]"
else
"#{object_name}[#{method}]"
end
end

def checked?
Expand Down
6 changes: 5 additions & 1 deletion lib/formtastic/inputs/check_boxes_input.rb
Expand Up @@ -166,7 +166,11 @@ def unchecked_value
end

def input_name
"#{object_name}[#{association_primary_key || method}][]"
if builder.options.key?(:index)
"#{object_name}[#{builder.options[:index]}][#{association_primary_key || method}][]"
else
"#{object_name}[#{association_primary_key || method}][]"
end
end

protected
Expand Down
18 changes: 15 additions & 3 deletions lib/formtastic/inputs/select_input.rb
Expand Up @@ -122,8 +122,8 @@ module Inputs
# <%= f.input :authors, :as => :select, :wrapper_html => { :class => "special" } %>
#
# @example Exclude or include the blank option at the top of the select, or change the prompt
# <%= f.input :author, :as => :select, :input_html => { :include_blank => false } %>
# <%= f.input :author, :as => :select, :input_html => { :include_blank => true } %>
# <%= f.input :author, :as => :select, :include_blank => false %>
# <%= f.input :author, :as => :select, :include_blank => true %>
# <%= f.input :author, :as => :select, :input_html => { :prompt => "Please select an Author..." } %>
#
# @example Group options an `<optgroup>` with the `:group_by` and `:group_label` options (`belongs_to` associations only)
Expand Down Expand Up @@ -186,9 +186,21 @@ def input_html_options
def extra_input_html_options
{
:multiple => multiple?,
:name => "#{object_name}[#{association_primary_key}]#{'[]' if multiple?}"
:name => multiple? ? input_html_options_name_multiple : input_html_options_name
}
end

def input_html_options_name
if builder.options.key?(:index)
"#{object_name}[#{builder.options[:index]}][#{association_primary_key}]"
else
"#{object_name}[#{association_primary_key}]"
end
end

def input_html_options_name_multiple
input_html_options_name + "[]"
end

def multiple_by_association?
reflection && [ :has_many, :has_and_belongs_to_many ].include?(reflection.macro)
Expand Down
6 changes: 3 additions & 3 deletions lib/formtastic/inputs/text_input.rb
Expand Up @@ -9,16 +9,16 @@ module Inputs
#
# <%= semantic_form_for(@user) do |f| %>
# <%= f.inputs do %>
# <%= f.input :first_name, :as => :string %>
# <%= f.input :first_name, :as => :text %>
# <% end %>
# <% end %>
#
# <form...>
# <fieldset>
# <ol>
# <li class="string">
# <li class="text">
# <label for="user_first_name">First name</label>
# <input type="text" id="user_first_name" name="user[first_name]">
# <textarea cols="30" id="user_first_name" name="user[first_name]" rows="20"></textarea>
# </li>
# </ol>
# </fieldset>
Expand Down
18 changes: 11 additions & 7 deletions lib/formtastic/inputs/time_input.rb
Expand Up @@ -15,24 +15,28 @@ def fragments
time_fragments
end

def value_or_default_value
value ? value : Time.current
end

def fragment_value(fragment)
value_or_default_value.send(fragment)
value ? value.send(fragment) : ""
end

def hidden_fragments
if !options[:ignore_date]
date_fragments.map do |fragment|
template.hidden_field_tag("#{object_name}[#{fragment_name(fragment)}]", fragment_value(fragment), :id => fragment_id(fragment), :disabled => input_html_options[:disabled] )
template.hidden_field_tag(hidden_field_name(fragment), fragment_value(fragment), :id => fragment_id(fragment), :disabled => input_html_options[:disabled] )
end.join.html_safe
else
super
end
end

def hidden_field_name(fragment)
if builder.options.key?(:index)
"#{object_name}[#{builder.options[:index]}][#{fragment_name(fragment)}]"
else
"#{object_name}[#{fragment_name(fragment)}]"
end
end

end
end
end
end
14 changes: 14 additions & 0 deletions spec/builder/semantic_fields_for_spec.rb
Expand Up @@ -98,6 +98,20 @@
end)
output_buffer.should have_tag('form fieldset.inputs #context2_post_author_1_login_input')
end

it 'should render errors on the nested inputs' do
@errors = mock('errors')
@errors.stub!(:[]).with(:login).and_return(['oh noes'])
@bob.stub!(:errors).and_return(@errors)

concat(semantic_form_for(@new_post, :namespace => 'context2') do |builder|
concat(builder.semantic_fields_for(@bob) do |nested_builder|
concat(nested_builder.inputs(:login))
end)
end)
output_buffer.should =~ /oh noes/
end

end

context "when I rendered my own hidden id input" do
Expand Down
33 changes: 31 additions & 2 deletions spec/inputs/boolean_input_spec.rb
Expand Up @@ -21,8 +21,6 @@

it 'should generate a label containing the input' do
output_buffer.should_not have_tag('label.label')


output_buffer.should have_tag('form li label', :count => 1)
output_buffer.should have_tag('form li label[@for="post_allow_comments"]')
output_buffer.should have_tag('form li label', /Allow comments/)
Expand Down Expand Up @@ -186,5 +184,36 @@
it_should_have_an_inline_label_for("context2_post_allow_comments")

end

describe "when index is provided" do

before do
@output_buffer = ''
mock_everything

concat(semantic_form_for(@new_post) do |builder|
concat(builder.fields_for(:author, :index => 3) do |author|
concat(author.input(:name, :as => :boolean))
end)
end)
end

it 'should index the id of the wrapper' do
output_buffer.should have_tag("li#post_author_attributes_3_name_input")
end

it 'should index the id of the input tag' do
output_buffer.should have_tag("input#post_author_attributes_3_name")
end

it 'should index the name of the hidden input' do
output_buffer.should have_tag("input[@type='hidden'][@name='post[author_attributes][3][name]']")
end

it 'should index the name of the checkbox input' do
output_buffer.should have_tag("input[@type='checkbox'][@name='post[author_attributes][3][name]']")
end

end

end
28 changes: 28 additions & 0 deletions spec/inputs/check_boxes_input_spec.rb
Expand Up @@ -392,6 +392,34 @@
it_should_have_input_with_id('context2_author_post_ids_19')
it_should_have_input_wrapper_with_id("context2_author_posts_input")
end

describe "when index is provided" do

before do
@output_buffer = ''
mock_everything

concat(semantic_form_for(@fred) do |builder|
concat(builder.fields_for(@fred.posts.first, :index => 3) do |author|
concat(author.input(:authors, :as => :check_boxes))
end)
end)
end

it 'should index the id of the wrapper' do
output_buffer.should have_tag("li#author_post_3_authors_input")
end

it 'should index the id of the input tag' do
output_buffer.should have_tag("input#author_post_3_author_ids_42")
end

it 'should index the name of the checkbox input' do
output_buffer.should have_tag("input[@type='checkbox'][@name='author[post][3][author_ids][]']")
end

end


describe "when collection is an array" do
before do
Expand Down
31 changes: 31 additions & 0 deletions spec/inputs/date_input_spec.rb
Expand Up @@ -70,6 +70,37 @@
it_should_have_select_with_id("context2_post_publish_at_3i")

end

describe "when index is provided" do

before do
@output_buffer = ''
mock_everything

concat(semantic_form_for(@new_post) do |builder|
concat(builder.fields_for(:author, :index => 3) do |author|
concat(author.input(:created_at, :as => :date))
end)
end)
end

it 'should index the id of the wrapper' do
output_buffer.should have_tag("li#post_author_attributes_3_created_at_input")
end

it 'should index the id of the select tag' do
output_buffer.should have_tag("select#post_author_attributes_3_created_at_1i")
output_buffer.should have_tag("select#post_author_attributes_3_created_at_2i")
output_buffer.should have_tag("select#post_author_attributes_3_created_at_3i")
end

it 'should index the name of the select tag' do
output_buffer.should have_tag("select[@name='post[author_attributes][3][created_at(1i)]']")
output_buffer.should have_tag("select[@name='post[author_attributes][3][created_at(2i)]']")
output_buffer.should have_tag("select[@name='post[author_attributes][3][created_at(3i)]']")
end

end

describe ':labels option' do
fields = [:year, :month, :day]
Expand Down
36 changes: 36 additions & 0 deletions spec/inputs/datetime_input_spec.rb
Expand Up @@ -76,6 +76,42 @@

end

describe "when index is provided" do

before do
@output_buffer = ''
mock_everything

concat(semantic_form_for(@new_post) do |builder|
concat(builder.fields_for(:author, :index => 3) do |author|
concat(author.input(:created_at, :as => :datetime))
end)
end)
end

it 'should index the id of the wrapper' do
output_buffer.should have_tag("li#post_author_attributes_3_created_at_input")
end

it 'should index the id of the select tag' do
output_buffer.should have_tag("select#post_author_attributes_3_created_at_1i")
output_buffer.should have_tag("select#post_author_attributes_3_created_at_2i")
output_buffer.should have_tag("select#post_author_attributes_3_created_at_3i")
output_buffer.should have_tag("select#post_author_attributes_3_created_at_4i")
output_buffer.should have_tag("select#post_author_attributes_3_created_at_5i")
end

it 'should index the name of the select tag' do
output_buffer.should have_tag("select[@name='post[author_attributes][3][created_at(1i)]']")
output_buffer.should have_tag("select[@name='post[author_attributes][3][created_at(2i)]']")
output_buffer.should have_tag("select[@name='post[author_attributes][3][created_at(3i)]']")
output_buffer.should have_tag("select[@name='post[author_attributes][3][created_at(4i)]']")
output_buffer.should have_tag("select[@name='post[author_attributes][3][created_at(5i)]']")
end

end


describe ':labels option' do
fields = [:year, :month, :day, :hour, :minute]
fields.each do |field|
Expand Down

0 comments on commit 6f4b9a3

Please sign in to comment.