diff --git a/lib/validates_timeliness/action_view/instance_tag.rb b/lib/validates_timeliness/action_view/instance_tag.rb index 9201d48..4a96d63 100644 --- a/lib/validates_timeliness/action_view/instance_tag.rb +++ b/lib/validates_timeliness/action_view/instance_tag.rb @@ -1,3 +1,4 @@ +# TODO remove this from the plugin for v3. module ValidatesTimeliness def self.enable_datetime_select_invalid_value_extension! @@ -6,13 +7,10 @@ module ValidatesTimeliness module ActionView - # Intercepts the date and time select helpers to allow the - # attribute value before type cast to be used as in the select helpers. - # This means that an invalid date or time will be redisplayed rather than the - # type cast value which would be nil if invalid. - # - # Its a minor user experience improvement to be able to see original value - # entered to aid correction. + # Intercepts the date and time select helpers to reuse the values from the + # the params rather than the parsed value. This allows invalid date/time + # values to be redisplayed instead of blanks to aid correction by the user. + # Its a minor usability improvement which is rarely an issue for the user. # module InstanceTag @@ -33,19 +31,19 @@ module ValidatesTimeliness end def value_with_timeliness(object) - return value_without_timeliness(object) unless @timeliness_date_or_time_tag - - raw_value = value_before_type_cast(object) - - if raw_value.nil? || raw_value.acts_like?(:time) || raw_value.is_a?(Date) + unless @timeliness_date_or_time_tag && @template_object.params[@object_name] return value_without_timeliness(object) end - date, time = raw_value.split(' ') - date_array = date.split('-') - time_array = time.split(':') + pairs = @template_object.params[@object_name].select {|k,v| k =~ /^#{@method_name}\(/ } + return value_without_timeliness(object) if pairs.empty? - TimelinessDateTime.new(*(date_array + time_array).map {|v| v.blank? ? nil : v.to_i}) + values = pairs.map do |(param, value)| + position = param.scan(/\(([0-9]*).*\)/).first.first + [position, value] + end.sort {|a,b| a[0] <=> b[0] }.map {|v| v[1] } + + TimelinessDateTime.new(*values) end end diff --git a/spec/action_view/instance_tag_spec.rb b/spec/action_view/instance_tag_spec.rb index 33ddaa5..536ecf9 100644 --- a/spec/action_view/instance_tag_spec.rb +++ b/spec/action_view/instance_tag_spec.rb @@ -8,73 +8,186 @@ describe 'ValidatesTimeliness::ActionView::InstanceTag' do @person = Person.new end - it "should display invalid datetime as datetime_select values" do - @person.birth_date_and_time = "2008-02-30 12:00:22" - output = datetime_select(:person, :birth_date_and_time, :include_blank => true, :include_seconds => true) + def params + @params ||= {} + end - output.should have_tag('select[id=person_birth_date_and_time_1i]') do - with_tag('option[selected=selected]', '2008') + describe "datetime_select" do + it "should use param values when attribute is nil" do + params["person"] = { + "birth_date_and_time(1i)" => 2009, + "birth_date_and_time(2i)" => 2, + "birth_date_and_time(3i)" => 29, + "birth_date_and_time(4i)" => 12, + "birth_date_and_time(5i)" => 13, + "birth_date_and_time(6i)" => 14, + } + @person.birth_date_and_time = nil + output = datetime_select(:person, :birth_date_and_time, :include_blank => true, :include_seconds => true) + output.should have_tag('select[id=person_birth_date_and_time_1i] option[selected=selected]', '2009') + output.should have_tag('select[id=person_birth_date_and_time_2i] option[selected=selected]', 'February') + output.should have_tag('select[id=person_birth_date_and_time_3i] option[selected=selected]', '29') + output.should have_tag('select[id=person_birth_date_and_time_4i] option[selected=selected]', '12') + output.should have_tag('select[id=person_birth_date_and_time_5i] option[selected=selected]', '13') + output.should have_tag('select[id=person_birth_date_and_time_6i] option[selected=selected]', '14') end - output.should have_tag('select[id=person_birth_date_and_time_2i]') do - with_tag('option[selected=selected]', 'February') + + it "should override object values and use params if present" do + params["person"] = { + "birth_date_and_time(1i)" => 2009, + "birth_date_and_time(2i)" => 2, + "birth_date_and_time(3i)" => 29, + "birth_date_and_time(4i)" => 13, + "birth_date_and_time(5i)" => 14, + "birth_date_and_time(6i)" => 15, + } + @person.birth_date_and_time = "2009-03-01 13:14:15" + output = datetime_select(:person, :birth_date_and_time, :include_blank => true, :include_seconds => true) + output.should have_tag('select[id=person_birth_date_and_time_1i] option[selected=selected]', '2009') + output.should have_tag('select[id=person_birth_date_and_time_2i] option[selected=selected]', 'February') + output.should have_tag('select[id=person_birth_date_and_time_3i] option[selected=selected]', '29') + output.should have_tag('select[id=person_birth_date_and_time_4i] option[selected=selected]', '13') + output.should have_tag('select[id=person_birth_date_and_time_5i] option[selected=selected]', '14') + output.should have_tag('select[id=person_birth_date_and_time_6i] option[selected=selected]', '15') end - output.should have_tag('select[id=person_birth_date_and_time_3i]') do - with_tag('option[selected=selected]', '30') + + it "should select attribute values from object if no params" do + @person.birth_date_and_time = "2009-01-02 13:14:15" + output = datetime_select(:person, :birth_date_and_time, :include_blank => true, :include_seconds => true) + output.should have_tag('select[id=person_birth_date_and_time_1i] option[selected=selected]', '2009') + output.should have_tag('select[id=person_birth_date_and_time_2i] option[selected=selected]', 'January') + output.should have_tag('select[id=person_birth_date_and_time_3i] option[selected=selected]', '2') + output.should have_tag('select[id=person_birth_date_and_time_4i] option[selected=selected]', '13') + output.should have_tag('select[id=person_birth_date_and_time_5i] option[selected=selected]', '14') + output.should have_tag('select[id=person_birth_date_and_time_6i] option[selected=selected]', '15') end - output.should have_tag('select[id=person_birth_date_and_time_4i]') do - with_tag('option[selected=selected]', '12') + + it "should select attribute values if params does not contain attribute params" do + @person.birth_date_and_time = "2009-01-02 13:14:15" + params["person"] = { } + output = datetime_select(:person, :birth_date_and_time, :include_blank => true, :include_seconds => true) + output.should have_tag('select[id=person_birth_date_and_time_1i] option[selected=selected]', '2009') + output.should have_tag('select[id=person_birth_date_and_time_2i] option[selected=selected]', 'January') + output.should have_tag('select[id=person_birth_date_and_time_3i] option[selected=selected]', '2') + output.should have_tag('select[id=person_birth_date_and_time_4i] option[selected=selected]', '13') + output.should have_tag('select[id=person_birth_date_and_time_5i] option[selected=selected]', '14') + output.should have_tag('select[id=person_birth_date_and_time_6i] option[selected=selected]', '15') end - output.should have_tag('select[id=person_birth_date_and_time_5i]') do - with_tag('option[selected=selected]', '00') - end - output.should have_tag('select[id=person_birth_date_and_time_6i]') do - with_tag('option[selected=selected]', '22') + + it "should not select values when attribute value is nil and has no param values" do + @person.birth_date_and_time = nil + output = datetime_select(:person, :birth_date_and_time, :include_blank => true, :include_seconds => true) + output.should_not have_tag('select[id=person_birth_date_and_time_1i] option[selected=selected]') + output.should_not have_tag('select[id=person_birth_date_and_time_2i] option[selected=selected]') + output.should_not have_tag('select[id=person_birth_date_and_time_3i] option[selected=selected]') + output.should_not have_tag('select[id=person_birth_date_and_time_4i] option[selected=selected]') + output.should_not have_tag('select[id=person_birth_date_and_time_5i] option[selected=selected]') + output.should_not have_tag('select[id=person_birth_date_and_time_6i] option[selected=selected]') end end - it "should not set values in datetime_select when datetime value is nil" do - @person.birth_date_and_time = nil - output = datetime_select(:person, :birth_date_and_time, :include_blank => true, :include_seconds => true) - output.should have_tag('select[id=person_birth_date_and_time_1i]') do - without_tag('option[selected=selected]') + describe "date_select" do + it "should use param values when attribute is nil" do + params["person"] = { + "birth_date(1i)" => 2009, + "birth_date(2i)" => 2, + "birth_date(3i)" => 29, + } + @person.birth_date = nil + output = date_select(:person, :birth_date, :include_blank => true, :include_seconds => true) + output.should have_tag('select[id=person_birth_date_1i] option[selected=selected]', '2009') + output.should have_tag('select[id=person_birth_date_2i] option[selected=selected]', 'February') + output.should have_tag('select[id=person_birth_date_3i] option[selected=selected]', '29') end - output.should have_tag('select[id=person_birth_date_and_time_2i]') do - without_tag('option[selected=selected]') + + it "should override object values and use params if present" do + params["person"] = { + "birth_date(1i)" => 2009, + "birth_date(2i)" => 2, + "birth_date(3i)" => 29, + } + @person.birth_date = "2009-03-01" + output = date_select(:person, :birth_date, :include_blank => true, :include_seconds => true) + output.should have_tag('select[id=person_birth_date_1i] option[selected=selected]', '2009') + output.should have_tag('select[id=person_birth_date_2i] option[selected=selected]', 'February') + output.should have_tag('select[id=person_birth_date_3i] option[selected=selected]', '29') end - output.should have_tag('select[id=person_birth_date_and_time_3i]') do - without_tag('option[selected=selected]') + + it "should select attribute values from object if no params" do + @person.birth_date = "2009-01-02" + output = date_select(:person, :birth_date, :include_blank => true, :include_seconds => true) + output.should have_tag('select[id=person_birth_date_1i] option[selected=selected]', '2009') + output.should have_tag('select[id=person_birth_date_2i] option[selected=selected]', 'January') + output.should have_tag('select[id=person_birth_date_3i] option[selected=selected]', '2') end - output.should have_tag('select[id=person_birth_date_and_time_4i]') do - without_tag('option[selected=selected]') + + it "should select attribute values if params does not contain attribute params" do + @person.birth_date = "2009-01-02" + params["person"] = { } + output = date_select(:person, :birth_date, :include_blank => true, :include_seconds => true) + output.should have_tag('select[id=person_birth_date_1i] option[selected=selected]', '2009') + output.should have_tag('select[id=person_birth_date_2i] option[selected=selected]', 'January') + output.should have_tag('select[id=person_birth_date_3i] option[selected=selected]', '2') end - output.should have_tag('select[id=person_birth_date_and_time_5i]') do - without_tag('option[selected=selected]') - end - output.should have_tag('select[id=person_birth_date_and_time_6i]') do - without_tag('option[selected=selected]') + + it "should not select values when attribute value is nil and has no param values" do + @person.birth_date = nil + output = date_select(:person, :birth_date, :include_blank => true, :include_seconds => true) + output.should_not have_tag('select[id=person_birth_date_1i] option[selected=selected]') + output.should_not have_tag('select[id=person_birth_date_2i] option[selected=selected]') + output.should_not have_tag('select[id=person_birth_date_3i] option[selected=selected]') end end - it "should not set value in datetime_select where datetime string has empty value" do - @person.birth_date_and_time = '2000-- ::' - output = datetime_select(:person, :birth_date_and_time, :include_blank => true, :include_seconds => true) - output.should have_tag('select[id=person_birth_date_and_time_1i]') do - with_tag('option[selected=selected]') + describe "time_select" do + before :all do + Time.now = Time.mktime(2009,1,1) end - output.should have_tag('select[id=person_birth_date_and_time_2i]') do - without_tag('option[selected=selected]') + + it "should use param values when attribute is nil" do + params["person"] = { + "birth_time(1i)" => 2000, + "birth_time(2i)" => 1, + "birth_time(3i)" => 1, + "birth_time(4i)" => 12, + "birth_time(5i)" => 13, + "birth_time(6i)" => 14, + } + @person.birth_time = nil + output = time_select(:person, :birth_time, :include_blank => true, :include_seconds => true) + output.should have_tag('input[id=person_birth_time_1i][value=2000]') + output.should have_tag('input[id=person_birth_time_2i][value=1]') + output.should have_tag('input[id=person_birth_time_3i][value=1]') + output.should have_tag('select[id=person_birth_time_4i] option[selected=selected]', '12') + output.should have_tag('select[id=person_birth_time_5i] option[selected=selected]', '13') + output.should have_tag('select[id=person_birth_time_6i] option[selected=selected]', '14') end - output.should have_tag('select[id=person_birth_date_and_time_3i]') do - without_tag('option[selected=selected]') + + it "should select attribute values from object if no params" do + @person.birth_time = "13:14:15" + output = time_select(:person, :birth_time, :include_blank => true, :include_seconds => true) + output.should have_tag('input[id=person_birth_time_1i][value=2000]') + output.should have_tag('input[id=person_birth_time_2i][value=1]') + output.should have_tag('input[id=person_birth_time_3i][value=1]') + output.should have_tag('select[id=person_birth_time_4i] option[selected=selected]', '13') + output.should have_tag('select[id=person_birth_time_5i] option[selected=selected]', '14') + output.should have_tag('select[id=person_birth_time_6i] option[selected=selected]', '15') end - output.should have_tag('select[id=person_birth_date_and_time_4i]') do - without_tag('option[selected=selected]') + + it "should not select values when attribute value is nil and has no param values" do + @person.birth_time = nil + output = time_select(:person, :birth_time, :include_blank => true, :include_seconds => true) + output.should have_tag('input[id=person_birth_time_1i][value=""]') + output.should have_tag('input[id=person_birth_time_2i][value=""]') + output.should have_tag('input[id=person_birth_time_3i][value=""]') + output.should_not have_tag('select[id=person_birth_time_4i] option[selected=selected]') + output.should_not have_tag('select[id=person_birth_time_5i] option[selected=selected]') + output.should_not have_tag('select[id=person_birth_time_6i] option[selected=selected]') end - output.should have_tag('select[id=person_birth_date_and_time_5i]') do - without_tag('option[selected=selected]') - end - output.should have_tag('select[id=person_birth_date_and_time_6i]') do - without_tag('option[selected=selected]') + + after :all do + Time.now = nil end end + end