这是我的模型和关联:

  • 用户获得了很多奖项
  • 奖属于用户
  • 奖有很多奖项
  • 奖属于 Prize

  • 让我们假设有四个奖品(捕获为记录):
  • 小马
  • 玩具
  • 口香糖
  • AwesomeStatus

  • 用户每天都可以获得一个或多个这些奖品。但用户每天只能获得一次每个奖品。例如,如果用户赢得 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/

    10-12 15:37