У меня есть рабочая автономная адаптация вашего кода (см. Ниже).Мне нужно было сделать три небольших изменения, чтобы заставить его работать так, как вы ожидали.
Чтобы заставить Обозревателя работать вообще, вам нужно создать его экземпляр.В моем примере мне нужно было добавить строки:
Mongoid.observers = CommentBadgeObserver
Mongoid.instantiate_observers
В Rails вы можете добиться того же, добавив это в config / application.rb (согласно docs ):
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