如何使用 params[:sort] 值按连接表列对 ActiveRecord 集合进行排序

How to sort an ActiveRecord collection by a joined tables column using params[:sort] value

我目前正在尝试按连接的 tables 列对 ActiveRecord 集合进行升序和降序排序。我目前正在尝试以下操作:

  def index
          #sorting logic
          
          if params[:sort]
           @one_on_ones = 
            apply_scopes(OneOnOne).by_manager(current_user.id).includes(:manager, :user).order(ordering_params(params))
            .page(params[:page])
            .per(params[:per])          
          else 
            @one_on_ones = apply_scopes(OneOnOne).by_manager(current_user.id).includes(:manager, :user).page(params[:page]).per(params[:page])
          end
            
          # add filtering logic
          render_ok(
            {
              one_on_ones: OneOnOneRepresenter.basic(@one_on_ones), total: @one_on_ones
            }
          )
        end

我正在使用模块 Orderable.rb 来解析传入的参数和 return 排序依据的字段和排序依据的方向,即 :asc 或 :desc。

 def ordering_params(params)
        ordering = {}
        if params[:sort]
            sort_order = { '+' => :asc, '-' => :desc }
            sort_sign = (params[:sort] =~ /\A[+-]/) ? params[:sort].slice!(0) : '+'
            
            model = controller_name.classify.constantize

            if (model.attribute_names.include?(params[:sort]) || params[:sort] === "first_name")
               ordering[params[:sort]] = sort_order[sort_sign]
            end
        end
        return ordering 
    end

这是我收到的无列错误:

 Rswag::Specs::UnexpectedResponse:
            Expected response code '400' to match '200'
            Response body: {"errors":"PG::UndefinedColumn: ERROR:  column \"first_name\" does not exist\nLINE 1: ...s\" WHERE \"one_on_ones\".\"manager_id\" =  ORDER BY \"first_nam...\n                                                             ^\n: SELECT  \"one_on_ones\".* FROM \"one_on_ones\" WHERE \"one_on_ones\".\"manager_id\" =  ORDER BY \"first_name\" ASC LIMIT  OFFSET "}
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rswag-specs-2.3.1/lib/rswag/specs/response_validator.rb:28:in `validate_code!'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rswag-specs-2.3.1/lib/rswag/specs/response_validator.rb:18:in `validate!'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rswag-specs-2.3.1/lib/rswag/specs/example_helpers.rb:30:in `assert_response_matches_metadata'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rswag-specs-2.3.1/lib/rswag/specs/example_group_helpers.rb:95:in `block in run_test!'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:254:in `instance_exec'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:254:in `block in run'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:496:in `block in with_around_and_singleton_context_hooks'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:453:in `block in with_around_example_hooks'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:464:in `block in run'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:604:in `block in run_around_example_hooks_for'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:338:in `call'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-rails-3.5.2/lib/rspec/rails/adapters.rb:127:in `block (2 levels) in <module:MinitestLifecycleAdapter>'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:443:in `instance_exec'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:443:in `instance_exec'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:375:in `execute_with'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:606:in `block (2 levels) in run_around_example_hooks_for'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:338:in `call'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:607:in `run_around_example_hooks_for'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:464:in `run'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:453:in `with_around_example_hooks'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:496:in `with_around_and_singleton_context_hooks'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:251:in `run'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:627:in `block in run_examples'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:623:in `map'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:623:in `run_examples'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:589:in `run'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:590:in `block in run'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:590:in `map'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:590:in `run'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:590:in `block in run'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:590:in `map'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:590:in `run'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:590:in `block in run'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:590:in `map'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:590:in `run'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:113:in `block (3 levels) in run_specs'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:113:in `map'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:113:in `block (2 levels) in run_specs'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/configuration.rb:1835:in `with_suite_hooks'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:112:in `block in run_specs'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/reporter.rb:77:in `report'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:111:in `run_specs'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:87:in `run'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:71:in `run'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:45:in `invoke'
          # /Users/tomshamp/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rspec-core-3.5.4/exe/rspec:4:in `<top (required)>'
          # /Users/tomshamp/.rbenv/versions/2.6.2/bin/rspec:23:in `load'
          # /Users/tomshamp/.rbenv/versions/2.6.2/bin/rspec:23:in `<main>'
          # 
          #   Showing full backtrace because every line was filtered out.
          #   See docs for RSpec::Configuration#backtrace_exclusion_patterns and
          #   RSpec::Configuration#backtrace_inclusion_patterns for more information.

我也尝试过对以下内容进行硬编码,但没有成功:

@one_on_ones = 
            apply_scopes(OneOnOne).by_manager(current_user.id).includes(:manager, :user).order("users.first_name" => :asc)
            .page(params[:page])
            .per(params[:per]) 

每当我使用此控制器按 OneOnOne 的字段对结果进行排序时,它工作正常,但任何时候我尝试按 :user table 进行排序时它都会刹车....

非常感谢任何帮助!

我不确定您使用的 rails 是哪个版本。但在当前版本中,您应该使用 order("users.first_name ASC" 而不是散列(在我的项目中有效):

apply_scopes(OneOnOne)
  .by_manager(current_user.id)
  .includes(:manager, :user)
  .order("users.first_name ASC")
  .page(params[:page])
  .per(params[:per]) 

或致电references(:user)

apply_scopes(OneOnOne)
  .by_manager(current_user.id)
  .includes(:manager, :user)
  .references(:user)
  .order("users.first_name" => :asc)
  .page(params[:page])
  .per(params[:per]) 

请参阅 includes

的文档