2011-11-22 34 views
8

Trên một mô hình dữ liệu mongoid đơn giản với người dùng có nhiều nhận xét, tôi muốn trao giải thưởng cho người dùng khi có ít nhất 1 nhận xét. Vì vậy, tôi thiết lập một quan sát viên như thế này:Làm thế nào để kiểm tra Mongoid :: Observer với rspec

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 

Phương pháp user.award: (? Nhưng tôi đoán nó là bình thường vì các quan sát viên được thực hiện ở chế độ nền)

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

Các thử nghiệm sau thất bại

Cách tốt nhất để xác thực hành vi này là gì?

Trả lời

7

Tôi đã có một sự thích ứng độc lập với mã của bạn (xem bên dưới). Tôi đã phải thực hiện ba thay đổi nhỏ để làm cho nó hoạt động theo cách bạn mong đợi.

Để làm cho Observer hoạt động, bạn phải khởi tạo nó. Trong ví dụ của tôi, tôi cần thiết để thêm các dòng:

Mongoid.observers = CommentBadgeObserver 
Mongoid.instantiate_observers 

trong Rails bạn có thể đạt được điều tương này thêm vào config/application.rb (theo docs):

config.mongoid.observers = :comment_badge_observer 

Tôi nghĩ rằng có cũng là lỗi logic nhỏ trong số CommentBadge.check_conditions_for, số > 1 phải là > 0.

Cuối cùng tôi đã thay đổi phương thức User#award để lưu huy hiệu thay vì người dùng, bởi vì trường 'khóa ngoại' lưu trữ mối quan hệ ở bên huy hiệu.

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

Nó hoạt động tuyệt vời! Cảm ơn rất nhiều Steve! – obo

+0

Điều đó là tốt để biết và cảm ơn bạn. Bạn có làm cho nó hoạt động trong Rails của bạn và đó có phải là người theo dõi người quan sát hay cái gì khác không? – Steve

+0

Có, tôi đã làm việc đó trong đơn đăng ký của mình; Tôi đã phải thiết lập hai dòng của instantiation instantiation trong tập tin spec của tôi. – obo

Các vấn đề liên quan