Хотите расти как разработчик и найти крутую работу? Не протирайте штаны — займитесь Open Source проектами. Так легче всего попасть в лучшие команды разработчиков и положить себе в резюме настоящий проект, вместо нелепых «примеров кода». Но найти подходящий проект для участия сложно. Начинаются лень и отговорки, а за ними — отсутствие профессионального роста, критики по-настоящему крутых программистов, уныние и застой.
На Cult of Martians мы собираем интересные задачи для современных веб-программистов. Можно выбрать подходящую по сложности, продолжительности и специализации. Задачи не выдуманы «из воздуха» — каждая решает насущную проблему, и решить ее можно через создание нового Open Source проекта или улучшение существующего. Решайте задачи, прокачивайтесь, присылайте решение на оценку. Лучших могут пригласить к себе на работу компании, программистам которых понравится ваше решен ие.
Для уверенных в себе, задача на несколько дней
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.
Инструкции по выполнению