Подтвердить что ты не робот

Как получить дату с date_select или select_date в Rails?

Используя select_date возвращает мне params[:my_date] с атрибутами year, month и day. Как легко получить объект Date? Я надеюсь на что-то вроде params[:my_date].to_date.

Я рад также использовать date_select.

4b9b3361

Ответ 1

Использование date_select дает вам 3 отдельных пары ключ/значение для дня, месяца и года соответственно. Поэтому вы можете передать их в Date.new в качестве параметров для создания нового объекта Date.

Пример date_select возвращенных параметров для модели Event:

"event"=>
 {"name"=>"Birthday",
  "date(1i)"=>"2012",
  "date(2i)"=>"11",
  "date(3i)"=>"28"},

Затем для создания нового объекта Date:

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

Вместо этого вы можете обернуть эту логику в методе:

def flatten_date_array hash
  %w(1 2 3).map { |e| hash["date(#{e}i)"].to_i }
end

И затем назовите его date = Date.new *flatten_date_array params[:event]. Но это не логика, которая действительно принадлежит контроллеру, поэтому вы можете переместить ее в другое место. Вы можете даже расширить его на класс Date и называть его date = Date.new_from_hash params[:event].

Ответ 3

Вот еще один

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

Ответ 4

Вот еще один для рельсов 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

Вам нужно включить его в свой контроллер или application_controller.rb:

class ApplicationController < ActionController::Base
  include Convert
end

Ответ 5

С ответом date_select @joofsh, здесь используется "один лайнер", предполагающий, что поле даты называется 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})

Ответ 6

Я использую следующий метод, который имеет следующие преимущества:

  • ему не нужно явно указывать param ключи xxx(1i) через xxx(3i) (и, таким образом, его можно было бы изменить, чтобы фиксировать час и минуту, просто изменив Date на DateTime); и
  • он извлекает дату из набора params, даже если эти параметры заполняются множеством других пар ключ-значение.

params является хешем формата { xxx(1i): '2017', xxx(2i): 12, xxx(3i): 31, ... }; date_key является общей подстрокой xxx параметров заданной даты.

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

Я решил разместить это как метод класса ApplicationRecord, а не как вспомогательный метод экземпляра ApplicationController. Мое рассуждение состоит в том, что аналогичная логика существует в экземпляре ActiveRecord (т.е. Model.new) для анализа дат, переданных из форм Rails.

Ответ 7

Или просто выполните следующее:

your_date_var = Time.parse(params[:my_date])