我正在尝试在我的 Ruby on Rails 应用程序中实现一个成就系统,但效果很差。
我有一长串想要检查的成就。所有这些都是由各种控制器中的某些创建操作触发的。
我的想法是我将拥有一个成就模型,其中包括控制器及其响应的操作。然后对创建进行之前过滤并检查适用的成就。当涉及到实际定义/执行成就时,我陷入了困境。每个成就可能需要不同的数据。例如,一个人想知道用户回答了多少个问题,另一个人想知道他们发表了多少条评论,第三个想知道用户邀请的有多少人做出了回应。
实际上将所有必要的 ruby 代码直接嵌入到数据库中是最好的做法吗?我可以看到做一个自包含的块来执行所有活动记录查找等并返回 true/false,尽管我们仍然存在一些关于提前了解设置的问题(即 current_user 等)。
有什么合理的最佳实践不会让我觉得肮脏吗?我可以看到完整的策略/规则引擎是一条路径,尽管这可能比计划a更让我害怕。
谢谢!
奥伦
我同意你的想法,使用Achievement
model.
不过,您可能不应该在控制器中实现触发器。想象一下,您有两种发表评论的方式;你将不可避免地得到代码重复。这种行为属于模型。
假设您想要跟踪用户发表的评论数量,并为 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
模型,并使用单表继承,以便它们仅存储在一张表中。子类可以包含每个单独成就所需的所有逻辑。您还可以在此模型中存储其他信息,例如授予成就的日期。为了确保数据库拒绝重复的成就,您可以创建一个UNIQUE
上的索引type
and user_id
列。
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
以上只是一种思路,当然可能还有其他的。代码只是一个例子,我还没有实际测试过。希望对您有一定的帮助。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)