JM: Standardize author crediting across creditable models#1940
JM: Standardize author crediting across creditable models#1940maebeale wants to merge 2 commits into
Conversation
| # by `author_credit` and, on their next save, normalized by the callback below. | ||
| # There is no data backfill. | ||
| attribute :author_credit_preference, :string, default: "full_name" | ||
| before_validation :default_author_credit_preference |
There was a problem hiding this comment.
🤖 From Claude: Blank preference normalizes to full_name here on save, so legacy rows migrate lazily through normal use — no bulk backfill. Reads are covered by author_credit's default branch.
| # anonymous, legacy free-text, or generic label that must not resolve to a | ||
| # profile. Mirrors author_credit's precedence so the linked person always | ||
| # matches the shown name. | ||
| def author_credit_person |
There was a problem hiding this comment.
🤖 From Claude: author_credit_person returns nil for anonymous and legacy free-text credits, so the byline helper never links those to a profile even when a person exists behind them.
| # Explicit LEFT JOINs (as raw SQL strings with unique aliases) reaching every | ||
| # person that can be credited, so the aliases never collide with SearchCop's | ||
| # or Rails' own joins. | ||
| def credited_person_join_sql |
There was a problem hiding this comment.
🤖 From Claude: Explicit LEFT JOIN aliases (not Rails' positional people_users guesses) so this composes with SearchCop/other joins without alias collisions; callers OR it in via an id subquery.
|
|
||
| # Orders by the credited author's name, matching `author_person` precedence: | ||
| # explicit author, then any legacy sources, then the creating user's person. | ||
| def order_by_author(direction) |
There was a problem hiding this comment.
🤖 From Claude: Sorts by first name then last name to match the default displayed credit ("First Last"). CommunityNews previously sorted last-name-first; this unifies on the visible order.
| def resolve_ids_order | ||
| return if sort.in?(%w[keywords popularity]) | ||
|
|
||
| if sort == "author" |
There was a problem hiding this comment.
🤖 From Claude: order_by_author already applied the join-based ordering, so preserve it through the id round-trip and dedupe fan-out in Ruby (DISTINCT + ORDER BY on non-selected COALESCE columns would error in MySQL).
|
@jmilljr24 there were some nuances and discrepancies for the author data handling across the different models. this consolidates most of the api into the shared concern and tries to establish more conventions. |
Good idea. I know we've run into this a number of time |
Move author display, credited-name search, and author sort into AuthorCreditable so Workshop/Resource/Story/CommunityNews/WorkshopVariation (and the *_idea models) behave identically. Credit resolves through a single precedence — explicit author person, legacy free-text/user author, creating user's person, then an overridable missing_author_label (Workshop shows "Facilitator"). Default author_credit_preference to full_name in the UI and treat a blank preference as full_name in logic, with no data backfill. Rename the legacy community_news author column to legacy_author_user_id. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Route every credited-author byline through a shared credited_author_link helper that gates the profile link on profile_is_searchable and never links an anonymous or legacy free-text credit (fixes the Workshop index leaking names for anonymous authors and Workshop/WorkshopVariation linking non-searchable profiles). Replace the bespoke author-sort SQL in the Story/CommunityNews controllers and the WorkshopSearchService author filter with the shared order_by_author / by_credited_person_name scopes, and add author search+sort to Workshop and WorkshopVariation. Cover the new behavior in helper, service, request, and shared model specs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
7990756 to
78b4b0e
Compare
🤖 suggested review level: 5 Inspect 🔬 shared credit/search/sort concern touching 5 models + 3 idea models, a column rename, view/controller rewrites, and validation changes
Makes Workshop, Resource, Story, CommunityNews, and WorkshopVariation (and the
*_ideamodels) credit, search, and sort by author identically, viaAuthorCreditable.Why
profile_is_searchablegate the others use.What
credited_author_linkhelper renders every byline, linking to the author's profile only when the credit resolves to a searchable person (never for anonymous or legacy free-text credits).author_creditprecedence: explicit author → legacy free-text/user author → creating user's person → overridablemissing_author_label(Workshop → "Facilitator").by_credited_person_namesearch +order_by_authorsort on the concern; models declare legacy sources vialegacy_author_name_columns/legacy_credited_user_columns. Retires the bespoke SQL in the Story/CommunityNews controllers andWorkshopSearchService. Adds author search+sort to Workshop and WorkshopVariation.author_credit_preferencedefaults tofull_namein the UI and is treated asfull_namewhen blank — no data backfill; blank rows normalize on their next save.community_news.user_author_id→legacy_author_user_id.Deferred (needs a yes)
workshops.full_name→legacy_author_name: it's welded into a 14-column MySQL FULLTEXT index + the admin form, i.e. the risky "legacy migration" half. The concern folds it in under its current name, so search/sort/display already work. Quick follow-up once you confirm.