这是我的模型和关联:
- 用户获得多项奖励
- 奖励属于用户
- 奖品众多
- 奖项属于奖品
假设有四个奖品(作为记录捕获):
- 小马
- 玩具
- 口香糖
- 很棒的状态
每天,用户都可以获得一项或多项此类奖品。但每个奖品每天只能获得一次。例如,如果用户赢得 AwesomeStatus,则会将一条记录添加到“奖项”表中,其中包含“用户”和“奖品”的 fk。显然,如果用户当天没有赢得 AwesomeStatus,则不会添加任何记录。
在一天结束时(假设在午夜之前),我想返回失去 AwesomeStatus 的用户列表。 (当然,要失去 AwesomeStatus,您必须提前一天。)不幸的是,就我而言,我认为观察者不会起作用,并且必须依赖于脚本。无论如何,您将如何确定哪些用户失去了 AwesomeStatus?注意:不要让你的解决方案过度依赖于时间段——在本例中是一天。我希望在每个时期用户有机会赢得奖品(以及失去奖品)的次数方面保持灵 active 。
最佳答案
我可能会做这样的事情:
类(class)奖项还应有一个“argumented_at”列,其中包含授予奖项的日期。因此,当需要创建奖项时,可以这样做:
# This will make sure that no award will be created if it already exists for the current date
@user.awards.find_or_create_by_prize_id_and_awarded_at(@prize.id, Time.now.strftime("%Y-%m-%d"))
然后我们可以有一个范围向所有用户加载将于今天到期的奖励,并且所提供的奖励没有有效奖励。
# user.rb
scope :are_losing_award, lambda { |prize_id, expires_after|
joins("INNER JOIN awards AS expired_awards ON users.id = expired_awards.user_id AND expired_awards.awarded_at = '#{(Time.now - expires_after.days).strftime("%Y-%m-%d")}'
LEFT OUTER JOIN awards AS active_awards ON users.id = active_awards.user_id AND active_awards.awarded_at > '(Time.now - expires_after.days).strftime("%Y-%m-%d")}' AND active_awards.prize_id = #{prize_id}").
where("expired_awards.prize_id = ? AND active_awards.id IS NULL", prize_id)
}
那么我们可以这样调用它:
# Give me all users who got the prize three days ago and has not gotten it again since
User.are_losing_award(@prize.id, 3)
可能有一些方法可以使用 ARel 查询或其他东西更好地编写范围,我还不是这方面的专家,但这种方法应该在那之前有效:)
关于ruby-on-rails - 逻辑和代码帮助,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5101544/