使用.order根据用户在Rails 4

时间:2016-04-08 01:54:08

标签: mysql ruby-on-rails

我正在尝试在表格中返回用户的排名,我感到难过。

首先,我有一张桌子可以在我的游戏中捕捉得分Participation。对于两个玩家,它将包含user_idgame_id,最后是score的结果,如下所示:

<Participation id: 168, user_id: 1, game_id: 7, ranking: 0, created_at: "2016-04-07 05:36:48", updated_at: "2016-04-07 05:36:58", finished: true, current_question_index: 3, score: 2>

然后第二个结果可能是:

<Participation id: 169, user_id: 2, game_id: 7, ranking: 0, created_at: "2016-04-07 05:36:48", updated_at: "2016-04-07 05:36:58", finished: true, current_question_index: 3, score: 1>

如果我想展示用户所在位置的排行榜,那就很简单,例如:Participation.where(game_id: "7").order(:asc)。我现在成功了。

相反,我希望返回一个结果,用户在表格中排名,如果由score组织,则竞争对手。对于裸骨,在上面的例子中,我会有用户1和用户2,都玩游戏7,并且:

  • user_id 1:应该返回1表示第1名,更高分2分
  • user_id 2:应该返回2为第2位,低分为1分

如何在我的控制器中重写participation语句,以根据分数检查用户在匹配game_id的位置,然后根据该排名分配整数值?

对于奖励积分,如果我可以让控制器返回该值(如user_id 1为1),您认为使用update_attributes将其添加到ranking是不错的列而不是打破一个新表来存储用户排名?

3 个答案:

答案 0 :(得分:0)

如果您正在使用mysql,请尝试在有序查询上使用ROW_NUMBER函数来计算排名:

homeMenu=(ImageView)findViewById(R.id.homeMenu);
homeTitle=(TextView)findViewById(R.id.homeTitle);

生成的SQL将是:

Participation.select("user_id, ROW_NUMBER() AS rank").where(game_id: game_id).order(score: :asc)

我通常使用Postgres,因此无法直接测试查询,但它应该可以正常工作。

如果您需要频繁访问排名列,或者您需要访问单个用户/游戏对的排名,我建议您暂停排名列。您还需要设置一个后台工作来定期执行此操作,可能每15分钟左右一次。但是,上面动态查询的好处是它更有可能是最新的,但需要时间来生成,具体取决于该特定游戏存在多少参与条目。

答案 1 :(得分:0)

尝试

Participation.all.order("game_id asc, score desc")

答案 2 :(得分:0)

我最终想出了一个如何做到这一点的策略。同样,这里的关键是我要分配一个&#34; rank&#34;一个用户,实际上是一个整数,表示&#34; row&#34;如果我们按照score列排序所有结果,他们就会进入。

这是我的过程:

    a = Participation.where(user_id: current_user.id).last.score
    b = Participation.where(user_id: current_user.id).last.id
    scores = Participation.where(game_id: params[:game_id]).where("score > ?", a).count

    if scores == 0 
        Participation.update(b, :ranking => 1)
    else 
        Participation.update(b, :ranking => scores + 1)
    end 

  end

简而言之,我计算了特定结果的得分有多少。因此,如果我是用户2并且我获得第二高分,那么这将计算1个结果。使用if / else逻辑,我认为将其转换为排名并相应地更新我的表。

你可以回到这里,说排名可能需要经常更新(比如后台工作),这肯定是正确的。尽管如此,这种方法确实可以回答我的问题。