2013-03-11 64 views
2

我需要一些關於投票系統的建議,這些投票系統可以在每月的基礎上識別頂級投票獲得者。我有一個可以工作的系統,但是對於rails來說是新手,我確信有更高效的方法可用。下面是我的當前設置(略控制器代碼)的簡化版本:Ruby on Rails - 每月頂級投票獲取者

class Charity < ActiveRecord::Base 
    has_many :votes 
end 

class Vote < ActiveRecord::Base 
    belongs_to :charity 
end 

我的架構如下:

ActiveRecord::Schema.define(:version => 20130310015627) do 
    create_table "charities", :force => true do |t| 
    t.string "name" 
    t.text  "description" 
    t.date  "last_win" 
    t.datetime "created_at", :null => false 
    t.datetime "updated_at", :null => false 
    end 
    create_table "votes", :force => true do |t| 
    t.integer "charity_id" 
    t.datetime "created_at", :null => false 
    t.datetime "updated_at", :null => false 
    end 
end 

我將使用「只要」寶石運行cron作業確定每月贏家並更新慈善機構表的'last_win'列。 下面的代碼是在那裏我質疑我的效率:

vote_counts = Vote.count(:group => "charity_id") 
most_votes = vote_counts.values.max 
winning_ids = vote_counts.map{|k,v| v == most_votes ? k :nil }.compact 
charities = Charity.find(winning_ids) 
charities.each {|charity| charity.update_attributes(:last_win => Date.today)} 

我敢肯定有很多方法可以做到這一點更好,希望得到一些建議。如果您對建立投票表/關聯的更好方式有任何建議,那也是值得讚賞的。

由於提前, CRS

+0

只能有一個贏家嗎?它看起來像你的代碼處理關係。 – 2013-03-11 01:22:36

+0

可以有多個獲勝者。 cron工作將在每月的第一天運行。我會調整它只計算在上個月投出的選票。 – Clay 2013-03-11 01:30:26

回答

2

東西像這樣:

如果只有一個贏家,這將工作我想

winner_id = Vote.group(:charity_id).order("count(*) desc").pluck(:charity_id).first 
Charity.find(winner)id).update_attribute!(:last_win => Date.today) 

您可以修改它的聯繫:

most_votes = Vote.group(:charity_id).order("count(*) desc").count.first[1] 
winners = Vote.group(:charity_id).having("count(*) = ?", most_votes).pluck(:charity_id) 

Charity.where(:id => winners).update_all(:last_win => Date.today) 

確保一切都在你的數據庫索引正確,

你也許可以簡化IT較多,但SQL將會變得更加複雜。

+0

感謝您的幫助。感謝您提醒我索引。 – Clay 2013-03-12 00:47:48

1

最後兩行可能是:

Charity.where(id:winning_ids).update_all(last_win:Date.today) 

這將轉化爲一個SQL更新命令,而不是對每個獲獎慈善機構發出的更新命令。

第一部分,你確定獲勝的慈善機構看起來沒問題,而且由於你將它作爲cron工作運行,你可能不在乎是否需要幾分鐘時間。

不過,如果你想顯示實時值,你可以在Vote添加after_create鉤來更新計數器爲它的主人慈善機構(可能在另一個表):

class Vote < ActiveRecord::Base 
    belongs_to :charity 
    after_create :increment_vote_count 
    CharityVote.where(year:Time.now.year, month:Time.now.month, 
    charity_id:self.charity_id).first_or_create.increment!(:counter) 
end