En utilisant select_date
me rend un params[:my_date]
avec les attributs year
, month
et day
. Comment obtenir facilement un objet Date? J'espère quelque chose comme params[:my_date].to_date
.
Je suis heureux d'utiliser date_select
à la place également.
L'utilisation de date_select vous donne 3 paires clé/valeur distinctes pour le jour, le mois et l'année respectivement. Vous pouvez donc les passer dans Date.new
comme paramètres pour créer un nouvel objet Date.
Un exemple date_select a renvoyé des paramètres pour un modèle Event
:
"event"=>
{"name"=>"Birthday",
"date(1i)"=>"2012",
"date(2i)"=>"11",
"date(3i)"=>"28"},
Ensuite, pour créer le nouvel objet Date
:
event = params[:event]
date = Date.new event["date(1i)"].to_i, event["date(2i)"].to_i, event["date(3i)"].to_i
Vous pouvez à la place décider d'envelopper cette logique dans une méthode:
def flatten_date_array hash
%w(1 2 3).map { |e| hash["date(#{e}i)"].to_i }
end
Et puis appelez-le comme date = Date.new *flatten_date_array params[:event]
. Mais ce n'est pas une logique qui appartient vraiment à un contrôleur, vous pouvez donc décider de le déplacer ailleurs. Vous pouvez même étendre cela à la classe Date
et l'appeler comme date = Date.new_from_hash params[:event]
.
En voici un autre:
# view
<%= date_select('event', 'date') %>
# controller
date = Date.civil(*params[:event].sort.map(&:last).map(&:to_i))
Trouvé sur http://kevinlochner.com/use-Rails-dateselect-without-an-activerecord
Voici l'autre
Date.civil(params[:event]["date(1i)"].to_i,params[:event]["date(2i)"].to_i,params[:event]["date(3i)"].to_i)
En voici un autre pour Rails 5:
module Convert
extend ActiveSupport::Concern
included do
before_action :convert_date
end
protected
def convert_date
self.params = ActionController::Parameters.new(build_date(params.to_unsafe_h))
end
def build_date(params)
return params.map{|e| build_date(e)} if params.is_a? Array
return params unless params.is_a? Hash
params.reduce({}) do |hash, (key, value)|
if result = (/(.*)\(\di\)\z/).match(key)
params_name = result[1]
date_params = (1..3).map do |index|
params.delete("#{params_name}(#{index}i)").to_i
end
hash[params_name] = Date.civil(*date_params)
else
hash[key] = build_date(value)
end
hash
end
end
end
Vous devez l'inclure dans votre contrôleur ou application_controller.rb:
class ApplicationController < ActionController::Base
include Convert
end
Avec l'exemple de date_select @ joofsh, voici un "one liner" que j'utilise, en supposant que le champ de date s'appelle start_date
:
ev_params = params[:event]
date = Time.zone.local(*ev_params.select {|k,v| k.to_s.index('start_date(') == 0 }.sort.map {|p| p[1].to_i})
J'utilise la méthode suivante, qui présente les avantages suivants:
xxx(1i)
à xxx(3i)
(et pourrait donc être modifié pour capturer les heures et les minutes simplement en changeant Date
en DateTime
); etparams
même lorsque ces paramètres sont remplis avec de nombreuses autres paires clé-valeur.params
est un hachage au format { xxx(1i): '2017', xxx(2i): 12, xxx(3i): 31, ... }
; date_key
est la sous-chaîne courante xxx
des paramètres de date cible.
def date_from_params(params, date_key)
date_keys = params.keys.select { |k| k.to_s.match?(date_key.to_s) }.sort
date_array = params.values_at(*date_keys).map(&:to_i)
Date.civil(*date_array)
end
J'ai choisi de le placer comme méthode de classe de ApplicationRecord
, plutôt que comme méthode d'aide d'instance de ApplicationController
. Mon raisonnement est qu'une logique similaire existe au sein de l'instanciateur ActiveRecord (c'est-à-dire.Model.new
) pour analyser les dates passées depuis les formulaires Rails.