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