40 votes

Séparez les champs de formulaire de date et heure dans Rails

J'ai un ActiveRecord modèle Eventavec une colonne datetime starts_at. Je voudrais présenter une forme, où la date et l'heure pour starts_at sont choisis séparément (par exemple, "23-10-2010" pour la date et l' "18:00" du temps). Ces champs doivent être soutenus par la seule colonne starts_at, et les validations doivent être de préférence à l'encontre starts_at, trop.

Je peux bien sûr muck autour avec les attributs virtuels et des crochets, mais je voudrais une solution plus élégante. J'ai expérimenté avec les deux composed_of (rdoc), et l'attribut-décorateur (phare de discussion, github) sans succès.

Ci-dessous est une ébauche de ce que je voudrais..

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

Toute aide appréciée.

39voto

Frost Points 4169

Avez-vous d'avoir un text_field dans la vue?

Aussi loin que je peux dire, vous pouvez avoir un date_time champ puis il suffit d'utiliser deux différents champs de saisie pour définir les différentes parties du domaine.

form_for @event do |f|
  f.date_select :starts_at
  f.time_select :starts_at, :ignore_date => true
  f.submit
end

Depuis les rails de la date et de l'heure sélectionnez les aides à cinq paramètres différents (starts_at(1i) pour l'année la partie, 2i pour le mois de la partie, et ainsi de suite), ce qui signifie que l' date_select seulement des ensembles pour la date de la partie, tandis que si vous passez :ignore_date => true de la time_select, il ne réglez l'heure et les minutes de la partie.

Si vous devez avoir un text_field - je ne suis pas sûr de savoir comment le faire, mais il pourrait être possible de le faire à l'aide de certains jQuery magie avant de définir les paramètres de type dateheure avant l'envoi du formulaire.

9voto

asgeo1 Points 3336

Était à la recherche à ce sujet aujourd'hui pour un Rails de projet, et suis tombé sur ce petit bijou:

https://github.com/shekibobo/time_splitter

Réglage DateTimes peut être plus difficile ou plus laide chose, surtout par le biais d'un formulaire web. Trouver un bon DatePicker ou TimePicker est facile, mais en le faisant travailler sur les deux peut être difficile. TimeSplitter génère automatiquement des accesseurs pour la date, l'heure, l'heure et les minutes sur votre datetime ou les attributs de temps, rendant trivial à utiliser les différentes entrées d'un formulaire pour définir les différentes parties d'un champ datetime.

Regarde comme il l'aurait fait faire le travail pour vous

3voto

d_rail Points 2074

Utiliser date_select et time_select est un bon choix.

Cependant, je voulais un text_field pour la date (afin que je puisse utiliser un sélecteur de date JavaScript).

En utilisant strong_parameters ou Rails 4+:

models / event.rb

 # Add a virtual attribute
attr_accessor :start_at_date
 

views / events / _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
 

controllers / 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
  ...
 

2voto

Sergei Zinin Points 61

Une solution élégante peut fournir une gem date_time_attribute :

 class MyModel < ActiveRecord::Base
  include DateTimeAttribute

  date_time_attribute :starts_at
end
 

Cela vous permettra de définir séparément starts_at_date et 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
 

Cela vous permettra également de jouer avec les fuseaux horaires, d'utiliser Chronic, etc.

0voto

Chris Barretto Points 3934

Est-ce à cause d'un problème de conception? C'est vraiment beaucoup plus facile si vous enregistrez simplement starts_at en tant que type de données datetime et utilisez quelque chose comme:

http://puna.net.nz/timepicker.htm#

Il s’agit simplement des champs de date que vous avez pour votre modèle.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X