2011-02-24 385 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而不是刪除關聯。