このコミットが含まれているのは:
+76
-25
@@ -4,7 +4,9 @@
|
||||
|
||||
These rules apply to work under `backend/`.
|
||||
|
||||
This is a Rails API app using Active Record, RSpec, request specs, service objects, representation classes, and version tables for post/tag/wiki history.
|
||||
This is a Rails API app using Active Record, RSpec, request specs,
|
||||
service objects, representation classes, and version tables for post/tag/wiki
|
||||
history.
|
||||
|
||||
## Commands
|
||||
|
||||
@@ -50,14 +52,16 @@ If a command cannot be run or fails, report the exact command and failure.
|
||||
- `app/controllers`: API controllers.
|
||||
- `app/models`: Active Record models and concerns.
|
||||
- `app/representations`: JSON response shaping.
|
||||
- `app/services`: domain services such as version recorders, wiki commit, YouTube sync, and similarity calculation.
|
||||
- `app/services`: domain services such as version recorders, wiki commit,
|
||||
YouTube sync, and similarity calculation.
|
||||
- `config/routes.rb`: public API routes.
|
||||
- `db/migrate`: migrations.
|
||||
- `db/schema.rb`: schema snapshot.
|
||||
- `lib/tasks`: custom Rake tasks.
|
||||
- `spec`: RSpec tests.
|
||||
|
||||
Before changing behavior, inspect the matching route, controller, model, service, representation, and spec.
|
||||
Before changing behavior, inspect the matching route, controller, model,
|
||||
service, representation, and spec.
|
||||
|
||||
## Ruby style
|
||||
|
||||
@@ -65,17 +69,29 @@ Before changing behavior, inspect the matching route, controller, model, service
|
||||
- Use single quotes unless interpolation or escaping makes double quotes better.
|
||||
- Do not put a space before Ruby method-call parentheses.
|
||||
- Do not use `%w` or `%i` in new Ruby code.
|
||||
- Never write a Ruby line longer than 99 characters.
|
||||
- Aim to keep Ruby lines within 79 characters where practical.
|
||||
- For small Ruby method definitions that take keyword arguments, match the
|
||||
local no-parentheses style when nearby code uses it.
|
||||
- For multi-line Ruby hashes and keyword constructors, prefer a readable
|
||||
vertical shape with the opening brace on its own line.
|
||||
- Put one logical field per line when the expression would otherwise
|
||||
become dense.
|
||||
- Keep comments short and useful; avoid narrating obvious code.
|
||||
- Do not add production dependencies without approval.
|
||||
|
||||
## Authentication and authorization
|
||||
|
||||
- Authentication is handled through the `X-Transfer-Code` header in `ApplicationController#authenticate_user`.
|
||||
- Authentication is handled through the `X-Transfer-Code` header in
|
||||
`ApplicationController#authenticate_user`.
|
||||
- `current_user` is set by looking up `User.inheritance_code`.
|
||||
- Do not bypass or weaken the `X-Transfer-Code` flow unless the task explicitly changes authentication.
|
||||
- Unauthenticated write actions should return `:unauthorized` consistently with existing controllers.
|
||||
- Do not bypass or weaken the `X-Transfer-Code` flow unless the task
|
||||
explicitly changes authentication.
|
||||
- Unauthenticated write actions should return `:unauthorized` consistently
|
||||
with existing controllers.
|
||||
- Role checks use `User` enum roles: `guest`, `member`, and `admin`.
|
||||
- Use `current_user.gte_member?` for member-or-admin write permissions where existing controllers do so.
|
||||
- Use `current_user.gte_member?` for member-or-admin write permissions where
|
||||
existing controllers do so.
|
||||
- Use `current_user.admin?` only for admin-only paths, such as tag child relationship changes.
|
||||
- Do not replace role checks with looser presence checks.
|
||||
|
||||
@@ -88,7 +104,8 @@ Before changing behavior, inspect the matching route, controller, model, service
|
||||
- User and IP bans use `banned_at`, not a boolean `banned` column.
|
||||
- `User#banned?` and `IpAddress#banned?` check `banned_at.present?`.
|
||||
- Do not weaken BAN or IP BAN behavior.
|
||||
- If changing request authentication or controller before actions, add or update request specs covering banned users and banned IP addresses.
|
||||
- If changing request authentication or controller before actions, add or
|
||||
update request specs covering banned users and banned IP addresses.
|
||||
|
||||
## RSpec
|
||||
|
||||
@@ -99,49 +116,83 @@ Before changing behavior, inspect the matching route, controller, model, service
|
||||
- Put Rake task coverage under `spec/tasks`.
|
||||
- `spec/rails_helper.rb` loads `spec/support/**/*.rb`.
|
||||
- Request specs include `AuthHelper` and `JsonHelper`.
|
||||
- `AuthHelper#sign_in_as(user)` stubs `ApplicationController#current_user`; use it when matching existing request spec style.
|
||||
- Add or update request specs for API behavior changes, especially status codes, permissions, response shape, and version conflict behavior.
|
||||
- `AuthHelper#sign_in_as(user)` stubs
|
||||
`ApplicationController#current_user`; use it when matching existing
|
||||
request spec style.
|
||||
- Add or update request specs for API behavior changes, especially status
|
||||
codes, permissions, response shape, and version conflict behavior.
|
||||
|
||||
## Migrations
|
||||
|
||||
- Keep migrations and `db/schema.rb` consistent.
|
||||
- Use reversible migrations where practical; otherwise define explicit `up` and `down`.
|
||||
- For data backfills inside migrations, follow the existing pattern of defining migration-local `ActiveRecord::Base` classes with `self.table_name`.
|
||||
- For data backfills inside migrations, follow the existing pattern of
|
||||
defining migration-local `ActiveRecord::Base` classes with
|
||||
`self.table_name`.
|
||||
- Preserve existing indexes, foreign keys, check constraints, and null constraints.
|
||||
- Be careful with MySQL-specific options already present in migrations, such as `after:`.
|
||||
- Do not edit old migrations just to change current behavior unless explicitly requested; add a new migration.
|
||||
- Do not edit old migrations just to change current behavior unless
|
||||
explicitly requested; add a new migration.
|
||||
|
||||
## Version tables
|
||||
|
||||
- Versioned records include posts, tags, nico tags, and wiki pages.
|
||||
- Current records have `version_no`; version tables have positive `version_no` with unique indexes scoped to the parent record.
|
||||
- Current records have `version_no`; version tables have positive
|
||||
`version_no` with unique indexes scoped to the parent record.
|
||||
- Version event types are `create`, `update`, `discard`, and `restore`.
|
||||
- Version rows are readonly through the `VersionRecord` concern.
|
||||
- Use the existing recorder services instead of manually inserting version rows in application code:
|
||||
- Use the existing recorder services instead of manually inserting version
|
||||
rows in application code:
|
||||
- `PostVersionRecorder`
|
||||
- `TagVersionRecorder`
|
||||
- `NicoTagVersionRecorder`
|
||||
- `WikiVersionRecorder`
|
||||
- `TagVersioning`
|
||||
- `VersionRecorder` locks the current record, validates sequence consistency, skips unchanged update snapshots, creates the next version row, and updates the record `version_no`.
|
||||
- `VersionRecorder` locks the current record, validates sequence consistency,
|
||||
skips unchanged update snapshots, creates the next version row, and updates
|
||||
the record `version_no`.
|
||||
- Do not update versioned records without considering whether a version snapshot must be created.
|
||||
- For optimistic concurrency paths, preserve `base_version_no`, `force`, and `merge` semantics and cover conflicts in request specs.
|
||||
- For optimistic concurrency paths, preserve `base_version_no`, `force`, and
|
||||
`merge` semantics and cover conflicts in request specs.
|
||||
|
||||
## Domain cautions
|
||||
|
||||
- Posts have tag snapshots, parent post implications, original-created ranges, viewed state, and version conflict behavior.
|
||||
- Tags have canonical names, aliases through `TagName`, categories, parent implications, discard behavior, and version snapshots.
|
||||
- Nico tags have separate relation/version behavior; do not treat them like normal editable tags without checking existing code.
|
||||
- Wiki pages involve page content, revisions/history, version rows, title/tag-name behavior, and diff/restore paths.
|
||||
- Materials, theatres, and comments have user and permission checks; inspect the controller before changing them.
|
||||
- Posts have tag snapshots, parent post implications, original-created ranges,
|
||||
viewed state, and version conflict behavior.
|
||||
- Tags have canonical names, aliases through `TagName`, categories, parent
|
||||
implications, discard behavior, and version snapshots.
|
||||
- Nico tags have separate relation/version behavior; do not treat them like
|
||||
normal editable tags without checking existing code.
|
||||
- Wiki pages involve page content, revisions/history, version rows,
|
||||
title/tag-name behavior, and diff/restore paths.
|
||||
- Materials, theatres, and comments have user and permission checks; inspect
|
||||
the controller before changing them.
|
||||
|
||||
## API responses
|
||||
|
||||
- Use representation classes under `app/representations` when existing endpoints do.
|
||||
- Keep response keys consistent with existing JSON contracts; frontend code expects camelCase conversion client-side, while Rails params and JSON keys are generally snake_case.
|
||||
- Preserve existing HTTP status conventions: `:unauthorized` for no user, `:forbidden` for insufficient role or banned user, `:not_found` for missing records, and `:unprocessable_entity` for validation failures.
|
||||
- Keep response keys consistent with existing JSON contracts.
|
||||
- Frontend code expects camelCase conversion client-side, while Rails params
|
||||
and JSON keys are generally snake_case.
|
||||
- Preserve existing HTTP status conventions:
|
||||
`:unauthorized` for no user, `:forbidden` for insufficient role or banned
|
||||
user, `:not_found` for missing records, and `:unprocessable_entity` for
|
||||
validation failures.
|
||||
- For diagnostic or internal helper JSON, prefer a deliberately light response
|
||||
shape over full representation classes when callers only need identifiers,
|
||||
labels, URLs, or weights.
|
||||
|
||||
## Active Record performance
|
||||
|
||||
- When a controller action serializes nested associations, preload the
|
||||
associations it will touch instead of allowing N+1 queries.
|
||||
- When an association may already be preloaded, prefer loaded-association
|
||||
checks that reuse the preloaded data without losing the efficient database
|
||||
path.
|
||||
|
||||
## Files to avoid in routine work
|
||||
|
||||
- Do not inspect or edit `tmp/`, `log/`, `storage/`, `vendor/`, or dependency directories unless explicitly needed.
|
||||
- Do not modify generated schema or migration output without the corresponding migration when schema changes are made.
|
||||
- Do not inspect or edit `tmp/`, `log/`, `storage/`, `vendor/`, or dependency
|
||||
directories unless explicitly needed.
|
||||
- Do not modify generated schema or migration output without the corresponding
|
||||
migration when schema changes are made.
|
||||
|
||||
新しい課題から参照
ユーザをブロックする