From a24a47d854f8b64d21c4f830062f1a026c605b0f Mon Sep 17 00:00:00 2001 From: ryoya-kobayashi Date: Tue, 2 Jun 2026 00:14:13 +0900 Subject: [PATCH] Make search_form_for / _with / turbo_search_form_for honour per-search search_key (#1118) `sort_link` and `sort_url` already read the search key from the search's context (`search.context.search_key`). The form-building helpers were instead falling back to the global `Ransack.options[:search_key]` in `finalize_form_options` / `finalize_form_with_options`, which meant that passing `search_key:` to `Model.ransack` was silently ignored: inputs were emitted under `q[...]` regardless of the override. The two private finalisers now take the `search` object and use `search.context.search_key`. `Context#search_key` already falls back to `Ransack.options[:search_key]` when no per-search override is given, so the global default continues to apply for the unconfigured case. --- lib/ransack/helpers/form_helper.rb | 14 ++++++------- spec/ransack/helpers/form_helper_spec.rb | 26 ++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/lib/ransack/helpers/form_helper.rb b/lib/ransack/helpers/form_helper.rb index 90665da8..966eaf60 100644 --- a/lib/ransack/helpers/form_helper.rb +++ b/lib/ransack/helpers/form_helper.rb @@ -10,7 +10,7 @@ def search_form_for(record, options = {}, &proc) search = extract_search_and_set_url(record, options, 'search_form_for') options[:html] ||= {} html_options = build_html_options(search, options, :get) - finalize_form_options(options, html_options) + finalize_form_options(search, options, html_options) form_for(record, options, &proc) end @@ -30,7 +30,7 @@ def search_form_with(record_or_options = {}, options = {}, &proc) search = extract_search_and_set_url(record, options, 'search_form_with') options[:html] ||= {} html_options = build_html_options(search, options, :get) - finalize_form_with_options(options, html_options) + finalize_form_with_options(search, options, html_options) form_with(model: search, **options, &proc) end @@ -48,7 +48,7 @@ def turbo_search_form_for(record, options = {}, &proc) turbo_options = build_turbo_options(options) method = options.delete(:method) || :post html_options = build_html_options(search, options, method).merge(turbo_options) - finalize_form_options(options, html_options) + finalize_form_options(search, options, html_options) form_for(record, options, &proc) end @@ -122,14 +122,14 @@ def build_html_options(search, options, method) } end - def finalize_form_options(options, html_options) - options[:as] ||= Ransack.options[:search_key] + def finalize_form_options(search, options, html_options) + options[:as] ||= search.context.search_key options[:html].reverse_merge!(html_options) options[:builder] ||= FormBuilder end - def finalize_form_with_options(options, html_options) - options[:scope] ||= Ransack.options[:search_key] + def finalize_form_with_options(search, options, html_options) + options[:scope] ||= search.context.search_key options[:html].reverse_merge!(html_options) options[:builder] ||= FormBuilder end diff --git a/spec/ransack/helpers/form_helper_spec.rb b/spec/ransack/helpers/form_helper_spec.rb index f0b78d40..693a700e 100644 --- a/spec/ransack/helpers/form_helper_spec.rb +++ b/spec/ransack/helpers/form_helper_spec.rb @@ -859,6 +859,21 @@ module Helpers it { should match /example_name_eq/ } end + # Regression test for https://github.com/activerecord-hackery/ransack/issues/1118 + # When a per-search `search_key:` option is passed to `Person.ransack`, + # `search_form_for` should honour it instead of falling back to the + # global `Ransack.options[:search_key]`. `sort_link` and `sort_url` + # already read this from the search's context. + describe '#search_form_for with per-search search_key' do + subject { + @controller.view_context + .search_form_for(Person.ransack({}, search_key: :people_search)) { |f| + f.text_field :name_eq + } + } + it { should match /people_search_name_eq/ } + end + describe '#search_form_with with default format' do subject { @controller.view_context .search_form_with(model: Person.ransack) {} } @@ -903,6 +918,17 @@ module Helpers it { should match /example\[name_eq\]/ } end + # Regression test for https://github.com/activerecord-hackery/ransack/issues/1118 + describe '#search_form_with with per-search search_key' do + subject { + @controller.view_context + .search_form_with(model: Person.ransack({}, search_key: :people_search)) { |f| + f.text_field :name_eq + } + } + it { should match /people_search\[name_eq\]/ } + end + describe '#search_form_with without Ransack::Search object' do it 'raises ArgumentError' do expect {