{"record":{"id":"027ce5035091733a","repo":"activerecord-hackery/ransack","slug":"sort-direction-must-be-called-inside-a-search-form","errorCode":null,"errorMessage":"sort_direction must be called inside a search FormBuilder!","messagePattern":"sort_direction must be called inside a search FormBuilder!","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/ransack/helpers/form_builder.rb","lineNumber":72,"sourceCode":"        bases = [''.freeze].freeze + association_array(options[:associations])\n        if bases.size > 1\n          collection = attribute_collection_for_bases(action, bases)\n          object.name ||= default if can_use_default?(\n            default, :name, mapped_values(collection.flatten(2))\n            )\n          template_grouped_collection_select(collection, options, html_options)\n        else\n          collection = collection_for_base(action, bases.first)\n          object.name ||= default if can_use_default?(\n            default, :name, mapped_values(collection)\n            )\n          template_collection_select(:name, collection, options, html_options)\n        end\n      end\n\n      def sort_direction_select(options = {}, html_options = {})\n        unless object.respond_to?(:context)\n          raise ArgumentError,\n          formbuilder_error_message('sort_direction'.freeze)\n        end\n        template_collection_select(:dir, sort_array, options, html_options)\n      end\n\n      def sort_select(options = {}, html_options = {})\n        attribute_select(options, html_options, 'sort'.freeze) +\n        sort_direction_select(options, html_options)\n      end\n\n      def sort_fields(*args, &block)\n        search_fields(:s, args, block)\n      end\n\n      def sort_link(attribute, *args)\n        @template.sort_link @object, attribute, *args\n      end\n","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/activerecord-hackery/ransack/blob/e82f6bab3956c5597e7debbefa218d9e94e58ceb/lib/ransack/helpers/form_builder.rb#L54-L90","documentation":"Ransack's FormBuilder#sort_direction_select (called directly or via sort_select/sort_fields) raises this ArgumentError when the form builder's object does not respond to #context — i.e. the form was not built around a Ransack::Search object. The guard exists because the helper reads sortable attributes from the search's context to populate the asc/desc dropdown.","triggerScenarios":"<%= form_for @person do |f| %> <%= f.sort_direction_select %> or f.sort_select inside a plain model-bound form; also when a custom builder wraps Ransack's FormBuilder but the object passed in is a model instance.","commonSituations":"Reusing sort-select snippets from Ransack docs inside existing simple_form/form_with forms; forgetting @q = Model.ransack(params[:q]) in the controller action that renders the form.","solutions":["Build @q = Person.ransack(params[:q]) in the controller","Render the form with search_form_for @q so the builder binds to the search object","For plain forms, hand-roll the direction select: f.select :dir, [['asc', 'asc'], ['desc', 'desc']]"],"exampleFix":"<!-- before -->\n<%= form_for @person do |f| %>\n  <%= f.sort_direction_select %>\n<% end %>\n\n<!-- after -->\n<%= search_form_for @q do |f| %>\n  <%= f.sort_direction_select %>\n<% end %>","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"def search_bound_form?(builder)\n  builder.object.respond_to?(:context)\nend","tryCatchPattern":null,"preventionTips":["sort_direction_select and sort_select belong exclusively in search_form_for forms","Ensure every view partial using sort_* helpers receives the @q search object, not a record","Prefer f.sort_select (it composes attribute_select + direction) inside search forms"],"tags":["ruby","rails","ransack","formbuilder","sorting","actionview"],"backgroundTag":"form-builder-wrong-object","analyzedSha":"e82f6bab3956c5597e7debbefa218d9e94e58ceb","analyzedAt":"2026-08-21T19:30:23.639Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}