Rails 3 кастомная валидация и musta

Я болтаюсь между собой и Rspec в эти дни. Я читал и играл немного с RSpec, но не так уж с Ifa. Я считаю, что утверждения Оданы в одной строке легче читать, а тест выглядит чище. Но когда я не могу понять, как написать конкретное утверждение в Долже, я переключаюсь на RSpec. Не очень доволен, хотя.

Итак, вот что я сделал сегодня. Я написал несколько пользовательских проверок для моей модели Course, Курс имеет 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, :presence => true, :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, attribute, value)
    if object.errors[attribute].blank?
      if value < DateTime.now.to_date
        object.errors[attribute] << "cannot be later than today"
      end
    end
  end
end

И вот мой курс_спек

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

Теперь, прежде чем я написал последний блок "it" с использованием Rspec, у меня было что-то подобное в контексте проверки

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)"]

Я не уверен, что я делаю не так здесь. Это мой пользовательский код проверки, который не является правильным, или мне нужно что-то настроить перед тем, как запустить последнее утверждение, чтобы start_date не равнялся nil при тестировании end_date?

Проверки работают хорошо в представлении. Я имею в виду, что получаю правильные ошибки проверки в зависимости от типа вводимых данных. Но я провалился. Я уже давно смотрю на это, но не могу понять, что именно я делаю не так.

2 ответа

Я думаю, что вы можете решить это одним из двух способов:

Либо вам нужно разместить вас 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

Или вы могли бы использовать помощников даты рельсов.

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

@nickgrim уже ответил на вопрос, но я хочу добавить комментарий. Точка describe а также it это поощрять предложения, которые начинаются со слов "описать" и "это". В вашем примере у вас есть это:

it " end date should not be before course start date" do
  # ...

"это дата окончания...." не является предложением. Пожалуйста, напишите это как-то так:

it "validates that end date should be >= start date" do
Другие вопросы по тегам