Подтвердить что ты не робот

Отдельные поля даты и времени в 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

Любая помощь была оценена.

4b9b3361

Ответ 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#

Он просто работает поверх любых полей даты, которые у вас есть для вашей модели.