这是我的模型和关联:
让我们假设有四个奖品(捕获为记录):
用户每天都可以获得一个或多个这些奖品。但用户每天只能获得一次每个奖品。例如,如果用户赢得 AwesomeStatus,则会向 Awards 表中添加一条记录,其中包含对 User 和 Prize 的 fk。显然,如果用户没有赢得当天的 AwesomeStatus,则不会添加任何记录。
在一天结束时(比方说午夜之前),我想返回丢失了 AwesomeStatus 的用户列表。 (当然,要失去您的 AwesomeStatus,您必须在前一天拥有。)不幸的是,就我而言,我认为观察者不会起作用,并且必须依赖脚本。无论如何,您将如何确定哪些用户丢失了 AwesomeStatus?注意:不要让你的解决方案过分依赖时间段——在这种情况下是一天。我希望在每个时间段内用户有机会赢得奖品(也可能失去奖品)的次数保持灵活性。
最佳答案
我可能会做这样的事情:
类 Award 也应该有一个 Awarded_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/