在 Ruby on Rails 中设计类似于 Stack Overflow 的基于点的系统
我并不是想重新创建 Stack Overflow,我确实看过类似的问题,但他们没有很多答案。
我对如何设计 Rails 应用程序感兴趣,特别是模型及其关联,以便捕获各种不同类型的操作及其点数。此外,这些点会随着时间的推移而衰减,并且可能会以其他操作或我正在跟踪的其他数据的形式进行修改。
例如,如果我正在设计 Stack Overflow(我又不是),它会像下面这样。
- 创建问题 = 5 分
- 回答问题 = 10 分
- 所选正确答案是回答问题分数的 x2 修正值。
从设计角度来看,我觉得关键部分需要 3 个模型。
动作模型是多态的,因此它可以属于问题、答案或其他任何内容。关联的类型存储在类型字段中。它还包含一个点字段,该字段是在创建时通过在我接下来讨论的点模型中查找来计算的。它还应该更新用户模型的总分,我不会在这里讨论。
点模型是一个查找表,操作可以在其中找出它们的点。它使用操作类型作为键。它还存储点的数量和衰减的字段。
修饰符模型是我不知道该如何处理的模型。我认为它可能应该是一个查找表,就像使用操作类型字段的点一样。此外,它还需要某种关于何时应用的条件。我不确定如何存储条件语句。它还需要存储点的修改方式。例如 x2、+5、-10、/100 等。另一个问题是在操作发生后如何应用修饰符。在我的示例中,这将是当一个问题被选择作为答案时。此时,积分已经确定。我能想到的唯一方法是在每个模型上都有一个 after_save ,该模型可能是一个修改器,用于检查修改器表并应用它们。但在我看来,这似乎是错误的。
还有其他问题,例如如何处理腐烂。我想我需要一个 cron 作业来重新计算每个人的分数,但这似乎扩展性不好。
我不确定我是否想得太多了,但我想要一些反馈。
I'm not trying to recreate Stack Overflow and I did look at similar questions but they don't have many answers.
I'm interested in how to design a rails app, particularly the models and their associations, in order to capture various different kinds of actions and their points amount. Additionally these points decay over time and there are possible modifiers in the form of other actions or other data I'm tracking.
For example if I were designing Stack Overflow (which again I'm not) it would go something like the following.
- Creating a question = 5 points
- Answering a question = 10 points
- The selected correct answer is a x2 modifier on the points for Answer a question.
From a design perspective it seems to me like I need 3 models for the key parts.
The action model is polymorphic so it can belong to questions, answers, or whatever. The kind of association is stored in the type field. It also contains a points field that is calculated at creation time by a lookup in the points model I will discuss next. It should also update a total points on the user model, which I won't discuss here.
The points model is a lookup table where actions go to figure out their points. It uses the actions type as a key. It also stores the number amount for the points and a field for their decay.
The modifier model is the one where I'm not sure what to do with. I think it should probably be a lookup table too like points using the action's type field. Additionally it needs some sort of conditional on when it should be applied. I'm not sure how to store a conditional statement. It also needs to store how the points are modified. For example x2, +5, -10, /100, etc. The other problem is how does the modifier get applied after the action has already happened. In my example it would be when a question is selected as answered. By this time the points were already set. The only way I can think of doing it is to have an after_save on every model that could be a modifier which checks the modifier table and applies them. That seems wrong to me somehow though.
There are other problems too like how to handle the decay. I guess I need a cron job that just recalculates everyone's points but that seems like it doesn't scale well.
I'm not sure if I'm over thinking this or what but I'd like some feedback.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我倾向于使用日志聚合快照,您可以在其中记录离散事件,然后定期聚合更改并将其存储在单独的表中。这将允许您将诸如衰减之类的事情作为插入作业而不是更新作业来处理。根据有多少票数,您甚至可以随着时间的推移汇总它们,然后从特定点向前滚动(尽管每个问题或答案可能没有足够的票数来引起关注),但考虑到您可能还有其他事情就像要跟踪的用户总积分一样,快照可能是一件好事。
然而,我认为在聚合快照表中解决衰减问题之前,您需要弄清楚如何处理衰减。
I tend to prefer an log-aggregate-snapshot where you log discrete events and then periodically aggregate changes and store those in a separate table. This would allow you to handle something like decay as an insert job rather than an update job. Depending on how many votes there are, you could even aggregate them over time and just roll forward from a specific point (though probably there aren't enough per question or answer for this to be a concern) but given that you may have other things like user's total points to track that may be a good thing to snapshot.
I think you need to figure out how you are going to handle decay before you address it in a aggregate snapshot table, however.
现在Rails有gem来实现这个功能
https://github.com/tute/merit
Now Rails has gem to achieve this feature
https://github.com/tute/merit