Как настроить GraphQL Relay API в Rails
Я пытаюсь обернуть голову вокруг GraphQL/Relay, и мне трудно начать с того, как правильно настроить API-интерфейс GraphQL, совместимый с Relay, с использованием Ruby on Rails.
Я нашел несколько уроков о том, как это сделать:
https://medium.com/react-weekly/relay-facebook-on-rails-8b4af2057152
https://medium.com/@gauravtiwari/graphql-and-relay-on-rails-getting-started-955a49d251de
Но все они относятся к graphql-relay
камень, который в данный момент недоступен: https://github.com/rmosolgo/graphql-relay-ruby
grahql-ruby
В документации gem есть раздел, относящийся к ретрансляции, но мне трудно понять, что нужно для настройки этого, чтобы использовать его клиент Relay.
Что необходимо для реализации API-интерфейса GraphQL для клиента Relay в Rails?
2 ответа
Я просто хочу оставить здесь свои выводы для тех, кто застрянет с этим в будущем и хочет получить более точное направление.
Во-первых, graphql-ruby
В состав gem входит все, что необходимо для реализации API-интерфейса GraphQL, совместимого с Relay. В том числе все, что было раньше в graphql-relay
драгоценный камень.
Вам нужно предоставить две вещи в своей схеме, чтобы функция ретрансляции ретрансляции работала хорошо, id_from_object
метод, который преобразует объект в вашем домене, в глобальный идентификатор, а также object_from_id
метод, который будет декодировать глобальный идентификатор в объект в вашем приложении:
ApplicationSchema = GraphQL::Schema.define do
/* Create IDs by joining the type name & ID, then base64-encoding it */
id_from_object ->(object, type_definition, query_ctx) {
GraphQL::Schema::UniqueWithinType.encode(type_definition.name, object.id)
}
object_from_id ->(id, query_ctx) {
type_name, object_id = GraphQL::Schema::UniqueWithinType.decode(id)
# Now, based on `type_name` and `id`
# find an object in your application
# This will give the user access to all records in your db
# so you might want to restrict this properly
Object.const_get(type_name).find(object_id)
}
end
Кроме того, все ваши типы должны реализовать NodeInterface
предоставленный рубиновым камнем, и выставить global_id_field
вместо типа идентификатора:
PostType = GraphQL::ObjectType.define do
name "Post"
# Implements the "Node" interface for Relay
interfaces [GraphQL::Relay::Node.interface]
# exposes the global id
global_id_field :id
field :name, types.String
end
Это позволит Relay повторно получать данные следующим образом:
query {
node(id: "RmFjdGlvbjox") {
id
... on Post {
name
}
}
}
Реле также использует babel-relay-plugin
который требует, чтобы schema.json был сгенерирован и доступен для клиента, если вы создаете изолированный API без рендеринга представлений, то нужно сделать так, чтобы клиенты получали схему и не выполняли эту работу на сервере, что-то вроде apollo-codegen может работать. Однако, если вы создаете приложение rails и вам нужна схема в том же приложении, вы можете выполнить запрос на самоанализ и сохранить результат в файле json с помощью задачи rake:
Schema.execute GraphQL::Introspection::INTROSPECTION_QUERY
Наконец, вы должны понимать, что Relay выражает отношения "один ко многим" со связями:
PostType = GraphQL::ObjectType.define do
# default connection
# obj.comments by default
connection :comments, CommentType.connection_type
# custom connection
connection :featured_comments, CommentType.connection_type do
resolve ->(post, args, ctx) {
comments = post.comments.featured
if args[:since]
comments = comments.where("created_at >= ?", since)
end
comments
}
end
end
Соединения поддерживают некоторые аргументы из коробки, вы можете использовать first
, last
, before
а также after
в ваших запросах на соединение:
query {
posts(first: 5) {
edges {
node {
name
}
}
}
}
Все это задокументировано в документации по Relay, поэтому обязательно прочтите ее, а также документацию по graphql-ruby.
Вы пытались установить его?
vagrant$ bundle install
Fetching gem metadata from https://rubygems.org/............
Fetching version metadata from https://rubygems.org/...
Fetching dependency metadata from https://rubygems.org/..
Resolving dependencies...
Installing graphql 0.19.4
Using bundler 1.11.2
Installing graphql-relay 0.12.0
Bundle complete! 1 Gemfile dependency, 3 gems now installed.
Use `bundle show [gemname]` to see where a bundled gem is installed.
в Gemfile:
gem 'graphql-relay'