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

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

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

Помощь запрашивалВова ДемВова Дем Вова Дем

ПомогАлександр АброськинАлександр Аброськин Александр Аброськин

Бэк: GraphQL Ruby: «умная» выборка полей из БД

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

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

Одной из ключевых особенностей GraphQL является возможность запросить клиентом только те данные, которые ему нужны (а не все те, которые предлагает API).

Однако, запросы к БД, которые выполняются при работе, например, с Active Record, не являются оптимальными: используется "SELECT * ..." вместо выборки лишь тех полей, которые необходимы для формирования ответа клиенту.

При большом количестве колонок в таблице или при хранении значений большого размера выгрузка всех полей и инициализация Active Record могут привести к разбуханию памяти или отрицательно повлиять на скорость выполнения запроса.

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

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

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

Рассмотрим следующий запрос:

query {
  posts {
    id
    title
  }
}

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

module GraphqlAPI
  module Types
    class Query < GraphQL::Schema::Object
      field :posts, Types::Post, null: false

      def posts
        Post.all
      end
    end
  end
end

При выполнении GraphQL-запроса будет выполнен следующий запрос в БД: SELECT * FROM posts, хотя нам было бы достаточно запросить всего два поля: id и title.

Учитывая, что GraphQL-запрос содержит информацию о запрашиваемых полях, мы можем использовать ее для построения более эффективного запроса в БД, например, используя следующий API:

module GraphqlAPI
  module Types
    class Query < GraphQL::Schema::Object
      # добавить наш плагин в базовый класс для полей (см. ниже)
      field_class.prepend(GraphQL::SmartSelect)

      # добавим опцию для активации плагина
      field :posts, Types::Post, null: false, smart_select: true

      # в значении мы можем, например, указать, какие поля включать всегда
      # (первичный ключ имеет смысл включать во все запросы)
      field :posts, Types::Post, null: false, smart_select: [:id]

      def posts
        Post.all
      end
    end

    class Post < GraphQL::Schema::Object
      field_class.prepend(GraphQL::SmartSelect)

      field :id, ID
      field :title, String

      # мы можем подсказать нашему плагину, какие поля из БД
      # нужны для формирования данного поля API
      field :contents, db_columns: [:raw_content]

      # для AR ассоциаций мы должны автоматически выводить
      # соответствующую колонку (внешний ключ), например, в
      # данном примере мы добавим "user_id"
      field :user, Types::User
    end
  end
end

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

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

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