Reputation: 9415
Is there a way to have a text_field just for the date part of a datetime attribute? For example, I have a datetime parameter called published_on, and I'd like my text_field to only submit for the date of the datetime field (not the time). This didn't work:
<%= f.text_field :published_on, :value=> (@step.published_on.strftime("%m/%d/%Y")), :ignore_time=>true %>
and submits the parameter published_on rather than published_on(1i), published_on(2i), and published_on(3i) (for the year, hour, and minute).
Edit
I'm able to get the parameters now, but I have a time zone error
This is my controller code:
date = params[:step][:published_on]
logger.debug "date: #{date}"
time = params[:step][:"published_on(4i)"] +":" + params[:step][:"published_on(5i)"]
logger.debug "time: #{time}"
dateTime = date+ " " + time
logger.debug "dateTime: #{dateTime}"
dateTime = DateTime.strptime(dateTime, '%m/%d/%Y %H:%M')
logger.debug "datetime: #{dateTime}"
params[:step][:published_on] = dateTime
params[:step].delete :"published_on(4i)"
params[:step].delete :'published_on(5i)'
which prints the following log statements:
date: 01/01/2013
time: 00:00
dateTime: 01/01/2013 00:00
datetime: 2013-01-01T00:00:00+00:00
It seems like the time is incorrect since the timezone is set to the default (00:00). Is there any way to get the timezone passed from the form?
Upvotes: 1
Views: 3229
Reputation: 9415
I finally figured it out thanks to a lot of Tilo's help.
This is what I have for my form:
<%= semantic_form_for [@project, @step], :html => {:multipart => true} do |f| %>
<%= f.inputs do%>
<%= f.text_field :published_on, :value=> (@step.published_on.strftime("%m/%d/%Y")), :ignore_time=>true %> at <%= f.time_select :published_on, :class=>"btn dropdown-toggle", :ampm=> true, :ignore_date=>true %>
<%= f.input :timeZone, :as=> :hidden, :value=> @step.published_on.zone%>
<% end %>
<% end %>
and my controller:
def update
@step = @project.steps.find_by_position(params[:id])
@step.images.each do |image|
image.update_attributes(:saved => true)
end
date = params[:step][:published_on]
logger.debug "date: #{date}"
time = params[:step][:"published_on(4i)"] +":" + params[:step][:"published_on(5i)"]
logger.debug "time: #{time}"
timeZone = params[:step][:timeZone]
logger.debug "timeZone: #{timeZone}"
dateTime = date+ " " + time +" " + timeZone
logger.debug "dateTime: #{dateTime}"
dateTime = DateTime.strptime(dateTime, '%m/%d/%Y %H:%M %Z')
logger.debug "datetime: #{dateTime}"
params[:step][:published_on] = dateTime
params[:step].delete :"published_on(4i)"
params[:step].delete :'published_on(5i)'
params[:step].delete :timeZone
respond_to do |format|
if @step.update_attributes(params[:step])
format.html { redirect_to project_steps_path(@project), :notice => 'Step was successfully updated.' }
format.json { head :no_content }
else
format.html { render :action => "edit" }
format.json { render :json => @step.errors, :status => :unprocessable_entity }
end
end
end
It seems sketchy to define a bunch of parameters for the same object and delete them later, but I didn't know any other way around it.
Upvotes: 0
Reputation: 34657
Do you have to have a text_field in the view?
As far as I can tell, you can have a date_time field and then just use two different input fields to set the different parts of the field.
form_for @event do |f|
f.date_select :starts_at
f.time_select :starts_at, :ignore_date => true
f.submit
end
Since the rails date and time select helpers set five different parameters (starts_at(1i) for the year part, 2i for the month part, and so on), that means that the date_select only sets them for the date part, while if you pass :ignore_date => true to the time_select, it will only set the hour and minute part.
If you must have a text_field I'm not sure how to do it, but it might be possible to do using some jQuery magic before setting the datetime parameters before sending the form.
Upvotes: 0
Reputation: 33732
In your form, use the text_field without the :value option.
In your controller, try:
@your_model.published_on = DateTime.parse( params[:published_on] )
This will set the date, and leave the time-portion as 00:00 midnight
Upvotes: 1