diff --git a/lib/formtastic/inputs/range_input.rb b/lib/formtastic/inputs/range_input.rb index 59b54e158..8738921b4 100644 --- a/lib/formtastic/inputs/range_input.rb +++ b/lib/formtastic/inputs/range_input.rb @@ -4,10 +4,14 @@ module RangeInput include Formtastic::Inputs::Base def range_input(method, options) - reflections = @object.class.reflect_on_validations_for(method) if @object.class.respond_to?(:reflect_on_validations_for) - reflections.each do |reflection| - if reflection.macro == :validates_numericality_of - unless options.include? :in + options[:input_html] ||= {} + options[:input_html][:in] = options.delete(:in) + options[:input_html][:step] = options.delete(:step) || 1 + + unless options[:input_html][:in] + reflections = @object.class.reflect_on_validations_for(method) rescue [] + reflections.each do |reflection| + if reflection.macro == :validates_numericality_of if reflection.options.include?(:greater_than) range_start = (reflection.options[:greater_than] + 1) elsif reflection.options.include?(:greater_than_or_equal_to) @@ -18,10 +22,9 @@ def range_input(method, options) elsif reflection.options.include?(:less_than_or_equal_to) range_end = reflection.options[:less_than_or_equal_to] end + + options[:input_html][:in] = (range_start..range_end) end - options[:input_html] ||= {} - options[:input_html][:in] = options.delete(:in) || (range_start..range_end) - options[:input_html][:step] = options.delete(:step) || 1 end end diff --git a/spec/inputs/range_input_spec.rb b/spec/inputs/range_input_spec.rb new file mode 100644 index 000000000..f1e03c949 --- /dev/null +++ b/spec/inputs/range_input_spec.rb @@ -0,0 +1,88 @@ +# encoding: utf-8 +require 'spec_helper' +require 'active_record' + +describe 'range input' do + + include FormtasticSpecHelper + + before do + @output_buffer = '' + mock_everything + end + + describe "when object is provided" do + before do + concat(semantic_form_for(@bob) do |builder| + concat(builder.input(:age, :as => :range)) + end) + end + + it_should_have_input_wrapper_with_class(:range) + it_should_have_input_wrapper_with_id("author_age_input") + it_should_have_label_with_text(/Age/) + it_should_have_label_for("author_age") + it_should_have_input_with_id("author_age") + it_should_have_input_with_type(:range) + it_should_have_input_with_name("author[age]") + + end + + describe "when namespace is provided" do + + before do + concat(semantic_form_for(@james, :namespace => "context2") do |builder| + concat(builder.input(:age, :as => :range)) + end) + end + + it_should_have_input_wrapper_with_id("context2_author_age_input") + it_should_have_label_and_input_with_id("context2_author_age") + + end + + describe "core processing" do + + before { mock_everything; @options = {} } + + describe "with validation_reflection" do + + before do + # Insane, but we need to test with and without validation_reflection + ::Author.stub!(:reflect_on_validations_for).with(:age).and_return([ActiveRecord::Reflection::MacroReflection.new(:validates_numericality_of, :age, {:greater_than => 0, :less_than => 6}, ::Author)]) + end + + it "works with alternate validation options" do + ::Author.stub!(:reflect_on_validations_for).with(:age).and_return([ActiveRecord::Reflection::MacroReflection.new(:validates_numericality_of, :age, {:greater_than_or_equal_to => 1930, :less_than_or_equal_to => (Time.now.year - 5)}, ::Author)]) + + concat(semantic_form_for(@james) do |builder| + concat(builder.input(:age, @options.merge(:as => :range))) + end) + + output_buffer.should have_tag("form li input[step=\"1\"][min=\"1930\"][max=\"#{Time.now.year - 5}\"]") + end + + it "assigns range and step from model" do + concat(semantic_form_for(@james) do |builder| + concat(builder.input(:age, @options.merge(:as => :range))) + end) + + output_buffer.should have_tag("form li input[step=\"1\"][min=\"1\"][max=\"5\"]") + end + + it "allows for overriding range and step values" do + @options.merge! :in => 9..10, :step => 0.2 + + concat(semantic_form_for(@james) do |builder| + concat(builder.input(:age, @options.merge(:as => :range))) + end) + + output_buffer.should have_tag("form li input[step=\"0.2\"][min=\"9\"][max=\"10\"]") + end + + end + + end + +end + diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 6ef70e005..5b05e27bc 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -121,6 +121,7 @@ def new_author_path; "/authors/new"; end @fred.stub!(:class).and_return(::Author) @fred.stub!(:to_label).and_return('Fred Smith') @fred.stub!(:login).and_return('fred_smith') + @fred.stub!(:age).and_return(27) @fred.stub!(:id).and_return(37) @fred.stub!(:new_record?).and_return(false) @fred.stub!(:errors).and_return(mock('errors', :[] => nil)) @@ -130,6 +131,7 @@ def new_author_path; "/authors/new"; end @bob = ::Author.new @bob.stub!(:to_label).and_return('Bob Rock') @bob.stub!(:login).and_return('bob') + @bob.stub!(:age).and_return(43) @bob.stub!(:created_at) @bob.stub!(:id).and_return(42) @bob.stub!(:posts).and_return([]) @@ -142,6 +144,7 @@ def new_author_path; "/authors/new"; end @james = ::Author.new @james.stub!(:to_label).and_return('James Shock') @james.stub!(:login).and_return('james') + @james.stub!(:age).and_return(38) @james.stub!(:id).and_return(75) @james.stub!(:posts).and_return([]) @james.stub!(:post_ids).and_return([])