Use when building or reviewing GraphQL APIs in Rails with graphql-ruby — must follow the TDD gates by writing a failing spec in spec/graphql/ using AppSchema.execute rather than HTTP controller dispatch, define arguments/return types without leaking internal model names (use connection_type for pagination), implement resolver/mutation classes that delegate to services, prevent N+1 queries by using and priming the dataloader on association loads, and ensure mutations return result and errors shapes on failure. Trigger words: graphql, graphql-ruby, resolver, mutation, dataloader, schema.
التثبيت
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
Use when building or reviewing GraphQL APIs in Rails with graphql-ruby — must follow the TDD gates by writing a failing spec in spec/graphql/ using AppSchema.execute rather than HTTP controller dispatch, define arguments/return types without leaking internal model names (use connection_type for pagination), implement resolver/mutation classes that delegate to services, prevent N+1 queries by using and priming the dataloader on association loads, and ensure mutations return result and errors shapes on failure. Trigger words: graphql, graphql-ruby, resolver, mutation, dataloader, schema.
metadata
{"version":"1.0.0","user-invocable":"true"}
Implement GraphQL
Use this skill when designing, implementing, or reviewing GraphQL APIs in a Rails application with the graphql-ruby gem.
Core Process
DO NOT proceed to step 3 before step 1 is written and failing.
SPEC: Write failing spec (happy path + auth + validation error case) — see TESTING.md. Use AppSchema.execute in spec/graphql/. Never use HTTP controller dispatch for GraphQL specs.
TYPE: Define arguments and return types. Use connection_type for pagination shapes. Do not leak internal model names.
IMPLEMENT: Create resolver/mutation class delegating to a service object. Use dedicated classes instead of inline field blocks.
N+1 CHECK: Use dataloader on every association load. For list resolvers, prime the dataloader with the records returned by the relation before fields resolve associated objects. Use bullet and db-query-matchers in specs.
# ✅ batches loads across all recordsdefbuyer
dataloader.with(Sources::RecordById, Buyer).load(object.buyer_id)
end
AUTH CHECK: Apply field-level guards where data is sensitive using Pundit or custom context guards.
field :internal_notes, String, null:truedo
guard -> (_obj, _args, ctx) { ctx[:current_user]&.admin? }
end
FINAL CHECK: Verify every item in the HARD-GATE checklist below. Ensure mutations return { result, errors } shapes on failure.
rescueActiveRecord::RecordInvalid => e
{ order:nil, errors: e.record.errors.full_messages }
RUN: Ensure the full test suite is green before PR.
HARD-GATE Checklist
Before shipping a resolver/mutation slice, ALL of the following must be confirmed: