From 9a8d5cb347911367785eba22c526be6e69f7b7bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20L=C3=B3pez=20Prat?= Date: Tue, 15 Sep 2026 14:24:48 +0900 Subject: [PATCH] fix: answer HTML from the show action by default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `show` declared its JSON format before its HTML one, so a request carrying no Accept header — curl, a bare fetch(), most HTTP libraries — arrived as */*, matched every registered type, and got JSON, while every other action in the engine answered HTML. The JSON branch also renders the record whole, including columns the model config hides from the show view. Clients sending an explicit Accept header or the .json extension are unaffected. --- docs/UPGRADING.md | 21 +++++++++++++++++++++ lib/rails_admin_next/config/actions/show.rb | 4 +++- spec/integration/actions/show_spec.rb | 9 +++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/docs/UPGRADING.md b/docs/UPGRADING.md index 0678921b15..6adbf27c61 100644 --- a/docs/UPGRADING.md +++ b/docs/UPGRADING.md @@ -398,6 +398,27 @@ end Note the block: a bare `inverse_of nil` reads the option rather than setting it. +## The show action answers HTML by default + +`show` used to declare its JSON format before its HTML one, so a request carrying no +`Accept` header — `curl`, a bare `fetch()`, most HTTP client libraries — arrived as +`*/*`, matched every registered type, and got JSON back. Every other action answered +HTML for the same request. + +It now declares HTML first. A client that explicitly sends `Accept: application/json`, +or requests the `.json` extension, is unaffected. + +If you have a script relying on the unheadered JSON response, send the header or use +`.json`: + +```bash +curl -H 'Accept: application/json' https://example.com/admin/player/1 +curl https://example.com/admin/player/1.json +``` + +Note that the JSON branch renders the whole record, including columns the model config +hides from the show view. + ## Dropped support These are intentionally gone — migrate off them before upgrading: diff --git a/lib/rails_admin_next/config/actions/show.rb b/lib/rails_admin_next/config/actions/show.rb index b0e0d036d4..ab1f840149 100644 --- a/lib/rails_admin_next/config/actions/show.rb +++ b/lib/rails_admin_next/config/actions/show.rb @@ -20,9 +20,11 @@ class Show < RailsAdminNext::Config::Actions::Base register_instance_option :controller do proc do + # HTML first: an Accept-less request arrives as */*, which matches every + # registered type, so Rails falls back to whichever is declared first. respond_to do |format| - format.json { render json: @object } format.html { render @action.template_name } + format.json { render json: @object } end end end diff --git a/spec/integration/actions/show_spec.rb b/spec/integration/actions/show_spec.rb index 3b0bf811db..6471c37530 100644 --- a/spec/integration/actions/show_spec.rb +++ b/spec/integration/actions/show_spec.rb @@ -47,6 +47,15 @@ end end + context "with no explicit format" do + it "responds with HTML" do + page.driver.options[:headers] = {"HTTP_ACCEPT" => "*/*"} + visit show_path(model_name: "team", id: team.id) + + expect(Mime::Type.parse(response_headers["Content-Type"]).first).to be_html + end + end + context "when compact_show_view is enabled" do it "hides nil fields in show view by default" do visit show_path(model_name: "team", id: team.id)