Skip to content

Make story author a direct person, separate from creator#1562

Open
maebeale wants to merge 1 commit into
mainfrom
maebeale/story-author-current-person
Open

Make story author a direct person, separate from creator#1562
maebeale wants to merge 1 commit into
mainfrom
maebeale/story-author-current-person

Conversation

@maebeale

@maebeale maebeale commented Jun 5, 2026

Copy link
Copy Markdown
Collaborator

What is the goal of this PR and why is this important?

  • Author credit on stories and story ideas was derived indirectly from the creating user's linked person, conflating "who wrote this" with "who entered it."
  • This makes author a first-class Person association so authorship is attributed independently of the account that created the record, while created_by/updated_by still capture the system user.

How did you approach the change?

  • Added a nullable author_id (FK to people) on stories and story_ideas, backfilled from each record's creator's person so existing credits are preserved.
  • AuthorCreditable now credits a direct author via a credited_person seam; workshop includers keep deriving it from the creator (no behavior change for them).
  • Story credit preference now defaults from the author's display preference (overridable per story); reworked the story form with a Person author picker (creator is read-only), person dropdowns that show email only to disambiguate duplicate names, and a linked "From Story Idea #N by …" provenance line.

UI Testing Checklist

  • Story form: author picker lists people; selecting one sets the credit shown on the story.
  • Author/facilitator dropdowns show just the name, adding the email only when two people share a name.
  • Promoting from a story idea carries the author + preference and shows the linked "From Story Idea #N by …" line.
  • Author credit preference pre-fills from the author's display preference and remains editable.

Anything else to add?

  • author is optional: rows whose creator has no linked person stay null and fall back to "Anonymous." Migration is reversible and backfill is idempotent.

Author credit on stories and story ideas was derived indirectly from the
creating user's linked person, conflating "who wrote this" with "who entered
it." This makes author a first-class Person association so authorship can be
attributed independently of the account that created the record, while
created_by/updated_by still capture the system user.

- Add nullable author_id (FK to people) to stories and story_ideas, backfilled
  from each record's creator's person to preserve existing credits
- AuthorCreditable now credits a direct author via a credited_person seam;
  workshop includers keep deriving it from the creator
- Story credit preference defaults from the author's display preference,
  overridable per story
- Rework the story form: a Person author picker (created_by becomes read-only),
  person dropdowns show email only to disambiguate duplicate names, and a
  linked "From Story Idea #N by ..." provenance line

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 5, 2026 15:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR makes “author” a first-class Person association on Story and StoryIdea, separating authorship from the account that created/updated the record while keeping created_by/updated_by for audit.

Changes:

  • Add nullable author_id FKs for stories and story ideas, and route author crediting through a credited_person seam.
  • Update story/story idea UI to display/select an author (Person) and improve person dropdown labels (email only for duplicate names).
  • Add/adjust factories and specs to cover the new author behavior and defaulting credit preference from the author.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
spec/support/shared_examples/author_creditable.rb Updates shared examples to test direct-author vs creator-derived crediting.
spec/requests/stories_spec.rb Ensures request specs create stories with explicit author.
spec/models/story_spec.rb Adds coverage for defaulting credit preference from the author.
spec/helpers/person_helper_spec.rb Adds tests for new person select option labeling behavior.
spec/factories/story_ideas.rb Adds author association to story idea factory.
spec/factories/stories.rb Adds author association to story factory.
db/schema.rb Captures schema changes for new author_id columns/indexes/FKs (also includes unrelated constraint/index diffs).
db/migrate/20260605120000_add_author_to_stories_and_story_ideas.rb Introduces author_id references + backfill from creator’s person.
app/views/story_ideas/show.html.erb Switches “Story by” display to the direct author.
app/views/stories/show.html.erb Switches “Story by” link to point at the direct author.
app/views/stories/_story_results.html.erb Updates index table “Author” column to use story author.
app/views/stories/_form.html.erb Adds author picker + reorganizes credit preference UI and story-idea provenance display.
app/models/story.rb Adds belongs_to :author, credited-person override, and preference defaulting callback.
app/models/story_idea.rb Adds belongs_to :author and credited-person override.
app/models/concerns/author_creditable.rb Uses credited_person seam (defaulting to creator’s person).
app/helpers/person_helper.rb Adds person_select_options to disambiguate duplicate names by email.
app/controllers/story_ideas_controller.rb Sets author from current_user.person on create.
app/controllers/stories_controller.rb Includes author in index scope, sets created_by on create, and carries author forward from story ideas.

@@ -0,0 +1,32 @@
class AddAuthorToStoriesAndStoryIdeas < ActiveRecord::Migration[7.2]
Comment on lines +12 to +16
UPDATE stories
JOIN users ON users.id = stories.created_by_id
SET stories.author_id = users.person_id
WHERE users.person_id IS NOT NULL
SQL
Comment on lines +19 to +23
UPDATE story_ideas
JOIN users ON users.id = story_ideas.created_by_id
SET story_ideas.author_id = users.person_id
WHERE users.person_id IS NOT NULL
SQL
Comment thread app/models/story.rb
Comment on lines +101 to +103
def default_author_credit_preference
self.author_credit_preference ||= author&.display_name_preference
end
Comment on lines 63 to 66
def create
@story = Story.new(story_params.except(:category_ids, :sector_ids))
@story.created_by = current_user
authorize! @story
class: "inline-block px-3 py-1 rounded-md text-sm font-medium #{DomainTheme.bg_class_for(:people, intensity: 100)} #{DomainTheme.text_class_for(:people)} #{DomainTheme.bg_class_for(:people, intensity: 100, hover: true)}" %>
<% else %>
<%= @story_idea.created_by&.name || "—" %>
<%= @story_idea.author&.full_name || "—" %>
</td>

<td class="px-4 py-2 text-sm text-gray-800"><%= story.created_by.name %></td>
<td class="px-4 py-2 text-sm text-gray-800"><%= story.author&.full_name || "—" %></td>
Comment on lines +276 to +280
<% if story_idea.author %>
<%= link_to story_idea.author_credit, person_path(story_idea.author), class: "font-medium text-gray-800 underline" %>
<% else %>
<span class="font-medium text-gray-800"><%= story_idea.author_credit %></span>
<% end %>
Comment thread db/schema.rb
Comment on lines 1338 to 1341

add_foreign_key "action_text_mentions", "action_text_rich_texts"
add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id"
add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id"
add_foreign_key "affiliations", "organizations"
add_foreign_key "affiliations", "organizations", column: "organization_agency_id"
Comment on lines +258 to +262
collection: AuthorCreditable::ADMIN_FORM_OPTIONS,
prompt: "Select a preference",
selected: f.object.author_credit_preference || story_idea&.author_credit_preference || f.object.author&.display_name_preference,
label: "Author credit preference",
hint: "Defaults to the author's name display preference; controls how their name is shown",
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants