2

毎月トップの投票者を認識するレールの投票システムについてアドバイスが必要です。私は機能するシステムを持っていますが、レールは初めてなので、もっと効率的な方法が利用できると確信しています。以下は、私の現在のセットアップの簡略版です(コントローラーコードは省略されています):

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

このようなもの:

勝者が1人しかいない場合、これはうまくいくと思います

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

最後の 2 行は次のようになります。

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 に答える