Отдельные поля даты и времени в Rails
У меня есть модель ActiveRecord Event
с столбцом datetime starts_at
. Я хотел бы представить форму, в которой дата и время для starts_at
выбираются отдельно (например, "23-10-2010"
для даты и "18:00"
для времени). Эти поля должны поддерживаться одним столбцом starts_at
, а проверки должны быть предпочтительно также против starts_at
.
Я могу, конечно, обманывать виртуальными атрибутами и крючками, но мне хотелось бы более элегантное решение. Я экспериментировал как с composed_of
(rdoc), так и с атрибутом-декоратором (обсуждение маяка, github) без успеха.
Ниже приведен пример того, что мне хотелось бы.
class Event < ActiveRecord::Base
validates_presence_of :start_date
end
# View
# On submission this should set start_date.
form_for @event do |f|
f.text_field :starts_at_date # date-part of start_date
f.text_field :starts_at_time_of_day # time-of-day-part of start_date
f.submit
end
Любая помощь была оценена.
Ответы
Ответ 1
Рассматривал это сегодня для проекта Rails и наткнулся на этот камень:
https://github.com/shekibobo/time_splitter
Установка DateTimes может быть сложной или уродливой, особенно через веб-форму. Найти хорошего DatePicker или TimePicker легко, но заставить их работать на обоих может быть сложно. TimeSplitter автоматически генерирует аксессуар для даты, времени, часа и минут в атрибутах времени и времени, что делает тривиальным использование разных входных форм для установки разных частей поля datetime.
Похоже, это сработает для вас.
Ответ 2
Вам нужно иметь text_field
в представлении?
Насколько я могу судить, вы можете иметь поле date_time
, а затем просто использовать два разных поля ввода для установки разных частей поля.
form_for @event do |f|
f.date_select :starts_at
f.time_select :starts_at, :ignore_date => true
f.submit
end
Так как помощники по дате и времени рельсов устанавливают пять разных параметров (starts_at(1i)
для части года, 2i
для части месяца и т.д.), это означает, что date_select
устанавливает их только для даты часть, а если вы пройдете :ignore_date => true
до time_select
, она установит только час и минуту.
Если у вас должен быть text_field
, я не уверен, как это сделать, но может быть возможно использовать некоторую магию jQuery перед настройкой параметров datetime перед отправкой формы.
Ответ 3
Использование date_select
и time_select
- хороший способ.
Однако мне нужна была text_field
для даты (так что я могу использовать подборку дат для JavaScript).
Использование сильных_параметров или Rails 4 +:
модели/event.rb
# Add a virtual attribute
attr_accessor :start_at_date
просмотров/События/_form.html.haml
- # A text field for the date, and time_select for time
= f.label :start_at
= f.text_field :start_at_date, value: (f.object.start_at.present? ? f.object.start_at.to_date : nil)
= f.time_select :start_at, :ignore_date => true
Контроллеры/events_controller.rb
# If using a date_select, time_select, datetime_select
# Rails expects multiparameter attributes
# Convert the date to the muiltiparameter parts
def event_params
if !!params[:event] && (params[:event]["start_at(4i)"].present? || params[:event]["start_at(5i)"].present?)
if params[:event][:start_at_date].present?
start_at_date = params[:event][:start_at_date]
else
start_at_date = Date.today
end
year = start_at_date.match(/^(\d{4})[\-\/]/)[1]
month = start_at_date.match(/[\-\/](\d{2})[\-\/]/)[1]
day = start_at_date.match(/[\-\/](\d{2})$/)[1]
params[:event]["start_at(1i)"] = year
params[:event]["start_at(2i)"] = month
params[:event]["start_at(3i)"] = day
end
...
Ответ 4
Элегантное решение может обеспечить date_time_attribute gem:
class MyModel < ActiveRecord::Base
include DateTimeAttribute
date_time_attribute :starts_at
end
Это позволит вам установить starts_at_date
и starts_at_time
отдельно:
form_for @event do |f|
f.text_field :starts_at_date
f.text_field :starts_at_time
f.submit
end
# this will work too:
form_for @event do |f|
f.date_select :starts_at_date
f.time_select :starts_at_time, :ignore_date => true
f.text_field :starts_at_time_zone
f.submit
end
# or
form_for @event do |f|
f.date_select :starts_at_date
f.text_field :starts_at_time
f.submit
end
Он также позволит вам играть с часовыми поясами, использовать Chronic и т.д.
Ответ 5
Это из-за проблемы с дизайном? Это намного проще, если вы просто сохраните start_at как тип данных datetime и используйте что-то вроде:
http://puna.net.nz/timepicker.htm#
Он просто работает поверх любых полей даты, которые у вас есть для вашей модели.