Modern tools for Ruby/Rails for building an achievement system

限于喜欢 提交于 2019-12-20 08:01:21

问题


I am interested in building a robust achievement system for my Ruby on Rails application.

The achievements can happen in a myriad of ways. Normally, we'd have some criteria that can happen to several models, some required, some optional (mix and match) that triggers an achievement.

I would say this is similar to the achievement system on here or Foursquare badges. Ideally if there is a modern tool out there that can help abstract a lot of the work in some DSL, that would be fantastic.

I'm interested in seeing how others solved this issue using Ruby or Ruby on Rails. Building this from scratch sounds unreasonable as I'm sure it's been solved many times repeatedly.


回答1:


An achievement system seems simple at first glance but can quickly become quite complex.

First, you have to identify what kind of achievements you want to provide. You can award :

  1. Badges
  2. Points
  3. Ranks

Of course, you'll also want to make various combinations of those. Non-obvious but frequently asked features are :

  • the ability to know its progress towards a specific rank or badge.
  • the ability to hide some badges

In RoR world, I have found 3 third-party libraries freely available. As often, there's no magic bullet and you have to choose one according to your needs.

Badgeable

Badgeable is a simple DSL which implements only a badge system. It's dynamic and simple to understand. This example is from the official documentation :

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

It would award the Fancy Pants badge to the diner who has eaten 12 expensive meals where the awarding meal was out of town. It includes interesting features like unseen badge, but cannot award the same badge multiples times. By default, Badgeable add hooks after creation of the observed record. In the above example, badge condition is executed after each Meal creation.

It supports both ActiveRecord and Mongoid.

Paths of Glory

Paths of Glory is quite different of Badgeable. This gem is more towards Points and Ranks. It separates logic to compute badges (observer) from logic to describe badges (Achivement class). Maybe it would be more natural for you if you already use Observer pattern. Take note that it's pure Ruby, there's no DSL in Paths of Glory.

In the Achievement class, you describe your levels, what you count and how to award achievements :

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

Observer part is very classic :

  observe :post

  def after_save(post)
    Teacher.award_achievements_for(post.user) unless post.new_record?
  end

It's not well documented but you can find a sample application using it here.

It includes helpers in order to follow progress to the next rank. Since it uses classic rails features, it should be compatible with every rails ORM available.

Merit

Merit seems to be the more complete gem about this subject, ATM. It allows to define badges, points and rules with a DSL.

For badges, it looks like :

grant_on ['users#create', 'users#update'], :badge => 'autobiographer', :temporary => true do |user|
  user.name.present? && user.address.present?
end

It will check on both creation and update if user has put its address. It will remove the badge if user removes its address.

For points, it's capable to count a score based on multiple models :

score 20, :on => [ 'comments#create', 'photos#create' ]

For ranks, it's quite similar to badges. Difference is mainly in the level :

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

This gem also provides means to compute badges or ranks in cron jobs and not after each writes on objects :

task :cron => :environment do
  MeritRankRules.new.check_rank_rules
end

Under the hood, Merit uses Ambry to store badges information. It should help to both reduces it's noise on your datastore and make it a little faster. There's an experimental support available for MongoMapper. I haven't found any means to have unseen badges or to follow progress towards a badge.




回答2:


activerecord-reputation-system by twitter folks if you need a comprehensive solution.




回答3:


Have you looked at Badgeable?




回答4:


You could use something like http://www.badgeville.com/



来源:https://stackoverflow.com/questions/9608069/modern-tools-for-ruby-rails-for-building-an-achievement-system

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!