Where is the Rails method that converts data from `datetime_select` into a DateTime object?
When I use <%= f.datetime_select :somedate %>
in a form, it generates HTML like:
<select id="some_date_1i" name="somedate1(1i开发者_Go百科)"> #year
<select id="some_date_2i" name="somedate1(2i)"> #month
<select id="some_date_3i" name="somedate1(3i)"> #day
<select id="some_date_4i" name="somedate1(4i)"> #hour
<select id="some_date_5i" name="somedate1(5i)"> #minute
When that form is submitted, the somedate1(<n>i)
values are received:
{"date1(1i)"=>"2011", "date1(2i)"=>"2", "date1(3i)"=>"21", "date1(4i)"=>"19", "date1(5i)"=>"25"}
How can I convert that into a DateTime object?
I could write my own method to do this, but since Rails already is able to do the conversion, I was wondering if I could call that Rails method to do it for me?
I don't know where to look for that method.
I'm ultimately trying to solve "How to handle date/times in POST parameters?" and this question is the first step in trying to find a solution to that other problem.
This conversion happens within ActiveRecord when you save your model.
You could work around it with something like this:
somedate = DateTime.new(params["date1(1i)"].to_i,
params["date1(2i)"].to_i,
params["date1(3i)"].to_i,
params["date1(4i)"].to_i,
params["date1(5i)"].to_i)
DateTime::new
is an alias of DateTime::civil
(ruby-doc)
The start of that code path, seems to be right about here:
https://github.com/rails/rails/blob/d90b4e2/activerecord/lib/active_record/base.rb#L1811
That was tricky to find! I hope this helps you find what you need
Hi I have added the following on the ApplicationController, and it does this conversion.
#extract a datetime object from params, useful for receiving datetime_select attributes
#out of any activemodel
def parse_datetime_params params, label, utc_or_local = :local
begin
year = params[(label.to_s + '(1i)').to_sym].to_i
month = params[(label.to_s + '(2i)').to_sym].to_i
mday = params[(label.to_s + '(3i)').to_sym].to_i
hour = (params[(label.to_s + '(4i)').to_sym] || 0).to_i
minute = (params[(label.to_s + '(5i)').to_sym] || 0).to_i
second = (params[(label.to_s + '(6i)').to_sym] || 0).to_i
return DateTime.civil_from_format(utc_or_local,year,month,mday,hour,minute,second)
rescue => e
return nil
end
end
Had to do something very similar, and ended up using this method:
def time_value(hash, field)
Time.zone.local(*(1..5).map { |i| hash["#{field}(#{i}i)"] })
end
time = time_value(params, 'start_time')
See also: TimeZone.local
Someone else here offered solution of using DateTime.new, but that won't work in Postgresql. That will save the record as is, that is, as it was inserted in form, and thus it won't save in database as utc time, if you are using "timestamp without timezone". I spent hours trying to figure out this one, and the solution was to use Time.new rather than DateTime.new:
datetime = Time.new(params["fuel_date(1i)"].to_i, params["fuel_date(2i)"].to_i,
params["fuel_date(3i)"].to_i, params["fuel_date(4i)"].to_i,
params["fuel_date(5i)"].to_i)
I had this issue with Rails 4. It turned out I forgot to add the permitted params to my controller:
def event_params
params.require(:event).permit(....., :start_time, :end_time,...)
end
This is the method I use - it returns the deleted keys as a new hash.
class Hash
def delete_by_keys(*keys)
keys.each_with_object({}) { |k, h| h[k] = delete(k) if include? k }
end
end
精彩评论