Skip to content

Instantly share code, notes, and snippets.

@slavone
slavone / 1_different_types_of_users_problem.md
Last active November 19, 2015 15:30
Code review of the skillgrid.ru test exercise

Этот пункт для меня оказался самым сложным и времязатратным, так как проблемы были как и с придумыванием достаточно оптимального решения, так и с его дальнейшей реализацией. Причем с реализацией проблем было намного больше. Ну, по порядку.

Если бы поля у всех пользователей были одинаковые, то хватило бы только добавить еще одно поле Тип. Но, так как поля у разных типов пользователей разные, то сложности начинаются с того, что нужно решить, как избавиться от лишних полей для пользователей, у которых этих полей быть не должно. Я обдумывал три разных решений:

  1. Тупо делать отдельную таблицу под каждый тип с полным набором полей.

Такое решение, например, предлагается в ридми Devise. В каждой таблице типа пользователя в этом варианте будут повторяющиеся атрибуты типа e-mail, пароля, итд, что уже является очевидным

@slavone
slavone / 2_user_priviliges_problem.md
Last active November 13, 2015 09:46
user_privileges_problem

Здесь особых сложностей не возникло. С фильтрацией действий на контроллерах рельсы сами по себе справляются, по-моему, вполне неплохо, главное учесть все варианты. В этом сильно помогает написание функциональных тестов.

Контроллер для товаров приведен ниже. Фильтры before_action не пропускают юзеров туда, куда им ходить не следует. При дальнейшем расширении, даже не смотря на растущие условия типа current_user.is_some_type_1? || current_user.is_some_type2? || current_user.is_some_type3?, мне кажется такое решение вполне устойчивым и расширяемым. Можно ли это сделать как-то еще оптимальнее?

С views все хуже, в них логика очень быстро накапливается и становится плохо отслеживаемой, ниже приведена пара примеров. Я гуглил по этому поводу, советует использовать декораторы. Какой наиболее правильный способ реализации этого паттерна в рельсах? Гем Draper вроде бы является самым рекомендуемым решением.

Еще вопрос по логике в views c формами. Админ и владелец магазинов оба могут редактировать товары, только редакти

@slavone
slavone / 3_purchase_problem.md
Last active November 14, 2015 10:43
purchase_review

В том виде, в котором сформулировано задание, кнопка покупки никак не связана с товаром. Если же покупка зависела бы от ID товара, то можно было бы передавать этот ID в виде параметров URL'а, и вроде тоже никаких проблем. Так что проблема с покупкой сводится только к делегации прав юзеров - ограничить доступ в контроллере, и видимость во views. Поэтому все вопросы из предыдущего пунка актуальны и здесь.

Для обработки запроса покупки я создал контроллер purchases_controller, откликающийся на один единственный метод new. По логике, что new - новая покупка. Стоит ли здесь придерживаться RESTful терминологии, или же особого смысла это не имеет?

Далее, при покупке нужно считать один случайный JSON со страницы. Я считывал всю страницу через JSON.load, и делал .sample полученной коллекции для получения случайного. Просто считать со страницы случайную запись, не подгружая ее полностью кажется мне невозможным, но может быть я ошибаюсь? Насколько сильно стоит логически отделять функционал такого типа(взаимодействия с

@slavone
slavone / 4_changing_user_type_problem.md
Last active November 14, 2015 10:46
changing_user_type_review

С имеющейся у меня схемой БД с изменением типа юзера проблем нет, но есть пара нюансов. При смене типа пользователя нужно удалить текущую запись пользователя во вспомогательной таблице его текущего типа, создать новую запись во вспомогательной таблице его нового типа, и обновить тип и айди в основной таблице user_logins. Нюанс в том, что это должно быть атомарной транзакцией, но ActiveRecord.transaction легко позволяет это сделать. Еще нюанс - при изменении типа пользователя, ID доп. таблиц будут бессмысленно инкрементироваться, еще раз показывая, что было бы неплохо избавиться от этих лишних ключей.

Для обработки этих действий я создал контроллер user_logins_controller, обеспечивающий стандартный RESTful функционал для user_logins(без добавления и удаления). Доступ туда все теми же стандартными фильтрами ограничивается для всех, кроме админов. При переходе на edit, грузится форма с одним единственным выпадающим списком с типами пользователей. При сабмите проверяется, изменился ли тип, и если изменился, то п

@slavone
slavone / dependent_destroy_script.rb
Created February 19, 2016 09:42
ruby script to add dependent: :destroy to all models if you forgot to do so in the first place :)
#path to folder with model files
dir = "./app/models/*.rb"
Dir.glob dir do |file|
pattern = /(has_one|has_many).*$/
text_to_append = ", dependent: :destroy\n"
before = File.read file
new_text = ''
before.each_line do |line|
@slavone
slavone / ajax_poller.coffee
Created April 12, 2016 08:53
Basic ajax poller in .coffee
@AjaxPoller = (args) ->
this.controllerUrl = args['controllerUrl']
this.pollBody = args['pollBody']
this.pollWhile = args['pollWhile']
this.interval = args['interval']
this.startPolling = () ->
that = this
$.ajax
url: that.controllerUrl
@slavone
slavone / redis-dump.sh
Created February 10, 2017 08:14 — forked from zinovyev/redis-dump.sh
Redis dump in bash
#! /usr/bin/env bash
redis-cli KEYS "*" | awk "{print \"echo \\\"RESTORE \"\$1\" 0 \`redis-cli --csv DUMP \\\"\"\$1\"\\\"\` \\\" \"}" | bash > dump.bkp
# to restore use: cat dump.bkp | redis-cli
@slavone
slavone / env_subst.sh
Last active May 1, 2017 10:14
basic static config templater in bash
#!/bin/sh
# Basic shell templater script for static configs in docker
# made to be run before container start inside entrypoint.sh
# reads $1 file, replaces all variables, enclosed into <%= VAR %>
# with values of env variable with that name
# writes the new file into $2
# Fails if any of the matched variables is empty
set -o errexit
@slavone
slavone / validation_skipper.rb
Created November 29, 2017 14:38
Rails skip validation
module ValidationSkipper
def skips_validation(attribute, validator)
_validators[attribute]&.reject! { |v| v.is_a?(validator) }
_validate_callbacks.each do |callback|
next unless callback.raw_filter.is_a?(validator)
callback.raw_filter.attributes.delete(attribute)
end
end
end
@slavone
slavone / task_one.exs
Last active December 3, 2017 17:08
Advent of Code 2017 Day One
input = """
4281224989975872839961169513979579335691369498483794171253625322698694611857431137339923313798564463624821296465562866115437565642757153598749248981134244727829747894643486262785329362288817862735862788865758282393667944292233174767223374243992399861536752759241133225618738143644513391869188134516852631928916271867698181287155957154445654445815146775218749359429135471217518516313733161224914715646977312989519895119172726843354634362182832619621586712666252991887645898145187935763756291638963496653129912857765951421462617922444757217829413647879689245378416985382884593551597839856381872546538518648745445848789991932426416118597567286346238534756384789237444715638456354681738241966843619342694594591242691968115129274426627615638243236217587858663914247786835991794478455959319285892559359532951119374312668153527813999672953893396261786641484155611753867259924697828887579425583621179386293691294397174274744168516281211916393556463942764518471311826524865614159428158187858845591934838781393518416333663