ActiveRecord与声誉系统相关的查询(has_many_through +多态关联)

时间:2013-10-20 04:52:44

标签: sql ruby-on-rails activerecord polymorphic-associations

问题

我正在构建一个应用程序(Rails 4,mysql)来促进创新锦标赛,类似于Darwinator。我使用ActiveRecord Reputation System作为评级系统。我需要一个以下格式的JSON

results = 
{
  contributor_count: 51  /* (submitters UNION raters).count */
  opportunity_count: 100 /* total ideas submitted */
  vote_count: 250 /* total votes/ratings cast */
  opportunities: [  /* descending order of avg_rating */
    {avg_rating: 9.6, content: "vision"},
    {avg_rating: 9,   content: "favorite xkcd comic"},
    {avg_rating: 8,   content: "smash bro skill"},
    {avg_rating: 7.9, content: "programming proficiency"},
    {avg_rating: 7.1, content: "experience"},
    ...
  ] 
}

<小时/>

用户故事

Bob创建/开始以下锦标赛:

  

“首席技术官最重要的特征是什么?”

鲍勃说服他的20个朋友总共提交了100个想法(机会):

  

“愿景”,“最喜欢的xkcd漫画”,“经验”,“粉碎兄弟技能”,   “编程熟练程度”等。

然后鲍勃说服他的50个朋友(包括大部分想法提交者)帮助他过滤提交的内容(机会),通过对提交的评分进行1-10分。

在对100个提交的机会进行了250次评级后(平均每次机会获得2.5次评分),Bob点击“完成锦标赛”按钮,然后进入锦标赛结果页面

Bob将获得锦标赛的结果(参见上面的JSON)

<小时/>

要解决的问题

结果JSON:

  1. contributor_count
  2. opportunity_count
  3. vote_count
  4. 按avg_rating降序排列的机会
  5. 评级流程

    1. 随机选择用户未评级/投票/评估的机会
    2. voted_on_count
    3. remaining_to_vote_on_count
    4. <小时/>

      状态/更新

      我将在整个解决此问题的过程中更新此内容。期待更多信息。

      contributor_count : 我可以通过@ tournaments.users获得提交者。我需要能够获得一套独特的评估者,然后UNION与评估者一起提交者......我怎样才能获得一套独特的评估者?

      OPPORTUNITY_COUNT : 赠品。 @ tournament.opportunities.count

      vote_count : 目前的策略是@ tournament.opportunities.inject(0){| sum,o | sum = sum + o.evaluators_for(:avg_ratings).count}

      以avg_rating降序排列的机会: 嗯...一些原始的SQL?

      随机选择用户未评级/投票/评估的机会: 使用ramdumb gem,@ opportunity = @ tournament.opportunities.random ...但是,需要过滤掉用户未评级的内容

      voted_on_count : 与上一个问题有关。 @ tournament.opportunities.where(投票赞成这个机会).count

      remaining_to_vote_on_count : @ tournament.opportunities.count - voted_on_count

      <小时/>

      模型

      class Tournament < ActiveRecord::Base
        has_many :opportunities
        # submitters of
        has_many :users, through: :opportunities
        ...
      end
      
      class Opportunity < ActiveRecord::Base
        belongs_to :tournament
        belongs_to :user
      
        has_reputation :avg_rating,
                       source: :user,
                       aggregated_by: :average
        ...
      end
      
      class User < ActiveRecord::Base
        has_many :opportunities
        has_many :tournaments, through: :opportunities
        has_many :evaluations, class_name: "RSEvaluation", as: :source
      
        has_reputation :avg_rating,
                       source: {reputation: :avg_rating, of: :opportunities},
                       aggregated_by: :average
        ...
      end
      

      schema.rb

      create_table "tournaments", force: true do |t|
        t.boolean  "currently_running", default: true
        t.datetime "created_at"
        t.datetime "updated_at"
        t.string   "description"
      end
      
      create_table "users", force: true do |t|
        t.datetime "created_at"
        t.datetime "updated_at"
      end
      
      create_table "opportunities", force: true do |t|
        t.string   "content"
        t.integer  "tournament_id"
        t.integer  "user_id"
        t.datetime "created_at"
        t.datetime "updated_at"
      end
      
      create_table "rs_evaluations", force: true do |t|
        t.string   "reputation_name"
        t.integer  "source_id"
        t.string   "source_type"
        t.integer  "target_id"
        t.string   "target_type"
        t.float    "value",           default: 0.0
        t.datetime "created_at"
        t.datetime "updated_at"
      end
      
      create_table "rs_reputations", force: true do |t|
        t.string   "reputation_name"
        t.float    "value",           default: 0.0
        t.string   "aggregated_by"
        t.integer  "target_id"
        t.string   "target_type"
        t.boolean  "active",          default: true
        t.datetime "created_at"
        t.datetime "updated_at"
      end
      
      create_table "rs_reputation_messages", force: true do |t|
        t.integer  "sender_id"
        t.string   "sender_type"
        t.integer  "receiver_id"
        t.float    "weight",      default: 1.0
        t.datetime "created_at"
        t.datetime "updated_at"
      end
      

0 个答案:

没有答案