{"record":{"id":"1ef60de8e6679ce0","repo":"activerecord-hackery/ransack","slug":"first-argument-must-be-a-ransack-search","errorCode":null,"errorMessage":"First argument must be a Ransack::Search!","messagePattern":"First argument must be a Ransack::Search!","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"lib/ransack/helpers/form_helper.rb","lineNumber":68,"sourceCode":"        html_options = build_html_options(search, options, method).merge(turbo_options)\n        finalize_form_options(options, html_options)\n        form_for(record, options, &proc)\n      end\n\n      # +sort_link+\n      #\n      #   <%= sort_link(@q, :name, [:name, 'kind ASC'], 'Player Name') %>\n      #\n      #   You can also use a block:\n      #\n      #   <%= sort_link(@q, :name, [:name, 'kind ASC']) do %>\n      #     <strong>Player Name</strong>\n      #   <% end %>\n      #\n      def sort_link(search_object, attribute, *args, &block)\n        search, routing_proxy = extract_search_and_routing_proxy(search_object)\n        unless Search === search\n          raise TypeError, 'First argument must be a Ransack::Search!'\n        end\n        args[args.first.is_a?(Array) ? 1 : 0, 0] = capture(&block) if block_given?\n        s = SortLink.new(search, attribute, args, params, &block)\n        link_to(s.name, url(routing_proxy, s.url_options), s.html_options(args))\n      end\n\n      # +sort_url+\n      # <%= sort_url(@q, :created_at, default_order: :desc) %>\n      #\n      def sort_url(search_object, attribute, *args)\n        search, routing_proxy = extract_search_and_routing_proxy(search_object)\n        unless Search === search\n          raise TypeError, 'First argument must be a Ransack::Search!'\n        end\n        s = SortLink.new(search, attribute, args, params)\n        url(routing_proxy, s.url_options)\n      end\n","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/activerecord-hackery/ransack/blob/e82f6bab3956c5597e7debbefa218d9e94e58ceb/lib/ransack/helpers/form_helper.rb#L50-L86","documentation":"The sort_link view helper raises a TypeError when, after unwrapping an optional [routing_proxy, search] array, its first effective argument is not a Ransack::Search instance. sort_link reads the search's context (klass, sorts) to build the column-header link, so any other object (model instance, relation, nil) is rejected up front.","triggerScenarios":"sort_link(@person, :name) where @person is a record or relation; sort_link(params[:q], :name) (raw params hash); forgetting @q = Person.ransack(params[:q]) in the controller; passing a routing-proxy array whose second element is not the search, e.g. [admin_proxy, @person].","commonSituations":"New Ransack installations where the controller still passes a relation to the view; refactoring views and dropping the @q assignment; using sort_link in a partial that receives the wrong local variable; passing an array form incorrectly for engines/admin namespaces.","solutions":["Set @q = Person.ransack(params[:q]) in the controller and call sort_link(@q, :name)","If you use the array form for routing proxies, keep the search object as the second element: sort_link([:admin, @q], :name)","If @q can be nil (e.g. non-GET renders), initialize a default: @q ||= Person.ransack"],"exampleFix":"# controller\n# before\ndef index\n  @people = Person.all\nend\n\n# after\ndef index\n  @q = Person.ransack(params[:q])\n  @people = @q.result\nend\n\n# view (unchanged)\n<%= sort_link(@q, :name, 'Person Name') %>","handlingStrategy":"type-guard","validationCode":"# in the controller, guarantee the instance var exists before render:\n@q = Person.ransack(params[:q]) if @q.nil?","typeGuard":"def ransack_search?(obj)\n  obj.is_a?(Ransack::Search)\nend\n\n# view:\n<%= sort_link(@q, :name) if ransack_search?(@q) %>","tryCatchPattern":null,"preventionTips":["Always assign @q in the controller action that renders the sortable table","Name the variable @q consistently — sort_link(@people, ...) is the classic copy-paste mistake","For the array/proxy form, verify the LAST element is the search: [:admin, @q]"],"tags":["ruby","rails","ransack","sort-link","views","typeerror"],"backgroundTag":"invalid-argument-type","analyzedSha":"e82f6bab3956c5597e7debbefa218d9e94e58ceb","analyzedAt":"2026-08-21T19:30:23.639Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}