【问题标题】:Virtual Attribute Validation Always Fails虚拟属性验证总是失败
【发布时间】:2014-02-03 07:01:34
【问题描述】:

我将一个日期时间列(是的,我将其命名为“日期时间”......也许这太令人困惑了)分成两个虚拟属性,date_fieldtime_field

然后使用这个SO answer 我在before_save 回调中重新组合两者。

但是,无论我是否填写了date_fieldtime_field,现在验证总是 失败并显示“不能为空白”

这是我的模型:

class SomeModel < ActiveRecord::Base

  validates :date_field, :time_field, presence: true

  before_save :convert_to_datetime

  def date_field
    datetime.strftime("%d/%m/%Y") if datetime.present?
  end

  def time_field
    datetime.strftime("%I:%M%p") if datetime.present?
  end

  def date_field=(date)
    @date_field = Date.parse(date).strftime("%Y-%m-%d")
  end

  def time_field=(time)
    @time_field = Time.parse(time).strftime("%H:%M:%S")
  end

  def convert_to_datetime
    self.datetime = DateTime.parse("#{@date_field} #{@time_field}")
  end

end

编辑:

以下是调查后的一些新信息:

1) 根据 xmpolaris 的评论,我尝试了 @date_field || datetime.present? datetime.strftime("%d/%m/%Y") : nil,但返回 nil

2) 我用 before_validation 替换了 before_save,这给了我一个 500 无效日期错误。

3) 我用 byebug 检查了参数,它们看起来像这样:

(byebug) p params[:date_field]
"2014-02-10"
(byebug) p params[:time_field]
"11:30"

这是 Rails 的正确格式吗?

【问题讨论】:

  • 属性读取器 (date_field, time_field) 方法在创建新记录时始终返回 nil。这就是它失败的原因。如果它的值可用,则必须返回虚拟属性,否则尝试从 datetime 属性中读取。例如@date_field ||日期时间。现在? datetime.strftime("%d/%m/%Y") : 无
  • 您的评论对我来说很有意义......但即使在实施您的建议之后,问题仍然存在,正如我所描述的那样。

标签: ruby-on-rails ruby


【解决方案1】:

我能看到的问题是:


未设置

before_save 运行 验证(before_validation 运行 验证)

我看到您正在使用Ruby setters & writers 创建虚拟属性。但是,您的 date_fieldtime_field 设置器仅在存在 datetime 时运行

根据您的代码,datetime 仅在您在 before_save 回调中设置 datetime 属性时出现,这意味着您的 setter 将无法使用 datetime

我会试试这个:

class SomeModel < ActiveRecord::Base
    before_validation :convert_to_datetime
end

虽然可能会有所帮助,但我认为这不会完全奏效

【讨论】:

  • 感谢您的有用评论!我尝试了before_validation,但它给了我一个 500 date invalid 错误,对于有效输入和缺少输入。
【解决方案2】:

在头疼之后,事实证明我需要从这里更改我的模板......

&lt;input type="text" id="time_field" name="time_field"&gt;

到这里:

&lt;input type="text" id="time_field" name="lesson[time_field]"&gt;

一开始甚至没有设置参数。

有人知道为什么这是必要的吗?如果有可能改变这种行为?

此外,xmpolaris 在他的评论中是正确的。还需要将我的吸气剂更改为:

def date_field
  @date_field || datetime ? datetime.strftime("%d/%m/%Y") : nil
end

def time_field
  @time_field || datetime ? datetime.strftime("%d/%m/%Y") : nil
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-03-29
    • 1970-01-01
    • 2016-01-18
    • 2013-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-25
    相关资源
    最近更新 更多