2011-11-22 81 views
8

在一個用戶有很多評論的簡單的mongoid數據模型中,當我寫至少1條評論時,我想授予用戶特定的徽章。所以,我建立了一個這樣的觀察者:如何使用rspec測試Mongoid :: Observer

class CommentBadgeObserver < Mongoid::Observer 
    observe :comment 

    def after_create(comment) 
    CommentBadge.check_conditions_for(comment.user) 
    end 
end 

class CommentBadge < Badge 
    def self.check_conditions_for(user) 
    if user.comments.size > 1 
     badge = CommentBadge.create(:title => "Comment badge") 
     user.award(badge) 
    end 
    end 
end 

的user.award方法:(?但我猜是因爲觀察員在後臺執行是正常的)

def award(badge) 
    self.badges << badge 
    self.save 
end 

下面的測試失敗

什麼可能是驗證此行爲的最佳方法?

回答

7

我有一個獨立的工作代碼(見下文)。我必須做出三個小小的改變,才能按照您的期望工作。

爲了讓觀察者在所有工作中都必須實例化它。在我的例子,我需要添加的行:(根據docs

Mongoid.observers = CommentBadgeObserver 
Mongoid.instantiate_observers 

在Rails可以達到增加這配置/ application.rb中同樣的事情:

config.mongoid.observers = :comment_badge_observer 

我想有也是CommentBadge.check_conditions_for中的小邏輯錯誤,> 1應該是> 0

最後我更改了User#award方法來保存徽章而不是用戶,因爲存儲關係的「外鍵」字段位於徽章一側。

class Comment 
    include Mongoid::Document 
    field :name 
    belongs_to :user 
end 

class CommentBadgeObserver < Mongoid::Observer 
    observe :comment 

    def after_create(comment) 
    CommentBadge.check_conditions_for(comment.user) 
    end 
end 

class Badge 
    include Mongoid::Document 
    field :title 
    belongs_to :user 
end 

class CommentBadge < Badge 
    def self.check_conditions_for(user) 
    if user.comments.size > 0 
     badge = CommentBadge.create!(:title => "Comment badge") 
     user.award(badge) 
    end 
    end 
end 

class User 
    include Mongoid::Document 
    field :first_name 
    has_many :comments 
    has_many :badges 

    def award(badge) 
    self.badges << badge 
    badge.save! 
    end 
end 

Factory.define(:user) do |u| 
    u.first_name 'Bob' 
end 

Factory.define(:comment) do |c| 
    c.name 'Some comment...' 
end 

# Observers need to be instantiated 
Mongoid.observers = CommentBadgeObserver 
Mongoid.instantiate_observers 

describe CommentBadgeObserver do 
    it 'should create badges' do 
    @user = Factory.build(:user) 
    @comment = Factory(:comment, :user => @user) 
    @user.badges.count.should == 1 
    @user.badges[0].title.should == "Comment badge" 
    end 
end 
+0

它很好用!非常感謝史蒂夫! – obo

+0

很高興知道並感謝你。你是否在你的Rails中工作,是觀察者實例化還是其他? – Steve

+0

是的,我在我的應用程序中工作。我必須在我的spec文件中設置觀察者實例化的兩行。 – obo