我需要一些关于轨道投票系统的建议,以便每月识别最高投票率。我有一个可以工作的系统,但对于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
我将使用'never'gem来运行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 :(得分: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)
确保数据库中的所有内容都已正确编入索引,
你可以更精简它,但SQL会变得更复杂。
答案 1 :(得分:1)
最后两行可能是:
Charity.where(id:winning_ids).update_all(last_win:Date.today)
这将转换为单个SQL更新命令,而不是为每个获胜慈善机构发布更新命令。
您确定获奖慈善机构的第一部分看起来没问题,而且由于您将其作为一项计算机工作,您可能不在乎是否需要几分钟。
但是,如果您想实时显示这些值,可以在after_create
上添加Vote
挂钩来更新其所有者慈善机构的计数器(可能在另一个表中):< / p>
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