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

J’ai un Event modèle ActiveRecord avec une colonne de date / starts_at . Je voudrais présenter un formulaire, où la date et l’heure pour starts_at sont choisies séparément (par exemple "23-10-2010" pour la date et "18:00" pour l’heure). Ces champs doivent être sauvegardés par la colonne single starts_at , et les validations doivent être de préférence contre starts_at .

Je peux bien sûr me débrouiller avec des atsortingbuts et des crochets virtuels, mais j’aimerais une solution plus élégante. J’ai expérimenté à la fois composé_of ( rdoc ), et atsortingbut-décorateur ( discussion de phare , github ) sans succès.

Vous trouverez ci-dessous un aperçu 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.

Était en train de regarder cela aujourd’hui pour un projet Rails, et est tombé sur ce joyau:

https://github.com/shekibobo/time_splitter

La définition de DateTimes peut être difficile ou moche, en particulier via un formulaire Web. Trouver un bon DatePicker ou TimePicker est facile, mais les faire travailler sur les deux peut être difficile. TimeSplitter génère automatiquement des accesseurs pour la date, l’heure, l’heure et la minute sur vos atsortingbuts datetime ou time, ce qui rend sortingvial l’utilisation de différentes entrées de formulaire pour définir différentes parties d’un champ datetime.

On dirait que ça ferait le travail pour toi

text_field -vous avoir un text_field dans la vue?

Autant que je date_time , vous pouvez avoir un champ date_time , puis simplement utiliser deux champs de saisie différents pour définir les différentes parties du champ.

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

Puisque les helpers select de date et heure des rails définissent cinq parameters différents ( starts_at(1i) ( starts_at(1i) pour la partie année, 2i pour la partie month, etc.), cela signifie que date_select ne les définit que pour la partie date, alors que si vous réussissez :ignore_date => true au time_select , il ne définira que la partie heure et minute.

Si vous devez avoir un text_field je ne suis pas sûr de savoir comment le faire, mais il est possible de faire de la magie jQuery avant de définir les parameters datetime avant d’envoyer le formulaire.

Utiliser un date_select et time_select est une bonne façon de faire.

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 atsortingbute 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 

contrôleurs / events_controller.rb

 # If using a date_select, time_select, datetime_select # Rails expects multiparameter atsortingbutes # 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 ... 

Une solution élégante peut fournir date_time_atsortingbute gem :

 class MyModel < ActiveRecord::Base include DateTimeAttribute date_time_attribute :starts_at end 

Il vous permettra de définir 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.

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

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

Il s’exécute simplement sur les champs de date que vous avez pour votre modèle.