Skip to content

Instantly share code, notes, and snippets.

@rmosolgo
Created July 3, 2024 14:23
Show Gist options
  • Save rmosolgo/364a1023d9167376160a45ea847e1d89 to your computer and use it in GitHub Desktop.
Save rmosolgo/364a1023d9167376160a45ea847e1d89 to your computer and use it in GitHub Desktop.
GraphQL-Ruby lookahead to plan sql queries by alias
require "bundler/inline"
gemfile do
gem "graphql", "2.3.7"
gem "sqlite3", "~>1.4"
gem "activerecord", require: "active_record"
end
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Schema.define do
self.verbose = false
create_table :books, force: true do |t|
t.column :author, :string
t.column :title, :string
t.column :stars, :integer
t.column :library_id, :integer
end
create_table :libraries, force: true do |t|
t.column :name, :string
end
end
class Library < ActiveRecord::Base; end
l1 = Library.create!(name: "Clemons")
l2 = Library.create!(name: "Alderman")
class Book < ActiveRecord::Base; end
Book.belongs_to(:library)
Library.has_many(:books)
Book.create!(title: "Remembering", author: "Wendell Berry", stars: 3, library: l1)
Book.create!(title: "The Going to Bed Book", author: "Sandra Boynton", stars: 5, library: l1)
Book.create!(title: "Historical Brewing Techniques", author: "Lars Marius Garshol", stars: 4, library: l2)
Book.create!(title: "The Tale of Tom Kitten", author: "Beatrix Potter", stars: 3, library: l2)
class BookSchema < GraphQL::Schema
class Book < GraphQL::Schema::Object
field :author, String
field :title, String
field :stars, Integer
end
class Library < GraphQL::Schema::Object
field :books, [Book], extras: [:ast_node]
def books(ast_node:)
@object[:books][ast_node.alias]
end
end
class Query < GraphQL::Schema::Object
field :libraries, [Library], extras: [:lookahead, :ast_node]
def libraries(lookahead:, ast_node:)
book_lookahead = lookahead.selection(:books)
aliases = book_lookahead.ast_nodes.map(&:alias).uniq
alias_fields = {}
aliases.each do |b_alias|
b_alias_fields = lookahead.alias_selection(b_alias).selections.map(&:name)
alias_fields[b_alias] = b_alias_fields
end
::Library.all.map do |library|
result = {}
alias_fields.each do |b_alias, fields|
result[b_alias] = library.books.select(fields)
end
{ books: result }
end
end
end
query(Query)
end
ActiveRecord::Base.logger = Logger.new($stdout)
pp BookSchema.execute("{
libraries {
books1: books { title }
books2: books { author stars }
}
}").to_h
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment