如何在 RoR 中实现成就系统 [英] How to implement an achievement system in RoR

查看:57
本文介绍了如何在 RoR 中实现成就系统的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在我的 Ruby on Rails 应用程序中实现一个成就系统,效果很差.

I'm attempting, poorly, to implement an achievement system into my Ruby on Rails application.

我有一长串想要检查的成就.所有这些都是由各种控制器中的一些创建操作触发的.

I have a long list of achievements I'd like to check for. All are triggered by some create action in various controllers.

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

I've had the idea that I'll have a achievement model, which includes the controller and action it responds to. Then do a before filter for the create and check for applicable achievements. I get stuck when it comes to actually defining/executing the achievements. Each achievement may require different data. For example one will want to know how many questions a user has answered, another how many comments they've made, and a third how many people the user invited have responded.

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

IS the best thing to do to actually just embed all the necessary ruby code straight into the DB? I could see doing a self contained block that does all the active record finding, etc and returns true/false, though there we are still some issues about knowing what is setup in advance (i.e. current_user, etc).

是否有任何合理的最佳做法不会让我感到肮脏?我可以看到完整的政策/规则引擎是一种途径,尽管这可能比计划 a 更让我害怕.

Any reasonable best practices out there that don't make me feel dirty? I could see a full on policy/rules engine being one path, though that may scare me more than plan a.

谢谢!奥伦

推荐答案

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

I agree with your idea to use an Achievement model.

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

You should probably not implement the triggers in your controllers, though. Imagine that you have two ways to post a comment; you will inevitably get code duplication. This sort of behaviour belongs in a model.

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

Suppose you want to track the number of comments that a user makes, and award an achievement for 100 comments. You could have the following models:

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模型的子类,采用单表继承,只存储在一张表中.子类可以包含每个单独成就所需的所有逻辑.您还可以在此模型中存储其他信息,例如授予成就的日期.为了确保数据库拒绝重复的成就,您可以在 typeuser_id 列上创建一个 UNIQUE 索引.

The different achievements are all subclasses of Achievement model, and use single table inheritance so that they are stored in just one table. The subclasses can contain all logic required for each individual achievement. You can also store additional information in this model, such as the date on which the achievement was awarded. To make sure that the database rejects duplicate achievements, you could create a UNIQUE index on the type and user_id columns.

CommentAchievement.check_conditions_for(user) 可以随时调用.您可以创建一个不时运行的后台作业,或者您可以创建一个观察者:

CommentAchievement.check_conditions_for(user) can be called whenever you wish to. You may create a background job that runs every now and then, or you could create an observer:

# 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

以上只是一种方法,当然可能还有其他方法.代码只是一个例子,我还没有实际测试过.希望对你有帮助.

The above is just one idea of how to do it, of course there may be others. The code is just an example, I haven't actually tested it. Hopefully it's of some help to you.

这篇关于如何在 RoR 中实现成就系统的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆