将 daterange 参数解析为两个属性 - Rails 4、Datetimepicker GEM

Parsing daterange param as two attributes - Rails 4, Datetimepicker GEM

我有一个模型 Foo,它有两个 datetime 属性,分别称为 start_timeend_timeFoo 每个属性都有验证逻辑:

型号:

...
validate :dates_logic_validation, on: :save
...
  def dates_logic_validation
    if start_time < Time.now
      errors.add(:start_time, 'Start time must be greater or equal to today\'\s date')
      return false
    elsif start_time > end_time
      errors.add(:end_time, 'End time must be greater than start time')
      return false
    else
      true
    end
  end

当我尝试通过控制台创建/更新 Foo 时,验证错误处理工作正常。使用 datetimepicker gem,我在参数散列中获取了两个日期。在我的 foos#create 中,我希望能够解析此 daterange 参数并将其分配给 foo.start_timefoo.end_time。为此,我添加了一个实例方法:

  def parse_date_range(daterange) #<= param is passed as "12/02/2015 - 01/14/2016"
    start_time = daterange.split("-")[0].strip!
    end_time = daterange.split("-")[1].strip!
    update_attributes(start_time: start_time, end_time: end_time)
  end

然后这样调用它:

控制器(#create):

  def create
    @foo= Foo.new(foo_params)
    @foo.parse_date_range(params[:daterange])
    if @foo.valid?
      @foo.save
      redirect_to foos_path(@foo)
    else
      render :new
    end
  end

这里是音乐停止的地方。如果我在 @foo 上调用 parse_data_range 之后记录 #{start_time}#{end_time},两者都将为空。这表明我可能无法在不存在的对象上调用 update_attributes。如果是这样,最好的解决方案是什么?

这应该开始工作了。

update_attributes(start_time: Date.parse(start_time), end_time: Date.parse(end_time))

您也可以使用

DateTime.parse("12/02/2015")
=> Thu, 12 Feb 2015 00:00:00 +0000 

我认为进行第二次数据库查询 (update_attributes) 是错误的,相反您可以在控制器中从 params 中提取日期,如下所示:

class FoosController < ApplicationController
  before_action :extract_start_end_times, only: :create

  def create
    @foo = Foo.new(foo_params)

    if @foo.valid?
      @foo.save
      redirect_to foos_path(@foo)
    else
      render :new
    end
  end

  # ...

  private
  def extract_start_end_times
    return unless params[:daterange].present?
    daterange = params.delete(:daterange)

    start_time, end_time = daterange.split(/\s*-\s*/)
                             .map {|date| Date.strptime(date, '%m/%d/%Y') }

    params.merge!(start_time: start_time, end_time: end_time)
  end
end

注意 Date.strptime(date, '%m/%d/%Y') 的用法。这是必要的,因为您的日期格式不明确(Ruby 无法知道“12/02/2015”是 12 月 2 日还是 2 月 12 日)。

如果您使用强参数,您可能需要修改 foo_params 方法以适应 start_timeend_time 参数。