0

看法

<%= form_for(@new_credit_entry) do |f| %>
    <%= f.date_select :created_on%>

我看到我可以指定一个无效的日期。这会产生一个 params 哈希,如下所示

"credit"=>{"created_on(1i)"=>"2013",
 "created_on(2i)"=>"2",
 "created_on(3i)"=>"31"

这当然是一个错误的日期。所以我知道我的模型需要对此进行验证——可能会使用 validates_timeliness gem。我需要知道的是如何在规范中模拟这个

这是一些rails控制台输出

irb(main):056:0> x = Credit.new(created_on: "2013-02-30")
=> #<Credit id: nil, description: nil, credit_category_id: nil, amount: nil, created_on: nil, created_at: nil, updated_at: nil>
irb(main):058:0> x.created_on_before_type_cast
=> "2013-02-30"
irb(main):060:0> x.created_on
=> nil

irb(main):057:0> y = Credit.new(created_on: "2013-03-03")
=> #<Credit id: nil, description: nil, credit_category_id: nil, amount: nil, created_on: "2013-03-03", created_at: nil, updated_at: nil>
irb(main):059:0> y.created_on_before_type_cast
=> "2013-03-03"
irb(main):061:0> y.created_on
=> Sun, 03 Mar 2013

irb(main):062:0> z = Credit.new("created_on(1i)"=>"2013",
irb(main):063:1*  "created_on(2i)"=>"2",
irb(main):064:1*  "created_on(3i)"=>"31")
=> #<Credit id: nil, description: nil, credit_category_id: nil, amount: nil, created_on: "2013-03-03", created_at: nil, updated_at: nil>
irb(main):065:0> z.created_on
=> Sun, 03 Mar 2013
irb(main):066:0> z.created_on_before_type_cast
=> Sun, 03 Mar 2013
4

1 回答 1

1

如果您使用validates_timeliness,它将拒绝您在上面尝试的无效日期。该模型将无效并且created_on将是nil. 这包括您提到的日期包装问题。

安装 validates_timeliness 后,您的模型中只需要:

validates_date :created_on

这是一个测试各种场景的规范:

describe Credit do
  it "rejects single digits" do
    credit = Credit.new created_on: "3"
    credit.should_not be_valid
    credit.created_on.should be_nil
  end

  it "rejects bad dates" do
    credit = Credit.new created_on: "2013-02-31"
    credit.should_not be_valid
    credit.created_on.should be_nil
  end

  it "rejects words" do
    credit = Credit.new created_on: "some nonsense"
    credit.should_not be_valid
    credit.created_on.should be_nil
  end

  it "accepts good dates" do
    date = "2013-02-28"
    credit = Credit.new created_on: date
    credit.should be_valid
    credit.created_on.should == Date.parse(date)
  end
end

即使没有 gem,您也可以很容易地验证这一点,但这看起来像是一个方便的 gem。不要忘记运行生成器以完成安装。

如果您确实选择推出自己的验证,您可能会遇到一些问题。

一是当您尝试将错误值粘贴到datedatetime列中时,底层数据库的行为会有所不同;有些在他们存储的值和他们所做的自动转换方面更加灵活。最好提前在 Rails 端进行验证。

更大的问题是,在运行验证时,ActiveRecord 已经尝试将值转换为与数据库字段类型匹配的类型。如果您date在数据库中有一个字段created_on,ActiveRecord 会将分配给的每个值转换created_on为一个Date对象。这最终会nil导致许多格式错误的日期。在您的验证器中,您需要查看created_on_before_type_cast原始字符串。ActiveRecord 创建一个动态的*_before_type_cast方法。您可以检查其格式并拒绝错误值。

我提到这些警告是为了鼓励您坚持使用宝石。:)

于 2013-03-17T07:58:51.620 回答