activerecord-hackery/ransack · error · ArgumentError
sort_direction must be called inside a search FormBuilder!
Error message
sort_direction must be called inside a search FormBuilder!
What it means
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.
Source
Thrown at lib/ransack/helpers/form_builder.rb:72
bases = [''.freeze].freeze + association_array(options[:associations])
if bases.size > 1
collection = attribute_collection_for_bases(action, bases)
object.name ||= default if can_use_default?(
default, :name, mapped_values(collection.flatten(2))
)
template_grouped_collection_select(collection, options, html_options)
else
collection = collection_for_base(action, bases.first)
object.name ||= default if can_use_default?(
default, :name, mapped_values(collection)
)
template_collection_select(:name, collection, options, html_options)
end
end
def sort_direction_select(options = {}, html_options = {})
unless object.respond_to?(:context)
raise ArgumentError,
formbuilder_error_message('sort_direction'.freeze)
end
template_collection_select(:dir, sort_array, options, html_options)
end
def sort_select(options = {}, html_options = {})
attribute_select(options, html_options, 'sort'.freeze) +
sort_direction_select(options, html_options)
end
def sort_fields(*args, &block)
search_fields(:s, args, block)
end
def sort_link(attribute, *args)
@template.sort_link @object, attribute, *args
end
View on GitHub (pinned to e82f6bab39)
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']]
Example fix
<!-- before --> <%= form_for @person do |f| %> <%= f.sort_direction_select %> <% end %> <!-- after --> <%= search_form_for @q do |f| %> <%= f.sort_direction_select %> <% end %>
Defensive patterns
Strategy: type-guard
Type guard
def search_bound_form?(builder) builder.object.respond_to?(:context) end
Prevention
- 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
When it happens
Trigger: <%= 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.
Common situations: 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.
Related errors
- attribute_select must be called inside a search FormBuilder!
- Invalid argument (#{args.class}) supplied to sorts=
- #{type} cannot be converted to an ARel join type
- #{value} cannot be converted to a Class
- Don't know how to klassify #{obj}
AI-assisted analysis of activerecord-hackery/ransack@e82f6bab39 (2026-08-21).
Data as JSON: /api/errors/027ce5035091733a.
Report an issue: GitHub.