如何在RoR中实现成就系统

时间:2009-05-19 22:06:31

标签: ruby-on-rails

我很难尝试在我的Ruby on Rails应用程序中实现一个成就系统。

我有很多我想要检查的成就。所有都是由各种控制器中的一些创建动作触发的。

我有一个想法,我将拥有一个成就模型,其中包括控制器和它响应的动作。然后为创建过滤器,检查适用的成就。在实际定义/执行成就时,我会陷入困境。每项成就可能需要不同的数据。例如,人们想要知道用户已经回答了多少问题,另一个问题是他们做出了多少评论,以及第三个用户邀请了多少人回答了问题。

实际上将所有必要的ruby代码直接嵌入到数据库中是最好的做法吗?我可以看到做一个自包含块来执行所有活动记录查找等,并返回true / false,尽管我们仍然存在一些关于事先知道什么是设置的问题(即current_user等)。

任何合理的最佳做法都不会让我感到肮脏?我可以看到一个完整的策略/规则引擎是一条路径,虽然这可能比我计划更多地吓到我。

谢谢! 奥伦

3 个答案:

答案 0 :(得分:52)

我同意您使用Achievement模型的想法。

但是,您可能不应该在控制器中实现触发器。想象一下,你有两种发表评论的方式;你将不可避免地得到代码重复。这种行为属于模型。

假设您要跟踪用户发表的评论数量,并为100条评论奖励成就。您可以使用以下模型:

class User < ActiveRecord::Base
  has_many :comments
  has_many :achievements

  def award(achievement)
    achievements << achievement.new
  end

  def awarded?(achievement)
    achievements.count(:conditions => { :type => achievement }) > 0
  end
end

class Achievement < ActiveRecord::Base
  belongs_to :user
end

class Comment < ActiveRecord::Base
  belongs_to :user
end

class CommentAchievement < Achievement
  def self.check_conditions_for(user)
    # Check if achievement is already awarded before doing possibly expensive
    # operations to see if the achievement conditions are met.
    if !user.awarded?(self) and user.comments.size > 100
      user.award(self)
    end
  end
end

不同的成就是Achievement模型的所有子类,并使用单表继承,因此它们只存储在一个表中。子类可以包含每个单独成就所需的所有逻辑。您还可以在此模型中存储其他信息,例如获得成就的日期。要确保数据库拒绝重复的成就,您可以在UNIQUEtype列上创建user_id索引。

只要你愿意,就可以调用{p> CommentAchievement.check_conditions_for(user)。您可以创建一个不时运行的后台作业,或者您可以创建一个观察者:

# app/models/comment_achievement_observer.rb
class CommentAchievementObserver < ActiveRecord::Observer
  observe :comment

  def after_create(comment)
    CommentAchievement.check_conditions_for(comment.user)
  end
end

# config/environment.rb
config.active_record.observers = :comment_achievement_observer

以上只是如何做到这一点的想法,当然可能还有其他人。代码只是一个例子,我还没有真正测试过它。希望这对你有所帮助。

答案 1 :(得分:18)

非常好的解决方案,molf。

我将其转换为插件/ gem,其中包含用于获得新成就的生成器:

http://github.com/paulca/paths_of_glory

快乐成就!

答案 2 :(得分:7)

我为这项任务写了一个Rails 3 gem,它适用于徽章,积分和排名。您可以在https://github.com/tute/merit中找到源代码。