Permalink
Browse files

:datetime, :date and :time selects now support a :default option in f…

…avour of a deprecated :selected option (issue #152):

* if the object has a value, we should pre-select that at all times, ignoring the :default option
* if the object has no value, and :default is provided as a Date/Time then :default should be pre-selected
* if the object has no value, and :default is provided as nil then no option should be pre-selected (it will default to the first)
* if the object has no value, and :default is not provided then fallback to Time.now (or perhaps a configurable default)
* :selected invokes a deprecation warning, but is an alias of :default
* it's not a real deprecation, as the behaviour has changed with all the bugs and half-fixes
  • Loading branch information...
justinfrench committed Jan 8, 2010
1 parent 0dafaf1 commit 326b556ceb0fc6d0761a8a451507abe986e8fd9b
Showing with 198 additions and 134 deletions.
  1. +12 −8 lib/formtastic.rb
  2. +0 −101 spec/custom_macros.rb
  3. +60 −11 spec/inputs/date_input_spec.rb
  4. +70 −11 spec/inputs/datetime_input_spec.rb
  5. +56 −3 spec/inputs/time_input_spec.rb
View
@@ -944,6 +944,11 @@ def time_input(method, options)
# This is an absolute abomination, but so is the official Rails select_date().
#
def date_or_datetime_input(method, options)
+ if options.key?(:selected)
+ ::ActiveSupport::Deprecation.warn(":selected is deprecated (and may still have changed behavior) in #{options[:as]} inputs, use :default instead, see commit 09fc6b4 and issue #152 on github.com/justinfrench/formtastic")
+ options[:default] = options[:selected]
+ end
+
position = { :year => 1, :month => 2, :day => 3, :hour => 4, :minute => 5, :second => 6 }
i18n_date_order = ::I18n.t(:order, :scope => [:date])
i18n_date_order = nil unless i18n_date_order.is_a?(Array)
@@ -954,12 +959,11 @@ def date_or_datetime_input(method, options)
list_items_capture = ""
hidden_fields_capture = ""
-
- default_time = options.has_key?(:selected) ? options[:selected] : ::Time.now
-
- # Gets the datetime object. It can be a Fixnum, Date or Time, or nil.
- datetime = options[:selected] || (@object ? @object.send(method) : default_time) || default_time
+ options[:default] = ::Time.now unless options.key?(:default) # can't do an ||= because nil is an important value
+ options[:default] = @object.send(method) if @object && @object.respond_to?(method) && @object.send(method) # object trumps :default
+ datetime = options[:default]
+
html_options = options.delete(:input_html) || {}
input_ids = []
@@ -970,15 +974,15 @@ def date_or_datetime_input(method, options)
if options[:"discard_#{input}"]
break if time_inputs.include?(input)
- hidden_value = datetime.respond_to?(input) ? datetime.send(input.to_sym) : datetime
+ hidden_value = options[:default].respond_to?(input.to_sym) ? options[:default].send(input.to_sym) : options[:default]
hidden_fields_capture << template.hidden_field_tag("#{@object_name}[#{field_name}]", (hidden_value || 1), :id => input_id)
else
- opts = strip_formtastic_options(options).merge(:prefix => @object_name, :field_name => field_name, :default => datetime)
+ opts = strip_formtastic_options(options).merge(:prefix => @object_name, :field_name => field_name, :default => options[:default])
item_label_text = ::I18n.t(input.to_s, :default => input.to_s.humanize, :scope => [:datetime, :prompts])
list_items_capture << template.content_tag(:li,
template.content_tag(:label, item_label_text, :for => input_id) <<
- template.send(:"select_#{input}", datetime, opts, html_options.merge(:id => input_id))
+ template.send(:"select_#{input}", options[:default], opts, html_options.merge(:id => input_id))
)
end
end
View
@@ -224,107 +224,6 @@ def it_should_call_find_on_association_class_when_no_collection_is_provided(as)
end
end
- def it_should_select_existing_datetime_else_current(*datetime_parts)
- describe "default value" do
- before do
- @new_post.should_receive(:publish_at=).any_number_of_times
- end
-
- describe "when attribute value is present" do
- before do
- @output_buffer = ''
- publish_at_value = 1.year.ago + 2.month + 3.day + 4.hours + 5.minutes # No comment =)
- @new_post.stub!(:publish_at).and_return(publish_at_value)
-
- semantic_form_for(@new_post) do |builder|
- concat(builder.input(:publish_at, :as => :datetime))
- end
- end
-
- it "should select the present value by default" do
- # puts output_buffer
- output_buffer.should have_tag("form li select#post_publish_at_1i option[@selected='selected'][@value='#{@new_post.publish_at.year}']") if datetime_parts.include?(:year)
- output_buffer.should have_tag("form li select#post_publish_at_2i option[@selected='selected'][@value='#{@new_post.publish_at.month}']") if datetime_parts.include?(:month)
- output_buffer.should have_tag("form li select#post_publish_at_3i option[@selected='selected'][@value='#{@new_post.publish_at.day}']") if datetime_parts.include?(:day)
- output_buffer.should have_tag("form li select#post_publish_at_4i option[@selected='selected'][@value='#{@new_post.publish_at.strftime("%H")}']") if datetime_parts.include?(:hour)
- output_buffer.should have_tag("form li select#post_publish_at_5i option[@selected='selected'][@value='#{@new_post.publish_at.strftime("%M")}']") if datetime_parts.include?(:minute)
- #output_buffer.should have_tag("form li select#post_publish_at_6i option[@selected='selected'][@value='#{@new_post.publish_at.sec}']") if datetime_parts.include?(:second)
- end
- end
-
- describe "when no attribute value is present" do
- before do
- @output_buffer = ''
- @new_post.stub!(:publish_at).and_return(nil)
- @current_time = ::Time.now
-
- semantic_form_for(@new_post) do |builder|
- concat(builder.input(:publish_at, :as => :datetime))
- end
- end
-
- it "should select the current day/time by default" do
- # puts output_buffer
- output_buffer.should have_tag("form li select#post_publish_at_1i option[@selected='selected'][@value='#{@current_time.year}']") if datetime_parts.include?(:year)
- output_buffer.should have_tag("form li select#post_publish_at_2i option[@selected='selected'][@value='#{@current_time.month}']") if datetime_parts.include?(:month)
- output_buffer.should have_tag("form li select#post_publish_at_3i option[@selected='selected'][@value='#{@current_time.day}']") if datetime_parts.include?(:day)
- output_buffer.should have_tag("form li select#post_publish_at_4i option[@selected='selected'][@value='#{@current_time.strftime("%H")}']") if datetime_parts.include?(:hour)
- output_buffer.should have_tag("form li select#post_publish_at_5i option[@selected='selected'][@value='#{@current_time.strftime("%M")}']") if datetime_parts.include?(:minute)
- #output_buffer.should have_tag("form li select#post_publish_at_6i option[@selected='selected'][@value='#{@custom_default_time.sec}']") if datetime_parts.include?(:second)
- end
-
- # TODO: Scenario when current time is not a possible choice (because of specified date/time ranges)?
- end
- end
- end
-
- def it_should_select_explicit_default_value_if_set(*datetime_parts)
- describe 'when :selected is set' do
- before do
- @output_buffer = ''
- end
-
- # Note: Not possible to override default selected value for time_zone input
- # without overriding Rails core helper. This Rails helper works "a bit different". =/
- #
- describe "no selected items" do
- before do
- @default_time = 2.days.ago
- @new_post.stub!(:publish_at).and_return(@default_time)
-
- semantic_form_for(@new_post) do |builder|
- concat(builder.input(:publish_at, :as => :time_zone, :selected => nil))
- end
- end
-
- it 'should not have any selected item(s)' do
- output_buffer.should_not have_tag("form li select#post_publish_at_1i option[@selected='selected']")
- end
- end
-
- describe "single selected item" do
- before do
- @custom_default_time = 5.days.ago
- @new_post.stub!(:publish_at).and_return(2.days.ago)
-
- semantic_form_for(@new_post) do |builder|
- concat(builder.input(:publish_at, :as => :datetime, :selected => @custom_default_time))
- end
- end
-
- it "should select the specified value" do
- output_buffer.should have_tag("form li select#post_publish_at_1i option[@selected='selected'][@value='#{@custom_default_time.year}']") if datetime_parts.include?(:year)
- output_buffer.should have_tag("form li select#post_publish_at_2i option[@selected='selected'][@value='#{@custom_default_time.month}']") if datetime_parts.include?(:month)
- output_buffer.should have_tag("form li select#post_publish_at_3i option[@selected='selected'][@value='#{@custom_default_time.day}']") if datetime_parts.include?(:day)
- output_buffer.should have_tag("form li select#post_publish_at_4i option[@selected='selected'][@value='#{@custom_default_time.strftime("%H")}']") if datetime_parts.include?(:hour)
- output_buffer.should have_tag("form li select#post_publish_at_5i option[@selected='selected'][@value='#{@custom_default_time.strftime("%M")}']") if datetime_parts.include?(:minute)
- #output_buffer.should have_tag("form li select#post_publish_at_6i option[@selected='selected'][@value='#{@custom_default_time.sec}']") if datetime_parts.include?(:second)
- end
- end
-
- end
- end
-
def it_should_use_the_collection_when_provided(as, countable)
describe 'when the :collection option is provided' do
@@ -38,23 +38,72 @@
it 'should have three selects for year, month and day' do
output_buffer.should have_tag('form li.date fieldset ol li select', :count => 3)
end
-
- it_should_select_existing_datetime_else_current(:year, :month, :day)
- it_should_select_explicit_default_value_if_set(:year, :month, :day)
-
- describe "when :selected is nil" do
- before(:each) do
- output_buffer.replace ''
- semantic_form_for(:project, :url => 'http://test.host') do |builder|
- concat(builder.input(:publish_at, :as => :datetime, :selected => nil))
+ describe ':default option' do
+
+ describe "when the object has a value" do
+ it "should select the object value (ignoring :default)" do
+ output_buffer.replace ''
+ @new_post.stub!(:created_at => Time.mktime(2012))
+ semantic_form_for(@new_post) do |builder|
+ concat(builder.input(:created_at, :as => :date, :default => Time.mktime(1999)))
+ end
+ output_buffer.should have_tag("form li ol li select#post_created_at_1i option[@selected]", :count => 1)
+ output_buffer.should have_tag("form li ol li select#post_created_at_1i option[@value='2012'][@selected]", :count => 1)
end
end
- it "should not pre-select any options" do
- output_buffer.should_not have_tag("form li.datetime li select option[@selected]")
+ describe 'when the object has no value' do
+ it "should select the :default if provided as a Date" do
+ output_buffer.replace ''
+ @new_post.stub!(:created_at => nil)
+ semantic_form_for(@new_post) do |builder|
+ concat(builder.input(:created_at, :as => :date, :default => Date.new(1999)))
+ end
+ output_buffer.should have_tag("form li ol li select#post_created_at_1i option[@selected]", :count => 1)
+ output_buffer.should have_tag("form li ol li select#post_created_at_1i option[@value='1999'][@selected]", :count => 1)
+ end
+
+ it "should select the :default if provided as a Time" do
+ output_buffer.replace ''
+ @new_post.stub!(:created_at => nil)
+ semantic_form_for(@new_post) do |builder|
+ concat(builder.input(:created_at, :as => :date, :default => Time.mktime(1999)))
+ end
+ output_buffer.should have_tag("form li ol li select#post_created_at_1i option[@selected]", :count => 1)
+ output_buffer.should have_tag("form li ol li select#post_created_at_1i option[@value='1999'][@selected]", :count => 1)
+ end
+
+ it "should not select an option if the :default is provided as nil" do
+ output_buffer.replace ''
+ @new_post.stub!(:created_at => nil)
+ semantic_form_for(@new_post) do |builder|
+ concat(builder.input(:created_at, :as => :date, :default => nil))
+ end
+ output_buffer.should_not have_tag("form li ol li select#post_created_at_1i option[@selected]")
+ end
+
+ it "should select Time.now if a :default is not provided" do
+ output_buffer.replace ''
+ @new_post.stub!(:created_at => nil)
+ semantic_form_for(@new_post) do |builder|
+ concat(builder.input(:created_at, :as => :date))
+ end
+ output_buffer.should have_tag("form li ol li select#post_created_at_1i option[@selected]", :count => 1)
+ output_buffer.should have_tag("form li ol li select#post_created_at_1i option[@value='#{Time.now.year}'][@selected]", :count => 1)
+
+ end
end
end
+ it 'should warn about :selected deprecation' do
+ with_deprecation_silenced do
+ ::ActiveSupport::Deprecation.should_receive(:warn)
+ semantic_form_for(@new_post) do |builder|
+ concat(builder.input(:created_at, :as => :date, :selected => Date.new(1999)))
+ end
+ end
+ end
+
end
@@ -59,9 +59,6 @@
end
end
- it_should_select_existing_datetime_else_current(:year, :month, :day, :hour, :minute, :second)
- it_should_select_explicit_default_value_if_set(:year, :month, :day, :hour, :minute, :second)
-
describe 'when :discard_input => true is set' do
it 'should use default attribute value when it is not nil' do
@new_post.stub!(:publish_at).and_return(Date.new(2007,12,27))
@@ -150,20 +147,82 @@
output_buffer.should have_tag('form li.datetime fieldset ol li select', :count => 5)
end
end
-
- describe "when :selected is nil" do
+
+ describe ':default option' do
- before(:each) do
- output_buffer.replace ''
- semantic_form_for(:project, :url => 'http://test.host') do |builder|
- concat(builder.input(:publish_at, :as => :datetime, :selected => nil))
+ describe "when the object has a value" do
+ it "should select the object value (ignoring :default)" do
+ output_buffer.replace ''
+ @new_post.stub!(:created_at => Time.mktime(2012))
+ semantic_form_for(@new_post) do |builder|
+ concat(builder.input(:created_at, :as => :datetime, :default => Time.mktime(1999)))
+ end
+ output_buffer.should have_tag("form li ol li select#post_created_at_1i option[@selected]", :count => 1)
+ output_buffer.should have_tag("form li ol li select#post_created_at_1i option[@value='2012'][@selected]", :count => 1)
end
end
- it "should not pre-select any options" do
- output_buffer.should_not have_tag("form li.datetime li select option[@selected]")
+ describe 'when the object has no value' do
+ it "should select the :default if provided as a Date" do
+ output_buffer.replace ''
+ @new_post.stub!(:created_at => nil)
+ semantic_form_for(@new_post) do |builder|
+ concat(builder.input(:created_at, :as => :datetime, :default => Date.new(1999)))
+ end
+ output_buffer.should have_tag("form li ol li select#post_created_at_1i option[@selected]", :count => 1)
+ output_buffer.should have_tag("form li ol li select#post_created_at_1i option[@value='1999'][@selected]", :count => 1)
+ end
+
+ it "should select the :default if provided as a Time" do
+ output_buffer.replace ''
+ @new_post.stub!(:created_at => nil)
+ semantic_form_for(@new_post) do |builder|
+ concat(builder.input(:created_at, :as => :datetime, :default => Time.mktime(1999)))
+ end
+ output_buffer.should have_tag("form li ol li select#post_created_at_1i option[@selected]", :count => 1)
+ output_buffer.should have_tag("form li ol li select#post_created_at_1i option[@value='1999'][@selected]", :count => 1)
+ end
+
+ it "should not select an option if the :default is provided as nil" do
+ output_buffer.replace ''
+ @new_post.stub!(:created_at => nil)
+ semantic_form_for(@new_post) do |builder|
+ concat(builder.input(:created_at, :as => :datetime, :default => nil))
+ end
+ output_buffer.should_not have_tag("form li ol li select#post_created_at_1i option[@selected]")
+ end
+
+ it "should select Time.now if a :default is not provided" do
+ output_buffer.replace ''
+ @new_post.stub!(:created_at => nil)
+ semantic_form_for(@new_post) do |builder|
+ concat(builder.input(:created_at, :as => :datetime))
+ end
+ output_buffer.should have_tag("form li ol li select#post_created_at_1i option[@selected]", :count => 1)
+ output_buffer.should have_tag("form li ol li select#post_created_at_1i option[@value='#{Time.now.year}'][@selected]", :count => 1)
+
+ end
+ end
+
+ it 'should warn about :selected deprecation' do
+ with_deprecation_silenced do
+ ::ActiveSupport::Deprecation.should_receive(:warn)
+ semantic_form_for(@new_post) do |builder|
+ concat(builder.input(:created_at, :as => :date, :selected => Time.mktime(1999)))
+ end
+ end
end
end
+
+ it 'should warn about :selected deprecation' do
+ with_deprecation_silenced do
+ ::ActiveSupport::Deprecation.should_receive(:warn)
+ semantic_form_for(@new_post) do |builder|
+ concat(builder.input(:created_at, :as => :datetime, :selected => Time.mktime(1999)))
+ end
+ end
+ end
+
end
Oops, something went wrong.

0 comments on commit 326b556

Please sign in to comment.