Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 4 - Convert datetime into separate date and time fields

How can you convert a mysql datetime field into two form fields (1) date only, (2) time only, and combine both fields back into datetime format on form submit?

This would allow the use of the following gems, but store the dates in a single datetime field:

gem 'bootstrap-datepicker-rails'
gem 'bootstrap-timepicker-rails'

Thanks in advance!

like image 850
Nicholas.V Avatar asked Aug 27 '13 09:08

Nicholas.V


3 Answers

Found the solution with help from @Althaf

Added virtual attributes to model.rb Used before_save callback to convert back to datetime.

before_save :convert_to_datetime

def sched_date_field
  sched_date.strftime("%d/%m/%Y") if sched_date.present?
end 

def sched_time_field
  sched_time.strftime("%I:%M%p") if sched_time.present?
end

def sched_date_field=(date)
  # Change back to datetime friendly format
  @sched_date_field = Date.parse(date).strftime("%Y-%m-%d")
end

def sched_time_field=(time)
  # Change back to datetime friendly format
  @sched_time_field = Time.parse(time).strftime("%H:%M:%S")
end

def convert_to_datetime
  self.sched_time = DateTime.parse("#{@sched_date_field} #{@sched_time_field}")
end

Using Rails 4, needed to add sched_date_field and sched_time_field to strong params in controller.rb

Here are the fields in _form.html.erb

<%= f.label :sched_date_field, "Scheduled Date" %>
<%= f.text_field :sched_date_field, :class => "datepicker" %>

<%= f.label :sched_time_field, "Scheduled Time" %>
<%= f.text_field :sched_time_field, :class => "timepicker" %>
like image 146
Nicholas.V Avatar answered Nov 04 '22 03:11

Nicholas.V


You can use date_time_attribute gem:

class MyModel < ActiveRecord::Base
  include DateTimeAttribute

  date_time_attribute :scheduled_at
end

It will allow you to set schedule_at_date and scheduled_at_time separately. Once attributes are set, values will be combined into schedule_at.

like image 6
Sergei Zinin Avatar answered Nov 04 '22 04:11

Sergei Zinin


You could use virtual attributes See this Railscast and if you have a pro subscription the revised one.

Basically in the view you would the following

<%= f.label :date_field %>
<%= f.text :date_field %>
<%= f.label :time_field %>
<%= f.text :time_field %>

Your database would still keep a field which I'll call full_date

Now in your model you would have to define the above 2 fields as follows.

def date_field  # What this returns will be what is shown in the field
  full_date.strftime("%m-%d'%y") if full_date.present?
end 

def time_field
  full_date.strftime("%I:%M%p") if full_date.present?
end

def time_field=(time)
  full_date = DateTime.parse("#{date_field} #{time_field})
end

Since it looks like you are using Rails 4, you'll have to permit date_field and time_field in your strong parameters.

like image 5
Althaf Hameez Avatar answered Nov 04 '22 05:11

Althaf Hameez