2026'da Rails GraphQL API: graphql-ruby, Abonelikler ve Mülakat Soruları
Rails 8 ve graphql-ruby ile üretim düzeyinde GraphQL API oluşturma rehberi. Şema tasarımı, mutasyonlar, ActionCable ile abonelikler ve mülakat hazırlığı.

GraphQL, esnek veri çekme gerektiren API'ler için standart tercih haline geldi ve graphql-ruby, ActiveRecord ile sıkı entegrasyon sunarak bu yeteneği Rails'e taşıyor. 2024 sonunda yayınlanan Rails 8, geliştirilmiş abonelik desteği ve N+1 önleme için daha iyi tembel yürütme sunan graphql-ruby 2.4 ile mükemmel uyum sağlıyor.
graphql-ruby gem'i eksiksiz bir GraphQL implementasyonu sunar: Ruby DSL ile şema tanımı, ActiveRecord modellerinden otomatik tip çıkarımı, toplu işleme için yerleşik DataLoader ve gerçek zamanlı abonelikler için ActionCable entegrasyonu.
Rails 8 Uygulamasında graphql-ruby Kurulumu
Gem'in oluşturucusu başlangıç şema yapısını oluşturur ve GraphQL endpoint'ini bağlar. Gem'i ekleyip kurulum oluşturucusunu çalıştırarak temel dosyaları oluşturabilirsiniz.
# Gemfile
gem 'graphql', '~> 2.4'# Terminal
bundle install
rails generate graphql:installOluşturucu, şema dosyası, temel tipler ve mutasyonlar dizini ile app/graphql/ klasörünü oluşturur. Ayrıca /graphql altında bir route ekler ve isteğe bağlı olarak geliştirme için GraphiQL'i bağlar.
# app/graphql/sharpskill_schema.rb
class SharpskillSchema < GraphQL::Schema
mutation(Types::MutationType)
query(Types::QueryType)
subscription(Types::SubscriptionType)
# N+1 önleme için yerleşik DataLoader kullanımı
use GraphQL::Dataloader
# Abonelikler için gerekli
use GraphQL::Subscriptions::ActionCableSubscriptions
endŞema dosyası giriş noktası olarak görev yapar. Hangi tiplerin sorguları, mutasyonları ve abonelikleri işleyeceğini bildirir ve DataLoader gibi middleware'leri kaydeder.
Rails Modelleri için Tipler ve Çözücüler Tanımlama
API'de görünen her ActiveRecord modeli için karşılık gelen bir GraphQL tipi gerekir. Tip, hangi alanların açığa çıkarıldığını ve nasıl çözüldüğünü tanımlar.
# app/graphql/types/user_type.rb
module Types
class UserType < Types::BaseObject
field :id, ID, null: false
field :email, String, null: false
field :created_at, GraphQL::Types::ISO8601DateTime, null: false
# DataLoader ile otomatik toplu işleme yapan ilişki
field :posts, [Types::PostType], null: false
def posts
dataloader.with(Sources::ActiveRecordCollection, Post, :user_id).load(object.id)
end
end
enddataloader.with çağrısı birden fazla post çekme işlemini tek bir SQL sorgusunda toplar. DataLoader olmadan, 50 kullanıcının postlarıyla birlikte istendiği bir sorgu 51 sorgu çalıştırır. DataLoader ile sadece 2 sorgu çalışır.
# app/graphql/sources/active_record_collection.rb
class Sources::ActiveRecordCollection < GraphQL::Dataloader::Source
def initialize(model, foreign_key)
@model = model
@foreign_key = foreign_key
end
def fetch(ids)
records = @model.where(@foreign_key => ids).group_by(&@foreign_key)
ids.map { |id| records[id] || [] }
end
endBu kalıp ciddi her graphql-ruby projesinde görülür. Resmi DataLoader dokümantasyonu önbellekleme ve iç içe kaynaklar gibi ek kullanım durumlarını kapsar.
Argümanlar ve Filtreleme ile Sorgular Oluşturma
QueryType, istemcilere sunulan kök alanları tanımlar. Argümanlar filtreleme ve sayfalamayı mümkün kılar.
# app/graphql/types/query_type.rb
module Types
class QueryType < Types::BaseObject
field :users, [Types::UserType], null: false do
argument :email_contains, String, required: false
argument :limit, Integer, required: false, default_value: 20
end
def users(email_contains: nil, limit:)
scope = User.all
scope = scope.where('email ILIKE ?', "%#{email_contains}%") if email_contains
scope.limit(limit)
end
field :user, Types::UserType, null: true do
argument :id, ID, required: true
end
def user(id:)
User.find_by(id: id)
end
end
endÇözücü metodları alan tanımına uyan anahtar kelime argümanları alır. Nullable bir alandan nil döndürmek geçerlidir; non-null bir alandan hata fırlatmak GraphQL hata yanıtını tetikler.
Ruby on Rails mülakatlarında başarılı olmaya hazır mısın?
İnteraktif simülatörler, flashcards ve teknik testlerle pratik yap.
Mutasyonlar: Kayıt Oluşturma ve Güncelleme
Mutasyonlar sorgulardan daha katı kurallara tabidir. Her mutasyon kendi sınıfında yaşar ve hem sonucu hem de olası hataları içeren bir payload tipi döndürür.
# app/graphql/mutations/create_post.rb
module Mutations
class CreatePost < Mutations::BaseMutation
argument :title, String, required: true
argument :body, String, required: true
field :post, Types::PostType, null: true
field :errors, [String], null: false
def resolve(title:, body:)
post = context[:current_user].posts.build(title: title, body: body)
if post.save
{ post: post, errors: [] }
else
{ post: nil, errors: post.errors.full_messages }
end
end
end
endcontext[:current_user] controller'dan gelir. Kimlik doğrulama GraphQL katmanından önce, genellikle Devise veya bir JWT kütüphanesi kullanılarak gerçekleşir.
# app/controllers/graphql_controller.rb
class GraphqlController < ApplicationController
def execute
context = {
current_user: current_user,
request: request
}
result = SharpskillSchema.execute(
params[:query],
variables: params[:variables],
context: context,
operation_name: params[:operationName]
)
render json: result
end
endÇözücüler içindeki erişim kontrolü context[:current_user] değerini kontrol eder ve yetkilendirme olmadığında GraphQL::ExecutionError fırlatır. graphql-ruby yetkilendirme rehberi alan düzeyinde ve tip düzeyinde yetkilendirme kalıplarını detaylı açıklar.
GraphQL Abonelikleri ve ActionCable ile Gerçek Zamanlı Güncellemeler
Abonelikler, sunucu tarafı olayları gerçekleştiğinde istemcilerin güncellemeler almasını sağlar. Rails ActionCable WebSocket bağlantısını yönetir ve graphql-ruby GraphQL::Subscriptions::ActionCableSubscriptions aracılığıyla entegre olur.
# app/graphql/types/subscription_type.rb
module Types
class SubscriptionType < Types::BaseObject
field :post_created, Types::PostType, null: false do
argument :user_id, ID, required: false
end
def post_created(user_id: nil)
object # Trigger'dan geçirilen nesne
end
end
endAboneliği tetikleme uygulamanın herhangi bir yerinden yapılabilir, genellikle bir model callback'i veya servis nesnesinde.
# app/models/post.rb
class Post < ApplicationRecord
belongs_to :user
after_create_commit :notify_subscribers
private
def notify_subscribers
SharpskillSchema.subscriptions.trigger(
:post_created,
{ user_id: user_id },
self
)
end
endGraphQL aboneliklerini yöneten ActionCable kanalı gem ile birlikte gelir.
# app/channels/graphql_channel.rb
class GraphqlChannel < ApplicationCable::Channel
def subscribed
@subscription_ids = []
end
def execute(data)
result = SharpskillSchema.execute(
data['query'],
variables: data['variables'],
context: { current_user: current_user, channel: self },
operation_name: data['operationName']
)
payload = { result: result.to_h, more: result.subscription? }
@subscription_ids << result.context[:subscription_id] if result.subscription?
transmit(payload)
end
def unsubscribed
@subscription_ids.each do |sid|
SharpskillSchema.subscriptions.delete_subscription(sid)
end
end
endİstemci tarafında Apollo Client veya urql gibi kütüphaneler ActionCable WebSocket'ine bağlanır ve abonelik durumunu yönetir. ActionCable mekanizmaları hakkında mülakat hazırlığı için ActionCable & WebSockets modülüne bakabilirsiniz.
RSpec ile GraphQL API Testi
GraphQL API testi, şemaya karşı sorgu çalıştırmayı ve yanıt yapısı ile verileri doğrulamayı gerektirir.
# spec/graphql/queries/users_spec.rb
RSpec.describe 'Users query' do
let!(:user) { create(:user, email: 'test@example.com') }
let(:query) do
<<~GRAPHQL
query {
users(emailContains: "test") {
id
email
}
}
GRAPHQL
end
it 'returns users matching the filter' do
result = SharpskillSchema.execute(query)
users = result.dig('data', 'users')
expect(users.length).to eq(1)
expect(users.first['email']).to eq('test@example.com')
end
endMutasyon testleri hem başarı hem de doğrulama hatası yollarını doğrular.
# spec/graphql/mutations/create_post_spec.rb
RSpec.describe Mutations::CreatePost do
let(:user) { create(:user) }
let(:context) { { current_user: user } }
let(:mutation) do
<<~GRAPHQL
mutation($title: String!, $body: String!) {
createPost(input: { title: $title, body: $body }) {
post { id title }
errors
}
}
GRAPHQL
end
it 'creates a post when valid' do
result = SharpskillSchema.execute(
mutation,
variables: { title: 'Hello', body: 'World' },
context: context
)
data = result.dig('data', 'createPost')
expect(data['errors']).to be_empty
expect(data['post']['title']).to eq('Hello')
end
it 'returns errors when invalid' do
result = SharpskillSchema.execute(
mutation,
variables: { title: '', body: 'World' },
context: context
)
data = result.dig('data', 'createPost')
expect(data['errors']).to include("Title can't be blank")
end
endRails test kalıpları hakkında daha fazla bilgi için RSpec ile Test modülüne bakabilirsiniz.
Rails Geliştiricileri için Yaygın GraphQL Mülakat Soruları
Rails bağlamında GraphQL bilgisini test eden mülakatçılar, soyut tip teorisi yerine genellikle pratik uygulama konularına odaklanır.
graphql-ruby'de N+1 sorguları nasıl önlersiniz?
Özel kaynaklarla DataLoader kullanılır. Veritabanı çağrılarını toplu hale getiren bir kaynak sınıfı tanımlanır ve çözücülerde dataloader.with(SourceClass, args).load(id) çağrılır. DataLoader tek bir GraphQL yürütmesinde istenen tüm ID'leri toplar ve tek bir sorguda çeker.
Sorgu ile mutasyon arasındaki fark nedir?
Anlam açısından: sorgular veri okur ve yan etkileri olmamalıdır. Mutasyonlar veriyi değiştirir ve yan etkileri olabilir. GraphQL, sorgu alanları için paralel yürütme ve mutasyon alanları için sıralı yürütme garantisi verir, bu nedenle aynı istekteki iki mutasyon sırayla çalışır.
Rails'de abonelikler nasıl çalışır?
Abonelikler WebSocket bağlantıları için ActionCable kullanır. İstemci WebSocket üzerinden bir abonelik sorgusu gönderir. Sunucu aboneliği saklar ve trigger çağrıldığında sonucu eşleşen tüm istemcilere gönderir. Abonelik ID'si istemcilerin abonelikten çıkmasını sağlar.
Rails API için GraphQL'i ne zaman REST yerine tercih edersiniz?
GraphQL, istemciler farklı veri alt kümeleri gerektirdiğinde aşırı veri çekmeyi azaltır; bu durum farklı ekran boyutlarına sahip mobil uygulamalarda yaygındır. Ayrıca tek bir görünüm birden fazla modelden veri gerektirdiğinde birden fazla REST endpoint'i ihtiyacını ortadan kaldırır. REST, tutarlı veri şekilleriyle CRUD ağırlıklı API'ler ve önbelleklemenin kritik olduğu genel API'ler için daha basit kalır.
graphql-ruby'de kimlik doğrulama ve yetkilendirmeyi nasıl yönetirsiniz?
Kimlik doğrulama, GraphQL yürütmesinden önce controller'da gerçekleşir, genellikle Devise, Warden veya JWT doğrulaması ile. Kimliği doğrulanmış kullanıcı context içinde geçirilir. Yetkilendirme çözücülerde veya graphql-ruby'nin tip ve mutasyonlardaki authorized? hook'u aracılığıyla gerçekleşir ve erişim reddedildiğinde GraphQL::ExecutionError fırlatılır.
Daha fazla Ruby on Rails mülakat hazırlığı için GraphQL bilgisini tamamlayan REST API tasarım kalıplarını kapsayan Rails API Mode modülüne bakabilirsiniz.
Pratik yapmaya başla!
Mülakat simülatörleri ve teknik testlerle bilgini test et.
Rails ile Üretim GraphQL API'leri Oluşturma: Temel Çıkarımlar
- graphql-ruby'yi
rails generate graphql:installile kurmak şema, tipler ve routing'i oluşturur - Tüm ilişkiler için DataLoader kaynakları kullanmak veritabanı sorgularını toplar ve N+1 performans sorunlarını önler
- Mutasyonlar, dönüş tipinde açık hata alanları ile ayrı sınıflarda tanımlanır
- ActionCable aracılığıyla abonelik entegrasyonu, model callback'lerinden veya servis nesnelerinden tetiklenen gerçek zamanlı güncellemeler sağlar
- Sorguları ve mutasyonları RSpec'te doğrudan şemaya karşı çalıştırarak test edin
- Kimlik doğrulama controller'a aittir; yetkilendirme kontrolleri çözücüler içinde
context[:current_user]kullanılarak gerçekleşir - İstemciler esnek veri çekmeye ihtiyaç duyduğunda GraphQL'i tercih edin; tekdüze yanıtlarla basit CRUD API'ler için REST ile devam edin
Ruby on Rails kodundaki hatayı bulabilir misin?
Gerçek bir kod parçası, gizli bir hata, günde bir deneme. Denemek için hesap gerekmez.

Yazan:
Anthony Fillion-MailletSharpSkill kurucusu
10 yılı aşkın süredir fullstack geliştirici. SharpSkill’i yönetiyor ve burada yayımlanan her şeyden sorumlu.
19 Eylül 2026 tarihinde güncellendi
Paylaş
İlgili makaleler

Rails 2026'da Arka Plan Görevleri: Sidekiq vs Good Job Karşılaştırması ve Mülakat Soruları
Rails 8'de Sidekiq, Good Job ve Solid Queue karşılaştırması. Performans analizi, özellik karşılaştırması ve Ruby on Rails background jobs konusunda sık sorulan mülakat soruları.

2026'da Rails Active Storage: Dosya Yükleme, S3 Entegrasyonu ve Mülakat Soruları
2026'da Rails Active Storage için kapsamlı rehber. S3 yapılandırması, doğrudan yükleme, görüntü işleme ve iş görüşmelerinde sıkça sorulan sorular.

2026'da Rails Stimulus ve Importmaps: Build Araçları Olmadan Modern JavaScript
Rails 8'de Stimulus ve Importmaps için kapsamlı bir rehber - webpack, esbuild veya herhangi bir bundler olmadan interaktif web uygulamaları geliştirme.