Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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)">  #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.

like image 979
Zabba Avatar asked Feb 22 '11 03:02

Zabba


4 Answers

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)

like image 146
Dylan Markow Avatar answered Oct 29 '22 13:10

Dylan Markow


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

like image 41
ctcherry Avatar answered Oct 29 '22 13:10

ctcherry


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
like image 8
viniciuscb Avatar answered Oct 29 '22 13:10

viniciuscb


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

like image 3
Ja͢ck Avatar answered Oct 29 '22 14:10

Ja͢ck