J'ai un modèle ActiveRecord Event
avec une colonne datetime starts_at
. J'aimerais présenter un formulaire dans lequel 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 unique starts_at
, et les validations doivent aussi être de préférence contre starts_at
.
Je peux bien sûr utiliser des attributs virtuels et des crochets, mais j'aimerais une solution plus élégante. J'ai expérimenté avec composed_of
( rdoc ) et attribut-decorator ( lighthouse discussion , github ) sans succès.
Voici 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 à la recherche aujourd'hui pour un projet Rails, et est tombé sur ce joyau:
https://github.com/shekibobo/time_splitter
Définir DateTimes peut être une tâche difficile ou laide, notamment via un formulaire Web. Il est facile de trouver un bon DatePicker ou TimePicker, mais il peut être difficile de les faire travailler tous les deux. TimeSplitter génère automatiquement des accesseurs pour les attributs date, heure, heure et minute de vos attributs date/heure, ce qui rend simple l'utilisation de différentes entrées de formulaire pour définir différentes parties d'un champ date/heure.
On dirait que ça ferait le travail pour vous
Devez-vous avoir un text_field
dans la vue?
Autant que je sache, vous pouvez avoir un champ date_time
puis simplement utiliser deux champs d’entrée 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
Étant donné que les assistants de sélection de date et d’heure de Rails définissent cinq paramètres différents (starts_at(1i)
pour la partie de l’année, 2i
pour la partie du mois, etc.), cela signifie que le date_select
ne les définit que pour la partie de la date. Si vous passez :ignore_date => true
à time_select
, il ne définira que les heures et les minutes.
Si vous devez avoir un text_field
, je ne sais pas comment le faire, mais il serait peut-être possible d'utiliser un peu de magie jQuery avant de définir les paramètres datetime avant d'envoyer le formulaire.
Utiliser un date_select
et un time_select
est une bonne façon de faire.
Cependant, je voulais un text_field
pour la date (afin de pouvoir 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
...
Une solution élégante peut fournir date_time_attribute gem :
class MyModel < ActiveRecord::Base
include DateTimeAttribute
date_time_attribute :starts_at
end
Cela vous permettra de définir starts_at_date
et starts_at_time
séparément:
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 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.