From b7d1d675a3e757d50ae0305c08db284dfdde9bc2 Mon Sep 17 00:00:00 2001 From: maebeale Date: Fri, 5 Jun 2026 11:39:40 -0400 Subject: [PATCH] Show story idea body as required and humanize its error The story idea form's body field gave no visual cue it was required, and its validation error surfaced the internal "Rhino body" attribute name to public submitters. Mark the label required and relabel the attribute as "Body" so the error reads naturally. Co-Authored-By: Claude Opus 4.8 --- app/helpers/rhino_editor_helper.rb | 7 ++++--- app/views/story_ideas/_form.html.erb | 1 + config/locales/en.yml | 2 ++ spec/requests/story_ideas_spec.rb | 6 ++++++ 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/app/helpers/rhino_editor_helper.rb b/app/helpers/rhino_editor_helper.rb index ccb59c7d2..3ea93394e 100644 --- a/app/helpers/rhino_editor_helper.rb +++ b/app/helpers/rhino_editor_helper.rb @@ -1,16 +1,17 @@ module RhinoEditorHelper # custom rhino editor with stimulus controller attached to edit raw source html - def rhino_editor(form, base_attribute_name, label: nil, hint: nil) + def rhino_editor(form, base_attribute_name, label: nil, hint: nil, required: false) rhino_attr = :"rhino_#{base_attribute_name}" field_id = form.field_id(rhino_attr) value = form.object.public_send(rhino_attr) label_tag = if label.present? + label_content = required ? safe_join([ label, " ", content_tag(:abbr, "*", title: "required", class: "text-red-600 no-underline") ]) : label form.label( base_attribute_name, - label, - class: "block font-medium mb-1 text-gray-700 text optional" + label_content, + class: "block font-medium mb-1 text-gray-700 text #{required ? "required" : "optional"}" ) end diff --git a/app/views/story_ideas/_form.html.erb b/app/views/story_ideas/_form.html.erb index f96d2d17c..995ef20eb 100644 --- a/app/views/story_ideas/_form.html.erb +++ b/app/views/story_ideas/_form.html.erb @@ -111,6 +111,7 @@ <% else %>
<%= rhino_editor(f, :body, + required: true, label: "Please share details about your participant(s) (while maintaining confidentiality) and their workshop goals, including what happened during the workshop, and how creating made an impact. Include direct quotes whenever possible.", diff --git a/config/locales/en.yml b/config/locales/en.yml index 1ff330f4f..ae3ddbf99 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -33,6 +33,8 @@ en: hello: "Hello world" activerecord: attributes: + story_idea: + rhino_body: "Body" workshop_variation: rhino_body: "Details" workshop_variation_idea: diff --git a/spec/requests/story_ideas_spec.rb b/spec/requests/story_ideas_spec.rb index 7ab5bd697..3c599bb5b 100644 --- a/spec/requests/story_ideas_spec.rb +++ b/spec/requests/story_ideas_spec.rb @@ -170,6 +170,12 @@ post story_ideas_url, params: { story_idea: invalid_attributes } expect(response).to have_http_status(:unprocessable_content) end + + it "labels the body error as 'Body', not 'Rhino body'" do + post story_ideas_url, params: { story_idea: invalid_attributes } + expect(response.body).to include("Body can't be blank") + expect(response.body).not_to include("Rhino body") + end end describe "PATCH /update" do