Хотите расти как разработчик и найти крутую работу? Не протирайте штаны — займитесь Open Source проектами. Так легче всего попасть в лучшие команды разработчиков и положить себе в резюме настоящий проект, вместо нелепых «примеров кода». Но найти подходящий проект для участия сложно. Начинаются лень и отговорки, а за ними — отсутствие профессионального роста, критики по-настоящему крутых программистов, уныние и застой.
На Cult of Martians мы собираем интересные задачи для современных веб-программистов. Можно выбрать подходящую по сложности, продолжительности и специализации. Задачи не выдуманы «из воздуха» — каждая решает насущную проблему, и решить ее можно через создание нового Open Source проекта или улучшение существующего. Решайте задачи, прокачивайтесь, присылайте решение на оценку. Лучших могут пригласить к себе на работу компании, программистам которых понравится ваше решен ие.
Для продвинутых, задача на неделю
Необходимо написать инструмент для клонирования моделей (например, Active Record) с гибкими настройками. Существующие гемы (deep_clonable и amoeba), к сожалению, неудобны при работе со сложной бизнес-логикой и завязаны на ActiveRecord.
Польза: попрактиковаться в написании расширяемого DSL на Ruby и написать инструмент, которым будет активно пользоваться сообщество.
class PostCloner < Clowne::Cloner
# клонировать все ассоциированные объекты
include_all
# клонировать указанную ассоциацию
include_association :comments
# указать scope для ассоциации
include_association :comments, -> { where('created_at > ?', 1.year.ago) }
# или именнованный scope
include_association :comments, :this_year
# исключить ассоциацию (если она была добавлена через include_all или в родительском конфиге)
exclude_association :likes
# обнулить поля
nullify :external_id, :modified_at, :modified_by
# пользовательский блок, вызываемый в конце клонирования
finalize do |source, record|
# ...
end
end
Для клонирования объекта вызываем:
cloned_post = PostCloner.call(post)
# Дополнительно указываем контекст и произвольные параметры
cloned_post = PostCloner.call(post, for: :another_user, user_id: 123)
class PostCloner < Clowne::Cloner
...
# в конфигурации описываем именнованный контекст
context :another_user do
nullify :user_id
# в модификаторах ассоциаций имеем доступ к доп. параметрам
include_association :likes, -> (params) { where.not(user_id: params[:user_id]) }
# и в finalize
finalize do |source, record, params|
record.user_id = params[:user_id]
end
end
end
# Только произвольные параметры
cloned_post = PostCloner.call(post, user_id: 123)
# По умолчанию для модели Comment
class CommentCloner < Clowne::Cloner
...
end
class SimpleCommentCloner < Clowne::Cloner
...
end
class PostCloner < Clowne::Cloner
include_associations :comments, clone_with: SimpleCommentCloner
end
Если для модели не существует конфига, то клонируем только атрибуты, без ассоциаций
Механизм клонирования должен подразумевать интеграцию с разными фреймворками (не только Active Record), то есть должен быть внутренний API для написания адаптеров для произвольных фреймворков
По умолчанию должна быть только поддержка ActiveRecord:
class Post < ActiveRecord::Base
# Явно указать класс клонера
clone_with ArticleCloner
end
post.clone(params) == ArticleCloner.call(post, params)
Инструкции по выполнению