2011-02-24 157 views
3

这里是我的模型和协会:逻辑和代码帮助

  • 用户有很多奖
  • 奖属于用户
  • 奖有许多奖
  • 奖属于奖

让我们假设有四个奖项(如捕获记录):

  • 小马
  • 玩具
  • AwesomeStatus

每天用户可以授予这些奖励的一种或多种。但用户每天只能获得一次奖品。如果用户赢得AwesomeStatus,为前,一个记录添加到表奖与FK到用户和奖。显然,如果用户当天没有赢得AwesomeStatus,则不会添加任何记录。

在这一天结束(午夜之前,让我们说),我想回到谁失去了他们AwesomeStatus用户的列表。 (当然,失去你AwesomeStatus,你以前有一天。)不幸的是,在我的情况,我不认为观察员将工作,将不得不依靠脚本。无论如何,你会如何确定哪些用户失去了他们的AwesomeStatus?注意:不要让你的解决方案过度依赖于时间段 - 在这种情况下是一天。我要保持灵活性多少次,每次无论阶段的玩家有机会赢得奖品(并且还失去它)。

+0

好问题.... – Andrew 2011-03-06 17:03:40

回答

2

我可能会做这样的事情:

类奖也应该有一列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) 

有可能是给阿雷尔查询或更好的东西写范围的某些方面,我有没有高手呢,但是这方式应工作到那么:)

0

我想补充一个整数“时间”字段的奖项,它代表一个特定的时间段(天,周,5个小时的时间内,任何你想要的)。

现在,你可以搜索奖励表谁拥有在t-1的奖励状态的用户,而不是在t:

SELECT prev.user_id 
FROM awards prev 
OUTER JOIN awards current ON prev.user_id = current.user_id 
AND prev.prize_id = current.prize_id 
AND current.time_period = 1000 
WHERE prev.prize_id = 1 
AND current.prize_id IS NULL 
AND prev.time_period = 999 
0

只要使用的updated_at,或添加awarded_at像上述建议,并用它像这样:

scope :awarded, proc {|date| where(["updated_at <= ?", date])} 

在您的奖励模式。打印像这样的,也许:

awesome_status = Prize.find_by_name('AwesomeStatus') 
p "Users who do not have AwesomeStatus anymore:" 

User.all.each {|user| p user.username if user.awards.awarded(1.day.ago).collect(&:id).include?(awesome_status)} 

如果你希望它是动态的,显示的地方,等等抛出一个“lasts_for”进奖和比较反对,干脆写一个维护的cronjob,设置一个“活跃” boolean奖励为false而不是删除关联。