加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ruby-on-rails – Rails 3自定义验证和shoulda

发布时间:2020-12-17 02:16:41 所属栏目:百科 来源:网络整理
导读:这些天我在Shoulda和Rspec之间摇摆不定.我已经阅读并在RSpec上玩了很多,但与Shoulda没那么多.我发现Shoulda的一行断言更容易阅读,测试看起来更清晰.但是,当我无法弄清楚如何在Shoulda中编写特定的断言时,我会切换到RSpec.虽然不是很开心. 所以这就是我今天所
这些天我在Shoulda和Rspec之间摇摆不定.我已经阅读并在RSpec上玩了很多,但与Shoulda没那么多.我发现Shoulda的一行断言更容易阅读,测试看起来更清晰.但是,当我无法弄清楚如何在Shoulda中编写特定的断言时,我会切换到RSpec.虽然不是很开心.

所以这就是我今天所做的.我为我的模型课程写了一些自定义验证.课程有一个start_date和一个end_date.围绕它有一些规则.

> start_date和end_date都是必需的
> start_date不能晚于今天
> end_date不能在start_date之前

我知道那里有一些安静的东西可以为我做的.但是因为我是新人,我认为自己做这件事可能是个好主意,并在我去的时候学习.

所以这就是我的模型

class Course < ActiveRecord::Base
  belongs_to :category
  has_many :batches,:dependent => :destroy
  accepts_nested_attributes_for :batches,:reject_if => lambda {|a| a[:code].blank?},:allow_destroy => true
  has_and_belongs_to_many :students,:uniq => true

  validates_presence_of :name,:course_code,:total_seats
  validates_uniqueness_of :category_id,:scope => [:name,:course_code]

  validates :start_date,:presence => true,:course_start_date=>true
  validates :end_date,:course_end_date=>true
end

我的自定义验证如下

class CourseEndDateValidator < ActiveModel::EachValidator  
  def validate_each(object,attribute,value)
    if object.errors[attribute].blank? && object.errors[:start_date].blank?
      if value < object.start_date
        object.errors[attribute] << "cannot be later than start date"
      end
    end
  end
end

class CourseStartDateValidator < ActiveModel::EachValidator  
  def validate_each(object,value)
    if object.errors[attribute].blank?
      if value < DateTime.now.to_date
        object.errors[attribute] << "cannot be later than today"
      end
    end
  end
end

以下是我的course_spec

require 'spec_helper'require 'date'

describe Course do

  context  'validations' do
    it { should validate_presence_of(:name)}
    it { should validate_presence_of(:course_code)}
    it { should validate_presence_of(:start_date)}
    it { should validate_presence_of(:end_date)}
    it { should validate_presence_of(:total_seats)}

    date = DateTime.now.to_date
    it { should allow_value(date).for(:start_date) }
    it { should_not allow_value(date - 10 ).for(:start_date) }
    it {should allow_value(date + 10).for(:end_date)}
  end

  context  'associations' do
    it { should belong_to(:category)}
    it { should have_many(:batches).dependent(:destroy)}
    it { should have_and_belong_to_many(:students) }
  end

  it " end date should not be before course start date" do
    course = FactoryGirl.build(:course,:end_date=>'2011-12-10')
    course.should be_invalid
  end
end

在我使用Rspec编写最后一个“it”块之前,我在验证上下文中有类似的内容

context  'validations' do
    it { should validate_presence_of(:name)}
    it { should validate_presence_of(:course_code)}
    it { should validate_presence_of(:start_date)}
    it { should validate_presence_of(:end_date)}
    it { should validate_presence_of(:total_seats)}

    date = DateTime.now.to_date
    it { should allow_value(date).for(:start_date) }
    it { should_not allow_value(date - 10 ).for(:start_date) }
    it { should allow_value(date + 10).for(:end_date)}
    it { should_not allow_value(date - 10).for(:end_date)} # <-------------------
  end

我得到了以下失败

Failures:

  1) Course validations
     Failure/Error: it { should_not allow_value(date - 10).for(:end_date)}
       Expected errors when end_date is set to Fri,9 Dec 2011,got errors: ["name can't be blank (nil)","course_code can't be blank (nil)","total_seats can't be blank (nil)","start_date can't be blank (nil)"]

我不确定我在这里做错了什么.这是我的自定义验证代码不正确还是我需要在运行最后一个断言之前设置一些东西,以便在测试end_date时start_date不是nil?

验证在视图中正常工作.我的意思是我得到了正确的验证错误,具体取决于我输入的数据类型.但我的测试失败了.我现在已经看了一段时间,但无法弄清楚我到底做错了什么.

解决方法

我想你可以用两种方式解决这个问题:

您需要将date = DateTime.now.to_date放入before(:each)块之前.

context  'validations' do
  before(:each) { date = DateTime.now.to_date }

  it { should allow_value(date).for(:start_date) }
  it { should_not allow_value(date - 10 ).for(:start_date) }
  it { should allow_value(date + 10).for(:end_date)}
  it { should_not allow_value(date - 10).for(:end_date)}
end

或者您可以使用rails日期助手.

context  'validations' do
  it { should allow_value(Date.today).for(:start_date) }
  it { should_not allow_value(10.days.ago).for(:start_date) }
  it { should allow_value(10.days.from_now).for(:end_date)}
  it { should_not allow_value(10.days.ago).for(:end_date)}
end

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读