web-dev-qa-db-fra.com

Comment obtenir une date à partir de date_select ou select_date dans Rails?

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.

26
at.

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].

47
joofsh

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

12
Vassilis

Voici l'autre

Date.civil(params[:event]["date(1i)"].to_i,params[:event]["date(2i)"].to_i,params[:event]["date(3i)"].to_i)
3
Dhanabal

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
2
I0Result

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})
1
Radu Cugut

J'utilise la méthode suivante, qui présente les avantages suivants:

  1. il n'a pas à nommer explicitement les clés de paramètres xxx(1i) à xxx(3i) (et pourrait donc être modifié pour capturer les heures et les minutes simplement en changeant Date en DateTime); et
  2. il extrait une date d'un ensemble de params 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.

1
Ryan Lue