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

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

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

Бэк: Поддержка ассоциаций в Logidze

Для уверенных в себе, задача на неделю

Библиотека Logidze позволяет работать с версиями объектов ActiveRecord моделей и историей их изменений.

Необходимо расширить эту интеграцию, добавив поддержку ассоциаций.

Польза: возможность познакомиться с внутренностями ActiveRecord и научиться с ними работать.

Примеры работы, или что делать?

Предположим, что у нас есть две модели:

class Post < ActiveRecord::Base
  has_many :comments
  has_logidze
end

class Comment < ActiveRecord::Base
  belongs_to :post
  has_logidze
end

Мы хотим, чтобы при работы с версиями одной модели, соответствующие ассоциации (те, для которых включено версионирование) также подгружались для соответствующей отметки во времени. Пример:

# 2017-01-19
post = Post.create!(post_params)

# 2017-01-22
comment = post.comments.create(body: 'My comment')

# 2017-01-24
comment.update!(body: 'New text')

# смотрим пост до обновления комментария (первый случай)
old_post = post.at('2017-01-23')

# сам пост в этот момент не менялся, но у нас есть ассоциация, которая поменялась
old_post.comments.first #=> 'My comment'

# для более старой версии комментариев не было (второй случай)
very_old_post = post.at('2017-01-20')
very_old_post.comments.size #=> 0

Подводные камни и вопросы для обсуждения

  1. В первом случае объект old_post – это тот же самый объект post, так как Logidze возвращает сам объект, если не было изменений с указанного времени. Но для корректной загрузки ассоциаций нам необходимо знать о времени.

Можно изменить это поведение и возвращать объект, который знает о запрашиваемом времени; либо оставить это на откуп разработчикам и советовать им использовать touch: true, чтобы в родительской модели всегда были изменения.

  1. Сохранение прошлой версии должно сохранять и соответствующие ассоциации, но только при явном указании:
# не сохраняет старые версии ассоциаций
old_post.save!

post.undo!

# сохраняет предыдущие версии ассоциаций
old_post.save!(associations_versions: true)

post.undo!(old_post.save!(associations_versions: true))

Для обновления ассоциаций мы можем использовать встроенный механизм – ActiveRecord::AutosaveAssociation.

Нужно только научиться включать и выключать его (в случае, если была использована опция autosave: true) самостоятельно.

Во втором случае (very_old_post) нужно также учесть и удаление записей.

Идеи реализации

Нам необходимо уметь вклиниваться в процесс загрузки ассоциаций для объекта, добавляя вызов метода at(time) на загруженных объектах (см. ActiveRecord#associtaion и ActiveRecord::Associations::Association#load_target).

При этом нужно учитывать, какие ассоциации имеют версионирование (т.е. has_logidze).

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

  1. Присоединиться к обсуждению задачи на GitHub.
  2. Форкнуть проект logidze.
  3. Реализовать необходимый функционал.
  4. Сделать Pull Request.