2

我需要一些关于 Rails 投票系统的建议,该系统每月都会识别出票数最高的人。我有一个可以工作的系统,但对 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

我将使用 'whenever' gem 运行一个 cron 作业来确定每月获胜者并更新 charities 表的 '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

4

2 回答 2

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 会变得更加复杂。

于 2013-03-11T01:32:35.767 回答
1

最后两行可能是:

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

这将转化为单个 SQL 更新命令,而不是为每个获奖慈善机构发出更新命令。

您确定获胜慈善机构的第一部分看起来不错,并且由于您将其作为一项 cron 工作运行,您可能不在乎它是否需要几分钟。

但是,如果您想实时显示值,您可以添加一个after_create钩子Vote来更新其所有者慈善机构的计数器(可能在另一个表中):

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
于 2013-03-11T01:16:42.700 回答