Ruby 2.2.0 on Rails 4.2.2
我正在尝试编写一个自定义日期验证器(一旦我使这部分工作,它将被扩展以处理其他一些情况),但是现在它无法对字符串进行适当的验证(并返回false) - 它甚至没有跑。当设置为字符串时,rails似乎完全忽略date_ended
值。当我尝试相同的测试,除了一个整数,它正确验证并验证失败。如果我不允许nil值,验证器会正确地阻止在字符串值上创建记录,但这只是因为它拒绝了nil值。任何和所有建议都表示赞赏。
date_started
存在同样的问题。
编辑:我已经确认第二次预期验证失败,不第一次验证是通过在第一次调查之前仔细检查CommissionMember.count是否为0期望。
CommitteeMember :
class CommitteeMember < ActiveRecord::Base
belongs_to :committee
belongs_to :member
validates :committee_id, presence: true
validates :member_id, uniqueness: { scope: :committee_id }, presence: true
validates :date_started, date: true, allow_nil: true
validates :date_ended, date: true, allow_nil: true
end
schema.rb 相关行:
create_table "committee_members", force: :cascade do |t|
t.integer "committee_id", null: false
t.integer "member_id", null: false
t.date "date_started"
t.date "date_ended"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
DateValidator (自定义验证程序):
(请注意中间的打印值)
class DateValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
puts "Validating #{value}"
unless value.kind_of?(Date)
record.errors[attribute] << "must be of type date"
end
end
end
CommiteeMember 相关规范:
(请注意中间的打印值)
it 'should fail with a string for date_ended' do
expect(CommitteeMember.count).to eq(0)
CommitteeMember.create!(member_id: 1, committee_id: 1, date_ended: "S")
ap CommitteeMember.first
expect(CommitteeMember.count).to eq(0)
end
规范输出:
$ rspec spec/models/committee_member_spec.rb
......#<CommitteeMember:0x00000007d1f888> {
:id => 1,
:committee_id => 1,
:member_id => 1,
:date_started => nil,
:date_ended => nil,
:created_at => Tue, 11 Aug 2015 19:22:51 UTC +00:00,
:updated_at => Tue, 11 Aug 2015 19:22:51 UTC +00:00
}
F
Failures:
1) CommitteeMember validations should fail with a string for date_ended
Failure/Error: expect(CommitteeMember.count).to eq(0)
expected: 0
got: 1
(compared using ==)
# ./spec/models/committee_member_spec.rb:52:in `block (3 levels) in <top (required)>'
Finished in 0.54864 seconds (files took 2.43 seconds to load)
7 examples, 1 failure
Failed examples:
rspec ./spec/models/committee_member_spec.rb:48 # CommitteeMember validations should fail with a string for date_ended
答案 0 :(得分:3)
由于属性是日期属性,因此Rails会自动解析您尝试分配的任何值。如果它无法解析为日期,则会将值保留为nil
,例如在控制台中:
c = CommitteeMember.new
c.date_started = 'S'
=> "S"
c.date_started
=> nil
实际上,Rails实际上会将字符串解析为Date:
c.date_started = '2016-1-1'
=> "2016-1-1"
c.date_started
=> Fri, 01 Jan 2016
c.date_started.class
=> Date
这意味着您根本不需要验证日期字段是否为日期,因为Rails不会以其他方式存储它们。相反,只需验证它们是否存在:
validates_presence_of :date_started, :date_ended