Нам нужны твои мозги

Хотите расти как разработчик и найти крутую работу? Не протирайте штаны — займитесь Open Source проектами. Так легче всего попасть в лучшие команды разработчиков и положить себе в резюме настоящий проект, вместо нелепых «примеров кода». Но найти подходящий проект для участия сложно. Начинаются лень и отговорки, а за ними — отсутствие профессионального роста, критики по-настоящему крутых программистов, уныние и застой.

На Cult of Martians мы собираем интересные задачи для современных веб-программистов. Можно выбрать подходящую по сложности, продолжительности и специализации. Задачи не выдуманы «из воздуха» — каждая решает насущную проблему, и решить ее можно через создание нового Open Source проекта или улучшение существующего. Решайте задачи, прокачивайтесь, присылайте решение на оценку. Лучших могут пригласить к себе на работу компании, программистам которых понравится ваше решение.

Бэк: GraphQL Ruby: поддержка «внешних» схем

Для уверенных в себе, задача на несколько дней

Gem graphql-ruby предоставляет объектно-ориентированный интерфейс для построения GraphQL API на Ruby.

Одним из преимуществ GraphQL часто называют возможность агрегировать данные из разных источников в одном запросе и прозрачно для клиента.

Отдельно рассматривают случай, когда один провайдер GraphQL API агрегирует данные из других GraphQL API. Этот сценарий носит название schema stitching.

К сожалению, на сегодняшний день поддержка объединения (или сшивания) схем отсутвует в реализации на Ruby.

Необходимо написать плагин (gem) для graphql-ruby, который позволит создавать «внешние» поля в локальную схему.

Польза: познакомиться с GraphQL в Ruby, получить open source опыт Ruby, принести пользу сообществу.

Пример работы и возможный API

На стороне Ruby мы опишем наш интерфейс следующим образом:

module GraphqlAPI
  module Types
    module Types
      class BaseType < GraphQL::Schema::Object
        # подключаем плагин
        include GraphQL::RemoteFields

        # resolver - это любой объект, который реализует метод #resolve_remote_field
        remote_resolver MyResolver.new(url: "http://remote/api/graphql")
      end

      class Query < BaseType
        field :posts,
              [Types::Post],
              null: false

        field :payments,
              [Types::Payment],
              null: false,
              # помечаем поле как `remote`
              # – значение будет получаться через
              # зарегистрированный resolver
              remote: true

        field :billing_info,
              Types::BillingInfo,
              null: true,
              remote: true,
              # можем явно указать другой resolver
              remote_resolver: another_resolver,
              # по умолчанию на "внешний" сервер отправляется неизмененный
              # запрос, но можно определить правило (блок), чтобы изменить запрос
              # (вместо "...fields" будут запрашиваемые поля
              remote_query: ->(obj, ctx) { "query { billing { ...fields } }" }
      end
    end
  end
end

class MyResolver
  # resolver получает на вход запрос и текущий контекст
  # (который будет использоваться, например, для аутентификации)
  def resolve_remote_field(query, context)
  end
end

Пример исходного запроса:

query {
  posts {
    id
    title
  }
  payments {
    id
  }
  billingInfo {
    cardType
    last4
  }
}

Часть запроса будет выполнена локально:

query {
  posts {
    id
    title
  }
}

Другая часть будет проксирована на resolver по умолчанию:

query {
  payments {
    id
  }
}

И, наконец, третья часть запроса будет выполнена с помощью another_resolver:

query {
  billing {
    cardType
    last4
  }
}

Примечание: пример расширения API для полей смотрите в этом gist.

Инструкции по выполнению

  1. Сделать новый проект на GitHub — gem, который будет плагином для graphql-ruby.
  2. Реализовать необходимый функционал, предусмотреть нужные тесты.
  3. Прислать письмо или написать комментарий о выполненном задании.