好的,所以关于相关主题有很多答案,但由于某种原因,似乎没有人对以下非常真实的问题感兴趣:
我有一个Timecard
模型,其中包含to_date
和from_date
个字段。我正在使用jquery.ui.datepicker
并且一般来说 - 一切都很好。我也在使用'validates_timeliness'宝石:
class Timecard < ActiveRecord::Base
...
validates_date :to_date
validates_date :from_date
...
end
但是,如果用户决定手动编辑文本字段,输入类似'29 -Feb-2013'(这是无效日期)的内容,则此日期将转换为'01 -Mar-2013'。以下规范将失败:
describe "POST #create" do
...
context "with invalid attributes (invalid date)" do
it "re-renders the :new template" do
timecard = fix_date_attribs_for(:timecard_feb)
# Manually create an invalid date in the params hash - Feb only has 28 days
timecard['to_date(3i)'] = 29
post :create, timecard: timecard
response.should render_template :new
end
end
...
end
timecards_controller.rb 中的以下puts
:
def create
@timecard = Timecard.new(timecard_params)
puts ">>>> #{@timecard.valid?} - #{@timecard.to_yaml}"
...
end
运行上述规范时产生以下输出:
.>>>> true - --- !ruby/object:Timecard
attributes:
id:
name: February 2013
from_date: 2013-02-01
to_date: 2013-03-01
created_at:
updated_at:
F
Failures:
1) TimecardsController POST #create with invalid attributes (invalid date) re-renders the :new template
Failure/Error: response.should render_template :new
expecting <"new"> but rendering with <[]>
# ./spec/controllers/timecards_controller_spec.rb:65:in `block (4 levels) in <top (required)>'
Finished in 0.28495 seconds
17 examples, 1 failure
我如何在此处进行输入验证?在模型中使用回调似乎太过分了(因为问题发生在之前 - 当控制器执行@timecard = Timecard.new(timecard_params)
时)。我可以尝试在控制器中捕获Date.new(relevant_timecard_params)
异常,但它无法访问errors
哈希,因此我无法告诉用户它是无效日期,更不用说了控制器听起来不是正确的输入验证地点...请帮忙...
有'validate_timeliness',因为@Grantovich建议如下(启用插件),save
和update
失败,无效日期如'29 -Feb-2013',即使没有写{{1}在模型中。添加validates_date :to_date
时,validates_date
和save
失败,即使在完全有效的输入上,验证字段也会设置为update
(我怀疑是验证逻辑)。
还尝试指定格式:nil
但结果相同。
答案 0 :(得分:2)
您看到的行为来自标准的Ruby时间解析器,默认情况下validates_timeliness使用。您可以通过Time.parse
:
irb(main):001:0> Time.parse('29-Feb-2013')
=> 2013-03-01 00:00:00 -0500
This section of the validates_timeliness README表示可选的timeliness
解析器“比Ruby解析器更严格,这意味着如果它不是该月的有效数字,它将不接受该月的某一天”。这看起来就像你想要的行为,所以我尝试将以下内容放在validates_timeliness.rb
初始值设定项中(或者如果你已经有了配置行,则添加配置行):
ValidatesTimeliness.setup do |config|
config.use_plugin_parser = true
end