• Чего ожидать в IT после армии?

    dunmaksim
    @dunmaksim
    Технический писатель
    Единственный совет, который дам: НИКОГДА НИКОМУ НЕ ГОВОРИ, ЧТО УМЕЕШЬ ПОЛЬЗОВАТЬСЯ КОМПЬЮТЕРОМ.

    В армии ITшники не нужны. Их используют по прямому назначению, как микроскоп - для забивания гвоздей, то есть в качестве секретарей. Всю документацию по хорошему должны вести командиры подразделений, но я такого не видел вообще никогда и нигде. Задача ложится на выбранного рядового срочной службы, в очень, очень редких случаях двух. Объём работы таков, что лучше сходить два наряда подряд, чем быть канцеляром роты.

    Есть особая порода командиров-мудаков, которые ставят задачи примерно в 21:00. В 22:00 звучит команда "Отбой", в 22:30 приходит дежурный по полку и проверяет, все ли спят. В 22:35, после его ухода, ты встаёшь и идёшь в канцелярию, где до 2-3 ночи делаешь конспекты, справки, строевые записки, расходы и т. д. А подъём вместе со всеми. От уборки и прочих работ тоже никто не освободит. Не стоит даже надеяться на то, что дадут часок вздремнуть днём. Этот час - он для всех, кроме тебя.
    Ответ написан
    Комментировать
  • Как использовать как фильтр для ng-repeat в AngularJs?

    dunmaksim
    @dunmaksim
    Технический писатель
    ng-repeat работает с набором данных. Опишите в контроллере метод, который фильтрует основной набор в зависимости от значения в input'е. Для этого можно использовать $scope.$watch.
    Ответ написан
    Комментировать
  • Какую систему лучше использовать для Node.JS / IO.JS?

    dunmaksim
    @dunmaksim
    Технический писатель
    Однозначно Debian, т.к. стабильность (т.е. что всё работает так, как ожидается) там гораздо выше, чем в Ubuntu - дистрибутиве, построенном на пакетной базе текущей тестируемой, т.е. нестабильной, версии Debian. Только не слушайте местных линуксоедов насчёт того, что 8-ка - говно, потому что там systemd. Ставьте смело, т.к. systemd сейчас практически стандарт, в том же RHEL и CentOS 7 уже давно.
    Ответ написан
    2 комментария
  • Способы улучшения JS-кода?

    dunmaksim
    @dunmaksim
    Технический писатель
    Знаки !, -, + заставляют интерпретатор вычислить (в данном случае - выполнить) то, что находится справа. Например, в Bootstrap всюду вставлен знак + для этого.
    Однако, более правильным было бы переписать код так:
    (function ($){
        "use strict";
        
    }(this.jQuery));

    Это тоже шаблон самовызываемой функции, описан в книге Стояна Стефанова "JavaScript. Шаблоны" (люто рекомендую читать не смотря на преклонный для литературы данного типа возраст, где взять - сами знаете).

    Обращение к локальным переменным избавляет от головной боли и долгой отладки, когда непонятно, почему при клике на эту кнопку не только обновляется список записей таблицы, но и увеличивается размер шрифта в заголовке страницы. Глобальные переменные - зло, и с этим нужно бороться. Только замыкания, только хардкор.

    Что касается скорости - в сравнении с перерисовкой DOM любой ваш код будет быстрым, как молния. И да, обращение к глобальным переменным дороже, чем к локальным, т.к. сначала делается поиск в локальной области видимости, и только потом - к глобальной.

    document и window можете помещать, можете не помещать - разница будет только в том, что можно использовать краткие имена:

    (function (W, D){ 
        // W = window   (1 символ против 6)
        // D = document (1 символ против 8)
        "use strict";
    
    }(window, document));


    Всё остальное в указанной книге ну и конечно Николас Закас, "JavaScript. Оптимизация производит....
    Ответ написан
    2 комментария
  • С чего продолжить переход на администрирование Linux?

    dunmaksim
    @dunmaksim
    Технический писатель
    Всю жизнь сидел под Windows, потом устроился на работу, где тоже всё было под ней, но стали заметны тормоза многих сервисов, например, тех, что написаны на Python. Оно и понятно - где вы видели быстрый Apache под Windows?
    Сделал себе пару виртуальных машин с Linux'ом, потыкал разные дистрибутивы, неспеша перевёл почти все сервера фирмы и обслуживаемых организаций на Linux (Debian 7, сейчас ставлю 8).
    Выводы после трёх лет использования:
    Manjaro - тот же Arch, только с человеческим лицом, rolling releases, новые ядра и проприетарные драйвера, идеально для десктопа, но берите лучше сборку с XFCE4, кедовая ужасно тормозит и часто падает. Ниасилил, короче.
    Debian 8 - прост в освоении, огромное сообщество и количество мануалов, лучшее решение для серверов. Есть определённые проблемы, например, анальное огораживание по части лицензий софта (что мешает дописать non-free contrib к строкам в /etc/apt/sources.list местным линуксоедам - не знаю), не всегда есть драйвера на новое оборудование да и на старое тоже. На один из серверов так и не встал, потому что после перезагрузки в конце установки перестаёт считать FakeRAID-массив RAID-массивом. Ах, да, можно красноглазить и конпелировать ведро и почти весь остальной софт, прямо как в Source-based дистрибутивах! Вдруг пригодится? Гуглите apt-build. Есть официальный репозиторий с бэк-портами, буквально вчера выручил, когда понадобилось обновить Redis на 7-й версии Debian'а до 2.8.
    CentOS - это бесплатный и урезанный RHEL. Хорош для серверов, но многое из того, что в Debian есть в стандартных репах, там нужно ставить из каких-то мокрописечных левых репозиториев, где за качеством и надёжностью следят три с половиной человека (в отличие от Debian). Однако, поддерживает больше железа и проблем с ним (железом, а не дистром) как правило меньше. Вдобавок, срок поддержки - 10 лет, в отличие от Debian, где таковой куда короче. Почитать подробнее на Wiki бесплатно без СМС.
    Ubuntu - глючное кривое говно даже в LTS. Что мы имеем сейчас: 14.04.3 LTS, половина пакетов в котором куда старше, чем в Debian 8 (с ppa всё становится немного лучше, но EMACS надо всё-таки из сорцов собирать, либо юзать PPA с тестируемой веткой). Стабильность? Да вы меня разыгрываете! Unity? На кой хрен она вообще кому нужна? Может, для абсолютных нубов дистрибутив и хорош, благо куча программ для настройки есть, тот же AppCenter, ещё можно прикрутить ppa... Звук бубна уже слышите, да? Вброшу так же то, что любая Ubuntu создаётся на основе текущей тестируемой ветки Debian. Эх, Valve со своей SteamOS, построенной на Debian-stable...
    OpenSUSE. Может, и хороша эта суся, но меня отпугнула отсутствием кодеков из коробки и сложной системой управления пакетами. Чтобы заработало то, что мне нужно, я потратил кучу времени и нервов. На сервера не ставил, потому что есть CentOS и Debian. Один знакомый рекомендует этот дистрибутив и уже лет 5 только им и пользуется, но меня он убедить не смог. Стоит как минимум обратить на него внимание. Есть Thumbleweed, который позволяет использовать свежий софт (не весь, а некоторый) даже на LTS.
    FreeBSD. Чисто серверная система. Сборка пакетов из сорцов. Стабильность. Надёжность. Всё это перекрывается сложностью настройки и администрирования, т.е. требует грамотного, вдумчивого подхода и кучу свободного времени и литературы. Не холивара ради, но многие крупные игроки IT, тот же Яндекс, давно свалили с фряхи на линукс.
    OpenBSD. *nix-система в её классическом понимании. Возможно, лучший из дистрибутивов, но лично мне даже что бы выключить виртуалку нормально, а не через отправку сигнала ACPI, пришлось погуглить.
    Ответ написан
    1 комментарий
  • Из-за чего происходит ошибка в AngularJS?

    dunmaksim
    @dunmaksim
    Технический писатель
    Очевидно же - у вас файл называется questions.js
    Первая строка - <script src="...
    Интерпретатор пытается его выполнить и падает.
    Подключайте скпипты и библиотеки в html-файлах, а не в JS. В случае с Angular забудьте об AMD, либо подумайте о переходе на Dojo или Aurelia.
    Ответ написан
  • Стоит ли начинающему писать самому плагины на jquery?

    dunmaksim
    @dunmaksim
    Технический писатель
    У меня примерно такая же проблема, мне постоянно хочется улучшать код, который я пишу, из соображений производительности и красоты, но этот перфекционизм излишен и сильно увеличивает сроки разработки.
    Пока нет реально заметных тормозов - не надо ничего оптимизировать. Тенденция не самая хорошая (Witcher 3, Chrome, Assassins Creed - это только вершина айсберга), но пока вы будете делать свой идеальный быстрый плагин, конкуренты напишут кучу глючных кривых костылей, которые уже будут работать, и люди будут пользоваться ими, а когда наконец зарелизите версию 1.0, она уже настолько устареет, что вы и сами ей пользоваться не будете.
    Ответ написан
    Комментировать
  • Как правильно сериализовать объект?

    dunmaksim
    @dunmaksim
    Технический писатель
    Я бы написал так:
    models.py
    from django.db import models
    
    
    class Ingridient(models.Model):
    
        name = models.CharField(
            max_length=30,
            unique=True,
            db_index=True
        )
    
        class Meta:
            db_table = 'ingridient'
            ordering = [ 'name' ]
    
    
    class Recipe(models.Model):
    
        name = models.CharField(
            max_length=30,
            unique=True,
            db_index=True
        )
    
        ingridients = models.ManyToManyField(
            Ingridient
        )
    
        class Meta:
            db_table = 'recipe'
            ordering = [ 'name' ]


    serializers.py
    from rest_framework.serializers import ModelSerializer, PrimaryKeyRelatedField
    from .models import Ingridient, Recipe
    
    
    class IngridientSerializer(ModelSerializer):
    
        class Meta:
            model = Ingridient
    
    
    class RecipeReadListSerializer(ModelSerializer):
    
        class Meta:
            model = Recipe
            exclude = ['ingridients']
    
    
    class RecipeReadDetailSerializer(ModelSerializer):
    
        ingridients = IngridientSerializer(
            many=True
        )
    
        class Meta:
            model = Recipe
    
    
    class RecipeWriteSerializer(ModelSerializer):
    
        ingridients = PrimaryKeyRelatedField(
            queryset=Ingridient.objects.all(),
            many=True,
            default=[]
        )
    
        class Meta:
            model = Recipe


    views.py
    from rest_framework.viewsets import ModelViewSet
    
    from .serializers import IngridientSerializer, RecipeReadListSerializer, RecipeReadDetailSerializer, RecipeWriteSerializer
    from .models import Ingridient, Recipe
    from rest_framework.permissions import AllowAny
    
    
    class IngridientViewSet(ModelViewSet):
    
        queryset = Ingridient.objects.all()
    
        serializer_class = IngridientSerializer
    
        permission_classes = [
            AllowAny
        ]
    
        class Meta:
            model = Ingridient
    
    
    class RecipeViewSet(ModelViewSet):
    
        queryset = Recipe.objects.all()
    
        permission_classes = [
            AllowAny
        ]
    
        def get_serializer_class(self):
            if self.request.method == 'GET':
                if self.action == 'list':
                    return RecipeReadListSerializer
                return RecipeReadDetailSerializer
            return RecipeWriteSerializer


    urls.py
    from rest_framework.routers import SimpleRouter
    from .views import IngridientViewSet, RecipeViewSet
    
    router = SimpleRouter()
    router.register(r'ingridients', IngridientViewSet, base_name='ingridients')
    router.register(r'recipies', RecipeViewSet, base_name='recipe')
    
    urlpatterns = router.urls


    Насчёт использования SlugField не совсем уверен, что они нужны, ведь API в данном случае будет простым, список его URL вообще проще некуда, впрочем, я думаю, добавить их вы сможете в любое нужное время.
    Зачем для сериализации рецептов целых три сериализатора?
    При получении списка всех рецептов как правило не нужно сразу же получать и все ингридиенты. Во всяком случае, в моих приложениях я делаю подгрузку полной копии модели только при детальном просмотре, а в списках часть полей скрыта на уровне API. Надо ли говорить, что при сериализации пользователей несколько сериализаторов просто необходимы, чтобы не выводить пароль при получении объекта, но иметь возможность его обновлять при записи?
    Сериализатор для чтения деталей как раз выдаёт вложенные объекты при получении модели рецепта - в поле ingridients будет массив полностью сериализованных объектов Ingridient.
    Третий сериализатор используется только для создания записей типа Recipe или их обновления. Для заполнения ингридиентов нужно передать список их id. DRF сам проверит существование соответствующих моделей и выполнит все остальные действия.
    Ответ написан
    Комментировать
  • Django. Как изменять отдельные поля в форме?

    dunmaksim
    @dunmaksim
    Технический писатель
    Используйте частичное обновление update() вместо полного save(): https://docs.djangoproject.com/en/1.8/ref/models/q...
    При этом вместо POST лучше установить заголовок запроса в PATCH.
    Ответ написан
    2 комментария
  • JSlint настройка проверки JS?

    dunmaksim
    @dunmaksim
    Технический писатель
    Обычно для таких случаев лучше настройки автоформаттера кода подкрутить. Что там у вас: jsfmt, web-beautify, js-beautify? В любом случае, просто найдите опцию "JSLint Happy" или подобную, после чего перепишите код как положено:
    • [FAIL] все переменные объявляются за один var (а вот другая точка зрения)
    • [OK] строгий режим
    • [FAIL] внутри for ... in ... делать проверку hasOwnProperty()
    • [FAIL] пробел перед круглыми скобками декларации анонимных функций
    • ну и так, мелочь всякая, лень перечислять дальше, например, for в вашем случае прекрасно заменяется на forEach(), отличная статья по теме

    Если поможет, в моём конфиге EMACS'а хранятся так же настройки автоформата для JS - файлы сами поймёте какие и куда положить (судя по убунте).
    Ответ написан
    Комментировать
  • Как в Django v1.8 в ClassBasedView установить CSRF-токен?

    dunmaksim
    @dunmaksim Автор вопроса
    Технический писатель
    Решение оказалось на редкость простым: в шаблоне нужно добавить строку:
    {% csrf_token %}
    В этом и только в этом случае cookie с CSRF-токеном будет присутствовать на странице.
    Ответ написан
    Комментировать
  • Стоит ли изучать TypeScript?

    dunmaksim
    @dunmaksim
    Технический писатель
    "Я русский бы выучил только за то, что им разговаривал Ленин!"
    А TypeScript - из-за Angular 2 и Dojo 2.
    Ответ написан
    Комментировать
  • Зачем писать pass в конце функции?

    dunmaksim
    @dunmaksim
    Технический писатель
    Просто заглушка для синтаксиса. Используется только в редких случаях, например, при множественном наследовании:

    class UsersAPIView(object):
        serializer_class = UserSerializer
        permission_classes = [IsAdmin]
        queryset = User.objects.all()
    
    class UserListCreateAPIView(UsersAPIView, ListCreateAPIView):
        pass # Иначе - indentation error
    
    class UserRetrieveUpdateDestroyAPIView(
        UsersAPIView,
        RetrieveUpdateDestroyAPIView):
        pass


    В результате имеем два класса, один для получения списка элементов или их создания, другой - для получения, обновления и удаления отдельного экземпляра записи.
    Ответ написан
    Комментировать
  • Давайте сделаем чеклист подготовки linux сервера?

    dunmaksim
    @dunmaksim
    Технический писатель
    Общее
    1. Обновить все пакеты.
    2. Добавить нужные репозитории и их ключи в список (Nginx, PostgreSQL)
    3. В нужные места для deb-based добавить non-free contrib, т.к. в том же Debian из коробки только свободные пакеты.
    4. Поставить и включить bash-completion
    5. Поставить sudo, внести себя в группу админов, запретить root'у логиниться в системе
    6. Поставить ntp и ntp-date, указать сервера в файлах настройки


    SSH (статья)
    1. Установить openssh-server
    2. Добавить в ~/.ssh/authorized_keys свой публичный ключ.
    3. Увеличить длину серверных ключей до 2048 бит минимум, по-умолчанию везде 768.
    4. Сгенерировать серверные ключи заново.
    5. Отключить авторизацию по паролю.
    6. Запретить входить без пароля
    7. Поставить и настроить fail2ban
    8. Сменить порт SSH с 22 на какой-нибудь другой (отсекает 95% ScriptKiddies сразу же)


    SSL (статья)
    1. Включить шифрование по ГОСТу (не всем нужно, но лично мне по работе - нужно всегда)


    PostgreSQL (статья)
    1. Ставить только из официального репозитория последнюю стабильную версию.
    2. Оптимизировать настройки postgresql.conf с помощью этого сайта под конкретную систему / машину.
    3. Сделать Listen только на внутренний интерфейс локальной сети или вообще на localhost, если СУБД и сервер приложений будут на одной машине.
    4. Настроить pg_hba.conf
    5. Написать скрипты резервного копирования.
    Ответ написан
    Комментировать
  • Что не так с rout-ингом?

    dunmaksim
    @dunmaksim
    Технический писатель
    Используйте не href, а ng-href - эта штука учитывает особенности работы Angular, например, асинхронную подгрузку значений в список элементов. В остальном всё вроде правильно, за исключением того, что в контроллере Вы используете одну переменную, а в шаблоне выводите значение другой:

    $scope.phoneId = $routeParams.phoneId;
    // Лучше - $scope.routeParams = $routeParams;


    Что имеете

    <a ng-href="#/phones/{{ phone.id }}>Посмотреть</a>

    Что должно быть:

    <a ng-href="#/phones/{{ phoneId }}>Посмотреть</a>

    P. S. Ссылку в кнопку? Почему бы не использовать для кнопок и ссылок-кнопок одни и те же наборы стилей, как это сделано в Bootstrap?
    Ответ написан
    Комментировать
  • Почему не передаются данные в форме?

    dunmaksim
    @dunmaksim
    Технический писатель
    1. Отображайте возможность выбора типа организации прямо в той же форме, где пользователь выбирает, физлицо он или организация. ng-if в помощь.
    2. Вызывать диалоговое окно не стоит, а если уж вызываете, сделайте кнопку отмены.
    3. В диалоговых окнах Angular Material свой $scope. Для правильной обработки используйте такой код:
    $mdDialog.show({
        templateUrl: '/template/dialog.html',
        controller: [ '$scope', '$mdDialog', function($scope, $mdDialog){
            $scope.cancel = $mdDialog.cancel; // Отмена. Ничего сложного.
            $scope.save = function(){
                $mdDialog.hide($scope.model); // Диалог закрывается, promise разрешается моделью
            };
        }]
    }).then(function (model) {
        // Та самая модель, которую возвращает $mdDialog. 
        // При использовании метода cancel() выполняет код для reject
    });
    Ответ написан
    1 комментарий
  • Что такое провайдер в программировании?

    dunmaksim
    @dunmaksim
    Технический писатель
    Как правило провайдер используется для инкапсуляции более сложного кода, скрывая детали реализации. Он служит этакой обёрткой, реализуя шаблон проектирования "Фасад".
    Вы копируете файл из каталога в каталог, просто перетащив его мышью. Но как это произошло на физическом уровне? Вам этого знать не обязательно, всё скрыто под множественными слоями абстракций.
    Чтобы не думать о каких-либо низкоуровневых вещах, часто вводят провайдеры, сервисы и т.д. Суть одна - скрыть какие-либо часто используемые сложные функции и рутинную работу за простым и понятным интерфейсом.
    Ответ написан
    2 комментария
  • Django как сделать запрос к профайлу user'a в шаблоне и проверить принадлежность к группе?

    dunmaksim
    @dunmaksim
    Технический писатель
    В статье я написал, как делать расширенную модель пользователя: dunmaksim.blogspot.ru/2015/05/django-18.html
    Для решения Вашей задачи нужно:
    • описать базовую модель User с полем role или полями вида is_user, is_vendor и т.п.
    • унаследовать от неё классы Vendor и PlainUser

    В виде делаем ещё проще (показано для ClassBasedView, так же требуется обязательная авторизация, но Вы можете допилить для себя):
    from os import path
    
    from django.contrib.auth.decorators import login_required
    from django.core.context_processors import csrf
    from django.shortcuts import render_to_response
    from django.template import RequestContext
    from django.views.generic import View
    
    
    class Login(View):
    
        def get(self, request):
            c = {}
            c.update(csrf(request))
                    RequestContext(request, c)
            return render_to_response(
                path.join('login', 'index.html'),
                RequestContext(request, c)
            )
    
    
    class LoginRequiredMixin(object):
    
        @classmethod
        def as_view(cls, **initkwargs):
            view = super(LoginRequiredMixin, cls).as_view(**initkwargs)
            return login_required(view)
    
    
    class Desktop(LoginRequiredMixin, View):
    
        def get(self, request):
            c = {}
            c.update(csrf(request))
            user = request.user
            if user.is_admin:
                return render_to_response(
                    path.join('admin', 'index.html'),
                    RequestContext(request, c)
                )
            if user.is_vendor:
                return render_to_response(
                    path.join('vendor', 'index.html'),
                    RequestContext(request, c)
                )
            return render_to_response(
                path.join('desktop', 'index.html'),
                RequestContext(request, c)
            )
    Ответ написан
    8 комментариев
  • Стараетесь ли вы использовать flex?

    dunmaksim
    @dunmaksim
    Технический писатель
    Я использую его по полной. Потому что нет нужды поддерживать старьё и основная библиотека - Angular Material.
    Ответ написан
    Комментировать
  • Правильна ли трактовка кода?

    dunmaksim
    @dunmaksim
    Технический писатель
    Всё несколько проще. Вместо "ассоциативный массив" всегда говорите "объект".

    /* Глобальная переменная - лучший друг быдлокодера */
    var map;
    
    /* Создадим с помощью конструктора новый объект */
    var brooklyn = new google.maps.LatLng(40.6743890, -73.9455);
    
    /* Так обычно объявляют константы (до ECMA 2015 нормального синтаксиса не было) */
    var MY_MAPTYPE_ID = 'Purple';
    
    // Обычно такую телегу записывают так (шаблон One-var template, привет, Pascal!):
    var map,
    	  brooklyn = new google.maps.LatLng(40.6743890, -73.9455),
    	  MY_MAPTYPE_ID = 'Purple';
    
    /* Декларируем функцию */
    function initialize() {
    	/* Создаём массив объектов */
        var featureOpts = [
    		{ // Раз
    			stylers: [ //И сразу вложенный объект с полем-массивом объектов
    				{ hue: '#6b20a1' },
    				{ visibility: 'simplified' },
    				{ gamma: 0.5 },
    				{ weight: 0.5 }
    			]
    		}, { // Два
    			elementType: 'labels',
    			stylers: [ // Вложенный массив
    				{ visibility: 'on' }
    			]
    		}, { // Три
    			featureType: 'water',
    			stylers: [
    				{ color: '#6b20a1' }
    			]
    		}];
    } // Закрывающую скобку кто ставить будет, я что ли?
    Ответ написан
    Комментировать