Rails 4 - Преобразование даты и времени в отдельные поля даты и времени

Как вы можете преобразовать поле datetime mysql в два поля формы (1) только для даты, (2) только время и объединить оба поля обратно в формат даты и времени на форме submit?

Это позволит использовать следующие драгоценные камни, но сохранить даты в одном поле datetime:

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

Спасибо заранее!

Ответ 1

Нашел решение с помощью @Althaf

Добавлены виртуальные атрибуты в model.rb. Используется before_save вызов before_save для преобразования обратно в 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

Используя Rails 4, нужно было добавить sched_date_field и sched_time_field к сильным параметрам в controller.rb

Вот поля в _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" %>

Ответ 2

Вы можете использовать date_time_attribute gem:

class MyModel < ActiveRecord::Base
  include DateTimeAttribute

  date_time_attribute :scheduled_at
end

Это позволит вам установить schedule_at_date и scheduled_at_time отдельно. После того как атрибуты будут установлены, значения будут объединены в schedule_at.

Ответ 3

Вы можете использовать виртуальные атрибуты. См. Этот Railscast и, если у вас есть профессиональная подписка, пересмотренную.

В основном в представлении вы бы следующее

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

Ваша база данных по-прежнему будет содержать поле, которое я назову full_date

Теперь в вашей модели вы должны определить 2 поля следующим образом.

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

Поскольку похоже, что вы используете Rails 4, вам нужно разрешить date_field и time_field в ваших сильных параметрах.

Ответ 4

В качестве альтернативы я установил в контроллере решение, которое выполняет все преобразования даты и времени до создания объекта, поскольку изменение данных в модели оказало влияние на все мои тесты и проверки. "Событие" - это объект, который я создаю здесь, и ему назначены значения даты и времени.

#In the controller:
def convert_to_datetime_and_assign(event, params)
  date_field = Date.parse(params[:date_field]).strftime("%Y-%m-%d")
  start_time_field = Time.parse(params[:start_time_field]).strftime("%H:%M:%S")
  end_time_field = Time.parse(params[:end_time_field]).strftime("%H:%M:%S")
  event.start_time = DateTime.parse("#{date_field} #{start_time_field}")
  event.end_time = DateTime.parse("#{date_field} #{end_time_field}")
  event
rescue ArgumentError
  event.errors.add(:start_time, :invalid, message: "Date or time was invalid")
  event
end

в методах создания и обновления контроллера я назвал метод выше:

@event = convert_to_datetime_and_assign(@event, event_params)

Я добавил поля для date_field, start_time_field и end_time_field в мои формы для создания/обновления "событий". И в модели я добавил средство доступа для доступа к этим значениям.

attr_accessor :date_field, :start_time_field, :end_time_field