2011-11-22 10 views
8

コメントが多いユーザーの簡単なモンゴイドデータモデルでは、少なくとも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

自分のコードをスタンドアロンで動作させることができました(下記参照)。私はそれがあなたが期待していたように働くために3つの小さな変更を加えなければなりませんでした。

オブザーバを動作させるには、インスタンス化する必要があります。私の例では、私は、行を追加する必要:Railsでは

Mongoid.observers = CommentBadgeObserver 
Mongoid.instantiate_observers 

あなたは(docsによる)のconfig/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

はい、私はアプリケーションで作業しました。オブザーバーのインスタンス化の2つの行をspecファイルに設定する必要がありました。 – obo

関連する問題