【问题标题】:Ordering by specific value in Activerecord按 Activerecord 中的特定值排序
【发布时间】:2013-12-02 22:47:25
【问题描述】:

在 Ruby on Rails 中,我试图根据当前用户是否是获胜者来排序玩家的比赛。

排序顺序为:

  • 按当前用户是否为获胜者排序
  • 然后按 created_at 等排序

我不知道如何做相当于:

Match.all.order('winner_id == ?', @current_user.id)

我知道这行在语法上不正确,但希望它表示顺序必须是:

1) 当前用户获胜的比赛 2) 其他比赛

【问题讨论】:

    标签: ruby-on-rails ruby activerecord rails-activerecord


    【解决方案1】:

    您可以在 SQL ORDER BY 子句中使用 CASE 表达式。然而,AR 不相信在 ORDER BY 中使用占位符,所以你必须做这样讨厌的事情:

    by_owner = Match.send(:sanitize_sql_array, [ 'case when winner_id = %d then 0 else 1 end', @current_user.id ])
    Match.order(by_owner).order(:created_at)
    

    这在任何 SQL 数据库中都应该同样有效(假设您的 @current_user.id 当然是一个整数)。

    您可以通过使用类方法作为范围来减少不愉快:

    class Match < ActiveRecord::Base
      def self.this_person_first(id)
        by_owner = sanitize_sql_array([ 'case when winner_id = %d then 0 else 1 end', id])
        order(by_owner)
      end
    end
    
    # and later...
    Match.this_person_first(@current_user.id).order(:created_at)
    

    隐藏肮脏。

    【讨论】:

    • 这确实成功了。我在控制器中做得很糟糕,但会尝试找出一种优雅的方式来将作用域集成到模型中(通过传递当前用户?)或辅助方法。
    【解决方案2】:

    如果你想在事物的 ruby​​ 端(而不是 SQL 端)进行排序,那么你可以使用 Array#sort_by 方法:

    query.sort_by(|a| a.winner_id == @current_user.id)
    

    如果您要处理更大的查询,那么您可能应该坚持使用 SQL。

    【讨论】:

    • 在这个我收到以下错误:{比较 FalseClass 与 true 失败}。另外不要忘记你需要括号而不是括号!
    • 它可能需要被强制转换为一个数字,我想这是承认 运算符的东西。
    • 老实说,我没有对错误进行太多调查,因为从长远来看(如果应用程序可以扩展,哈!)解决方案不是最佳的 - 我很确定有解决方案错误,当然。感谢您的跟进!
    【解决方案3】:

    这可以使用Arel 实现,而无需编写任何原始 SQL!

    matches = Match.arel_table
    Match
      .order(matches[:winner_id].eq(@current_user.id).desc)
      .order(created_at: :desc)
    

    在没有任何安全警告的情况下使用 Postgres 12 / Rails 6.0.3 为我工作

    【讨论】:

      【解决方案4】:

      我会构建一个查询,然后在它构建后执行它(主要是因为你可能没有@current_user。所以,像这样:

      query = Match.scoped
      
      query = query.order("winner_id == ?", @current_user.id) if @current_user.present?
      
      query = query.order("created_at")
      
      @results = query.all
      

      【讨论】:

      • 你知道,这正是我在发布之前尝试过的(不要担心@current_user,因为该站点在 before_filter 中进行身份验证)并且我收到此错误:PG::SyntaxError: ERROR: "," LINE 1: ...nfirmed, play_date DESC, created_at DESC, Winner_id == ?, 34 ^ : SELECT "matches".* FROM "matches" ORDER BY Confirmed, play_date DESC, created_at DESC,获胜者id == ?, 34
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-09
      • 2014-06-17
      • 1970-01-01
      相关资源
      最近更新 更多