2013-10-16 70 views
3

我有簡單的模型:早該和before_回調

class Category < ActiveRecord::Base 
    belongs_to :board 
    validates :name, presence: true, uniqueness: {scope: :board_id} 
    validates :board, presence: true 
    validates :display_order, presence: true, uniqueness: {scope: :board_id} 

    before_save :set_display_order 

    private 

    def set_display_order 
    last = self.board.categories.order("display_order DESC").last 
    self.display_order = last.display_order + 100 if last 
    end 
end 

當我加入這個before_save回調,這些測試將啓動失敗:

it { should validate_uniqueness_of(:display_order).scoped_to(:board_id) } 
    it { should validate_uniqueness_of(:name).scoped_to(:board_id) } 

有了錯誤(這一點,如果在私有方法行last = ...):

NoMethodError: 
    undefined method `categories' for nil:NilClass 

其他早該測試工作的優良:

it { should validate_presence_of(:name) } 
    it { should validate_presence_of(:board) } 
    it { should belong_to :board } 

任何想法這裏有什麼問題嗎?我試圖將before_save更改爲before_validation,但仍然相同。

回答

2

因爲應該在數據庫中創建記錄。寶石創建記錄跳過驗證

http://rubydoc.info/github/thoughtbot/shoulda-matchers/master/Shoulda/Matchers/ActiveModel#validate_uniqueness_of-instance_method Ensures that the model is invalid if the given attribute is not unique. It uses the first existing record or creates a new one if no record exists in the database. It simply uses ':validate => false' to get around validations, so it will probably fail if there are 'NOT NULL' constraints. In that case, you must create a record before calling 'validate_uniqueness_of'.

在你的情況下創建category爲空,這意味着category.board # => nil,你從零調用方法categories

你應該自己創建一個記錄來進行唯一性測試。

0

shoulda_matchers和AR回調的這種限制的一種方法是重新定義適配器使用的測試主題。

例如:

# category_spec.rb 

# assuming you're using factorygirl and have this setup correctly 
let(:board) { FactoryGirl.create(:board, :with_many_categories) } 
subject { FactoryGirl.build(:category, board: board) } 

# your shoulda matcher validations here