如何处理非模型Rails表单中的日期字段?

时间:2014-04-01 23:14:39

标签: ruby-on-rails forms activemodel

我正在使用ActiveModel创建一个非模型对象,该对象将与Rails表单构建器一起使用。这是一个Rails 3项目。这是我到目前为止的一个例子:

class SalesReport
  include ActiveModel::Validations
  include ActiveModel::Conversion
  extend ActiveModel::Naming

  attr_accessor :promotion_code, :start_date, :end_date

  def initialize(attributes = {})
    attributes.each do |name, value|
      send("#{name}=", value)
    end
  end

  def persisted?
    false
  end
end

我碰巧使用HAML和simple_form,但这并不重要。最后,我只是使用标准的Rails日期选择字段:

= simple_form_for [:admin, @report], as: :report, url: admin_reports_path do |f|
  = f.input :promotion_code, label: 'Promo Code'
  = f.input :start_date, as: :date
  = f.input :end_date, as: :date
  = f.button :submit

Rails将日期字段拆分为单独的字段,因此在提交表单时,实际上提交了3个日期字段:

{
  "report" => {
    "start_date(1i)" => "2014",
    "start_date(2i)" => "4",
    "start_date(3i)" => "1"
  }
}

在我的SalesReport对象中,我将params分配给我的attr方法,但是我收到的错误是我没有start_date(1i)=方法,我就是显然还没有定义。最后,我想最终得到一个Date对象,我可以使用它而不是3个单独的字段。

我应该如何处理非模型对象中的这些日期字段?

1 个答案:

答案 0 :(得分:4)

在初始化过程中,您可以手动将属性值分配给类方法,然后在下面覆盖start_dateend_date setter方法。

class SalesReport
  include ActiveModel::Validations
  include ActiveModel::Conversion
  extend ActiveModel::Naming

  attr_accessor :promotion_code, :start_date, :end_date

  def initialize(attributes = {})
    @promotion_code = attributes['promotion_code']
    year = attributes['start_date(1i)']
    month = attributes['start_date(2i)']
    day = attributes['start_date(3i)']
    self.start_date = [year, month, day]
  end

  def start_date=(value)
    if value.is_a?(Array)
      @start_date = Date.new(value[0].to_i, value[1].to_i, value[2].to_i)
    else
      @start_date = value
    end
  end

  def persisted?
    false
  end
end   

这应该允许您为设置者提供具有单独日期元素的Date实例或Array,并且设置者会将正确的日期分配给@start_date。 对@end_date执行相同的操作。

希望这可以帮到你。