Ruby on Rails - 每月最高票数

时间:2013-03-11 00:52:08

标签: ruby-on-rails ruby ruby-on-rails-3.2 voting favorites

我需要一些关于轨道投票系统的建议,以便每月识别最高投票率。我有一个可以工作的系统,但对于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

2 个答案:

答案 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