Как настроить 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'
Другие вопросы по тегам