Ответ 1
Система достижений кажется простой на первый взгляд, но может быстро стать довольно сложной.
Во-первых, вы должны определить, какие достижения вы хотите предоставить. Вы можете наградить:
- Значки
- Точки
- Ряды
Конечно, вы также захотите сделать различные комбинации. Неочевидные, но часто задаваемые функции:
- способность знать свой прогресс в отношении определенного ранга или значка.
- способность скрыть некоторые значки
В мире RoR я обнаружил, что 3 независимых библиотеки доступны. Как часто, нет волшебной пули, и вам нужно выбрать ее в соответствии с вашими потребностями.
Badgeable
Badgeable - это простой DSL, который реализует только систему значков. Это динамично и легко понять. Этот пример приведен из официальной документации:
badge "Fancy Pants" do
thing Meal
subject :person
count
Meal.where(:price_cents.gte => 10000).count >= 12
end
conditions do |meal|
meal.restaurant.city != meal.eater.city
end
end
Он наградил значком "Необычные брюки" закусочной, который съел 12 дорогих блюд, где награждение еды было за городом. Он включает в себя интересные функции, такие как невидимый значок, но не может присуждать одинаковые кратные значки. По умолчанию Badgeable добавляет крючки после создания наблюдаемой записи. В приведенном выше примере состояние значка выполняется после каждого создания Meal.
Он поддерживает как ActiveRecord, так и Mongoid.
Пути славы
Paths of Glory отличается от Badgeable. Этот камень больше связан с очками и званиями. Он отделяет логику от вычисления значков (наблюдателя) от логики для описания значков (класс Achivement). Возможно, для вас было бы более естественно, если вы уже используете шаблон Observer. Обратите внимание, что это чистый Ruby, там нет DSL в Paths of Glory.
В классе Achievement вы описываете свои уровни, то, что вы считаете и как награждать достижения:
level 1, :quota => 2
level 2, :quota => 4
level 3, :quota => 6
set_thing_to_check { |user| user.posts.count }
def self.award_achievements_for(user)
return unless user
return if user.has_achievement?(self)
user.award_achievement(self)
end
Часть наблюдателя очень классическая:
observe :post
def after_save(post)
Teacher.award_achievements_for(post.user) unless post.new_record?
end
Это не очень хорошо документировано, но вы можете найти пример приложения, используя здесь.
Он включает помощников, чтобы следить за ходом до следующего ранга. Поскольку он использует классические функции рельсов, он должен быть совместим с любыми доступными ORM рельсами.
Merit
Merit кажется более полным камнем об этом предмете, ATM. Это позволяет определять значки, баллы и правила с помощью DSL.
Для значков это выглядит так:
grant_on ['users#create', 'users#update'], :badge => 'autobiographer', :temporary => true do |user|
user.name.present? && user.address.present?
end
Он будет проверять как создание, так и обновление, если пользователь поставил свой адрес. Он удалит значок, если пользователь удалит свой адрес.
Для очков он способен подсчитывать оценку на основе нескольких моделей:
score 20, :on => [ 'comments#create', 'photos#create' ]
Для рангов это очень похоже на значки. Разница в основном находится на уровне:
set_rank :stars, :level => 2, :to => Commiter.active do |commiter|
commiter.branches > 1 && commiter.followers >= 10
end
set_rank :stars, :level => 3, :to => Commiter.active do |commiter|
commiter.branches > 2 && commiter.followers >= 20
end
Этот камень также предоставляет средства для вычисления значков или рангов в заданиях cron, а не после каждой записи на объекты:
task :cron => :environment do
MeritRankRules.new.check_rank_rules
end
Под капотом Merit используется Ambry для хранения информации о значках. Это должно помочь уменьшить шум на вашем хранилище данных и сделать его немного быстрее. Там есть экспериментальная поддержка для MongoMapper. Я не нашел никаких средств, чтобы иметь невидимые значки или следить за прогрессом в отношении значка.