Пределы дискуссии

Сергей Волков — человек спорный, но спорить с ним не стоит. А вот прочитать некоторые его заметки — стоит.

путать идеальное с реальным, хотя это все равно, что смешивать земное и небесное в политике (с одной стороны – опошляется и предстает в карикатурном виде вера, с другой – политики садятся в лужу). В основе всего такого – непонимание, что в реальной жизни нет ничего выше реальности, т.е. самой этой жизни.

Наблюдение над реальностью – единственное основание для выводов о возможном (как настоящем, так и в будущем), потому что бывает только так, как может быть, а может быть только так, как бывало. Человек, исходящий из идеальных схем, теряет связь с реальностью. Он рисует себе картинку «как должно быть» и потом начинает воображать, что где-то когда-то так оно и было, а потом вот почему-то испортилось (и вот бы восстановить). При этом о том, почему испортилось, приходится выдумывать самую нелепую ерунду — потому что на самом деле просто не было той благости, которая ему представлялась или эта благость вовсе таковой не являлась, а в лучшем случае была обречена собственными пороками.

***

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

Я всегда полагал, что сделать очевидной общность, к которой принадлежит человек, очертить его позицию, гораздо важнее, чем спорить с ним, ибо последнее в большинстве случаев именно по причине этой принадлежности абсолютно бессмысленно

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

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

Но это контрпродуктивно. Если знаешь позицию собеседника — уже знаешь достаточно. Разубеждать волхва в подлинности очередных Славяно-Греко-Латинских Вед бесполезно, он слышал эти аргументы миллион раз.

Тем более контрпродуктивно спорить с заведомо бредовой позицией на публике. Спорить с чем-то — означает признавать это потенциально равным.

Прапорщик с солдатом не спорит, прапорщик (не говоря о вышестоящих офицерах) солдату приказывает. Потому что солдат не равен прапорщику. Неравенство даже в Уставе прописано.

Даже не служившему человеку понятно, что спорить могут только равные. Иначе вышестоящий просто приказал бы нижестоящему заткнуться и выполнять.

Споры с теориями, которые не интересны даже лечащему врачу её первооткрывателя, только ещё больше убеждают публику, что уфология или креационизм — серьёзные, пусть и не признанные скучной официальной наукой области знания, в которых “что-то есть”.

Кацнельсон очень верно советует учёному бороться с лженаукой только на одном, небольшом участке — в своих собственных работах.

Бессмысленно спорить, если причина занятой позиции лежит за пределами спора. И тем более бессмысленно спорить с обитателями удивительной “планеты чудес и загадок”.

***

В известном анекдоте коварный профессор валил заочников на экзамене сложнейшим вопросом “Как называется предмет, который вы сдаёте?”.

Интернет — не заочка, обязательных лекций нет и экзамены сдавать не надо. Поэтому тут скорее был бы уместен более лёгкий вопрос — “На какой планете мы сейчас находимся?”.

Если человек уверен, что на Юпитере — спорить с уважаемым гуманоидом уже заранее не о чем.

Конечно, и среди людей инопланетного происхождения попадаются адекватные ксеноморфы, которые в курсе, что они на Земле, а не на исторической родине.

Опытный космолётчик даже может рассказать про планету такое, чего ты не знаешь. Со стороны ему виднее то, чего ты не замечаешь.

Но не надо зацикливаться на странных выводах, которые инопланетянин иногда выдаёт. Для марсианина вполне нормально верить в непременное наступление национал-феминизма в отдельно взятом Земшарном Евросоюзе или считать, что у всех нормальных планет должно быть по два спутника — как на родном Марсе. Поэтому лун на самом деле две — только одну из них НАСА скрывает.

Ни в какие масштабные подлоги и судьбоносные фальсификации я не верю. Это как вечный двигатель – «не рассматривается». Сие есть отрасль конспирологии, которая, как и фоменковщина – ПАРАЛЛЕЛЬНЫЙ МИР, «планета чудес и загадок». Жить на ней гораздо интереснее и приятнее (даже жаль, что в силу пошлости мышления я там не прижился), но это примерно то же, что мир фэнтэзи (видел у нас в парке эльфов с луками; вроде и при переписи сколько-то их насчитали), в котором тоже можно с успехом абстрагироваться от реальности […]

Но в мире, где «все подделано», пронизанном сетями двойных, тройных и далее агентов, которым управляют из тайных убежищ гениальные умы, — действуют своя логика и свои законы, которые распространяются на ВСЕХ его обитателей и которые, так сказать, «обоюдоостры». Как-то я сказал доставшему меня со своими «докажи» однокашнику примерно следующее: «А попробуй доказать, что ты действительно Андрюша Ш., а не натурализовавшийся марсианин №0123456789. Паспорт у тебя, конечно, фальшивый, диплом в переходе купил. Копию лицевого счета из ДЭЗа принесешь? Так у них там, известно, зарплаты маленькие… Что, мать жива? Так старушка за молочишко и Тони Блэра сыном признает. Ах, в Бауманском ЗАГСе метрическая запись есть? Так ведь марсиане для своего агента не поленятся всю книгу за 56-й год переписать. И о чем нам с тобой после этого говорить?» 

Если можно объявить фальшивым один документ – то и всякий другой, на обвинение в «работе на» всегда возможно ответное и т.д. Поэтому параллельный мир населен общностями (как бы сектами), каждая из которых верует в подлинность одного, отрицая подлинность другого и наоборот и находя в этом удовлетворение. В рамках своего мира всем хорошо, на реальный — не влияет. Придет человек в Лувр: «Ну Ван Дейк – ладно, но Рубенс-то – явная фальшивка. Многовато его, ох многовато. Ну не мог один человек столько написать. Скорее всего, и не было его вовсе, это в XVIII веке подмастерья забавлялись». Люди пожмут плечами, цены не дрогнут. 

Фальсификация же глобального порядка, предполагающая желание человека подурачить потомков, которым предстоит жить через несколько столетий – за пределами здравого смысла. Никто в ХХ-Х1Х в. не писал «историй» о существовании в это время вымышленных государств и происходящих там событиях, и просто потому что «все знали». Но «все знали» и 400, и 800 лет назад, поэтому про современную им жизнь «по крупному» не фантазировали и тогда. Конечно, всегда был тот мотив, по которому подделывают антиквариат, но он предполагает максимальное приближение к известным образцам и исключает оригинальничанье. Поэтому такие тексты и документы известны, но сенсаций обычно не содержат. Наконец, никакой текст или документ, как правило, не является единственным источником по вопросу, всегда есть множество других, с которыми он может быть сопоставлен. Если же вдруг таковым является (как платоновское известие об Атлантиде), то в этом случае вопрос обычно вовсе не рассматривается (кстати сказать, когда сомнительным источником заполняют «черную дыру», это «впредь до прояснения» более терпимо, чем отрицание хорошо известных фактов).

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

Для меня, в абсолютном большинстве случаев работающим с массовым материалом, который «подделать» заведомо нельзя, этот вопрос не актуален, сюжетами, когда решение вопроса зависит от подлинности или толкования какого-то одного документа, я предпочитаю не заниматься. Но на самом деле никакой такой бумажки, которая бы стоила миллиардов других хранящихся в архивах листов, просто не существует. Если документ противоречит всем остальным известным фактам, то есть все основания посчитать недостоверным именно его. Точно так же нормальный историк не станет перекраивать хронологию из-за одного труднообъяснимого события, если тем самым он сделает необъяснимыми 30 других.

Когда же вопрос о подлинности встает, для меня решающим является мнение специалистов — профессиональной среды. Критика источников преподается на младших курсах всем. Специалист же есть тот, кто реально работал именно с такого рода материалом и писал не «ваще», а «конкретно». Человек, выдавший на гора «Историю Востока», не написав предварительно десятки статей типа «Административные фунции уделов в Китае в нач. ХУ в.» или «Социальная мобильность землевладельческого слоя общины в Гуджарате в Х1Х в.» – это шарлатан. Вообще в историю, лежащую за пределами «новейшей» и частично «новой», с 50-х годов по комсомольским путевкам не направляли, и публика там в профессиональном отношении приличная, мне знакомая. Несерьезные и жулики встречаются, но их все знают. Так вот если относительно какого-то источника мнения разделяются – можно вникать в аргументы и выбирать «сторону»; если никто из серьезных специалистов подозрение в «фальсификации» не разделяет – вопроса просто нет. Мнение же по столь «специальным» вопросам людей, профессионально по теме не работавших, можно в расчет не принимать, это – «параллельный мир», в котором Ксения Собчак может основать историческую школу с еще большим успехом, чем Фоменко. 

Точно так же я не склонен принимать за результат действия «тайных сил» то, что по большей части бывает порождено глупостью, человеческими слабостями и случаем. Предпочтение экзотических объяснений наиболее простым всегда казалось мне чем-то типа ковыряния правой ногой в левом ухе, а излюбленное занятие жителей параллельного мира по конструированию «истинной» политической принадлежности человека – чрезвычайно занимательной игрой. Большинству интеллигентных людей годам к 30–35 довелось учитья, общаться, работать, пить с таким количеством разных лиц (не говоря о наличии близких и дальних родственников), где-то что-то при разных обстоятельствах писать и говорить, что возможности интерпретации весьма широки, а с подключением «логических умозаключений» — поистине безграничны. Меня самого, например, можно при желании смело отнести к ЛЮБОЙ из существующих политических общностей. Но и мне, в свою очередь, не составит труда проделать то же самое с кем угодно. 

Эта игра «чистого разума» гораздо увлекательней пошлых систематических штудий, поэтому, например, масоноборческие изыскания «пьяных советских самоделкиных» известны всем, а про словарь Серкова не знают даже многие историки. Поскольку же логика конспирологического мышления предполагает поиски враждебной агентуры прежде всего в ближайшем окружении и среди наиболее заметных соратников, картина их взаимоотношений обычно доставляет массу удовольствия менее озабоченным гражданам. Если на «планете чудес и загадок» невозможно доказать существовавшее, то опровергнуть несуществующее тем более невозможно. Если скажут, что это я организовал дефолт-98, не представляю, как бы я мог оправдаться. 

Загрузка файла в Django REST Framework

Учимся загружать файл через стандартное API Djan­go REST Frame­work.

Загруженный файл приходит в request.FILES, класс Upload­ed­File. Для HTML-формы должно быть установлено enctype=“multipart/form-data” и она должна заливаться через POST. Идут годы, а формы в HTML не меняются…

В Djan­go Mod­el есть специальный поля для хранения загруженных файлов — File­Field и Image­Field. Они хранят, разумеется, не в базе, а на жёстком диске.

Куда класть закаченный файлы — прописывается в settings.py:

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

И можно разрешить смотреть их прямо по URL, если у нас DEBUG:

from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    # Project url patterns...
]

if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Можно специально указать поддиректорию, в которую будут скидываться файлы, указанные для File­Field:

from django.db import models

class Document(models.Model):
    description = models.CharField(max_length=255, blank=True)
    document = models.FileField(upload_to='documents/%Y/%m/%d/')
    uploaded_at = models.DateTimeField(auto_now_add=True)

Загруженные в Document.document файлы будут лежать в папке media/documents/2018/05/04.

Удобней всего загружать через формы.

Создаём форму:

from django import forms
from uploads.core.models import Document

class DocumentForm(forms.ModelForm):
    class Meta:
        model = Document
        fields = ('description', 'document', )

Создаём view:

def model_form_upload(request):
    if request.method == 'POST':
        form = DocumentForm(request.POST, request.FILES)
        if form.is_valid():
            form.save()
            return redirect('home')
    else:
        form = DocumentForm()
    return render(request, 'core/model_form_upload.html', {
        'form': form
    })

 

jQuery UI control в React на примере FormBuilder

jQuery UI — симпатичная библиотека. У неё есть недостатки — она тяжелее Boot­strap и довольно старая. Но бывает, что нужный компонент есть только под неё. А у тебя проект на одном из React-фреймворков…

Для примера попробуем подключить старый jQuery Form­Builder. Это просто отличный редактор форм.

Конечно, есть другие. Есть даже редактор форм под React… но он использует доисторические библиотеки и отныне не собирается. А их тех, которые собираются, Form­Builder — самый наглядный. В него не страшно пустить даже неопытного пользователя.

Но увы… большинство React-фреймворков давным-давно jQuery-free. Как же нам подключить компонент?

Для начала идём в package.json и добавляем туда form­Builder. К счастью, он уже собран в виде npm-пакета, так что нам не нужно упоминать про jQuery и прочие зависимости. NPM их и так подтянет.

  "dependencies": {
    // ...
    "formBuilder": "^2.9.8",
    // ...
}

А потом создаём новый компонент и пишем:

import React, { Component } from 'react';
import * as $ from 'jquery'

class FormBuilder extends Component {
  state = { };

  componentDidMount() {
    window.jQuery = $;
    window.$ = $;
    require('jquery-ui-sortable');
    require('formBuilder');
    this.$formBuilderContainer = $(this.refs.formBuilderEditor);
    this.$formBuilderEditor = this.$formBuilderContainer.formBuilder({
        i18n: {
          locale: 'ru-RU'
        }
      });
  }
  render() {
    return (
             <div ref="formBuilderEditor"></div>
            );
    }
}

export default FormBuilder;

Добавляем на нужную страницу, запускаем… и видим, что форма на месте и даже кнопки нажимаются!

Динамически создаём React-компоненты

Иногда нужно создавать React-компонент динамически и даже в цикле. Но ren­der(), само собой, не желает выполнять циклы и начинает ругаться.

Чтобы создавать компоненты динамически, пишите по этому образцу. В зависимости от фреймворка можно заменить вызов на создание класса и отформатировать arrow-функциями.

let Block = React.createClass({
  createImage: function (image) {
    return <Image source={image} key={image} />;
  },

  createImages: function (images) {
    return images.map(this.createImage);
  },

  render: function () {
    return (
      <div className="container">
        <div className="row">
          <div className="col-sm-12 text-center">

            {this.createImages(data.images)}

          </div>
        </div>
      </div>
    );
  }
});

 

Вышел ya-api-direct 0.2.6

Как оказалось, от моего пробного gem-а ya-api-direct сделали 4 форка. В каждом добавилось что-то полезное.

Причём pull request сделал только один.

Сделал merge в проект и выпустил новую версию. Всего его скачало порядка 3000 человек. Кто все эти люди — для меня загадка.

Партнёрки, баннеры и дорвеи

На тему заработка в интернете написано столько чуши, что кто-то даже может поверить, что это работает.

Для полных лохов пишут статьи в духе “Зарабатываю $100500 каждый день”. Для лохов, которых уже пару сотен раз облапошили, актуальны статьи класса “Правда ли, что бинарные опционы развод для лохов?”. Лох читает и узнаёт, что для лохов это разводка, а умный сам кого хочешь разведёт.

Лохом он от этого быть, само собой, не перестанет.

Пользуясь тем, что этот сайт — целиком мой, я открою секрет заработка в интернете, баннеров и партнёрок.

Весь “заработок в Интернете” — разводка для лохов

Просто он бывает для совсем лохов (просмотр рекламы, разгадывание капчи) и для лохов прошареных (свой сайт с баннерами, партнёрками, проплаченными постами).

Единственный способ получить профит с сайта — это что-то с него продавать. И чтобы это покупали. Смотри доходы Амазона, Озона и прочей Алибабы.

Что же такое в этом смысле контекстная реклама или партнёрка?

Это ссылка на чужой сайт. Который что-то продаёт и может быть наверное поделится доходом.

Если пользователь щёлкнул по ней — он ушёл и больше не вернётся.

Если пользователь не щёлкнул — то от партнёрки не поступит ни цента.

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

Так что теперь вы знаете, как отличить лохов. Если в подписе фальшивого “хозяина жизни” красуется “кстати, стеклопакеты в Ярославле” — перед нами лох.

А если сервис сам показывает рекламу от твоего имени, как это делает ЖЖ, — то лох уже ты, любезный читатель.

source для virtualenv под windows

Иногда бывает нужно сделать свой, небольшой локальный Python-мирок. Например, если мы пишем на djan­go и не хотим ставить пакеты глобально.

Это очень поможет, когда намного позже мы будем собирать инсталлятор к проекту. Мы сможем одной командой pip узнать, какие пакеты нужны.

Как это делается сейчас

Python 3 научился создавать vir­tualenv штатными средствами. Вот так:

python3 -m venv /path/to/new/virtual/environment

Дальше работаем через cyg­win (как описано дальше).

Или переходим/ставим виртуалку для Ubun­tu.

Как это делалось раньше

Официальная документация по djan­go советует vir­tualenv. Действия такие:

$ virtualenv env
$ source env/bin/activate

А потом мы работаем в этой папке, как если бы именно она была у нас системной.

Но если вы вынуждены работать под Win­dows (например, такова политика компании), то это невозможно — в языке консоли Win­dows нет команды source или её аналога. Да и в Pow­er­shell она сводится к запуску скрипта в определённом контексте.

Самый лучший выход для Python 2.x — поставить cyg­win. Он ставится быстро, осваивается за несколько минут (логические диски — это папки вида /cygdrive/c/, остальное как привыкли) и позволяет писать строго по инструкции.

Правда, многих пакетов, который нам понадобятся, в нём по умолчанию нет. Поэтому надо их дополнительно поставить.

Для начала — при установке укажите, что хотите поставить Lynx. Если вы забыли — просто запустите установку ещё раз и укажите нужный пакет, он сам докачает и положет в нужную папку.

Потом ставим скрипт apt-cyg, который эмулирует apt-get.

lynx -source rawgit.com/transcode-open/apt-cyg/master/apt-cyg > apt-cyg
install apt-cyg /bin

Теперь начинаем ставить командами в духе apt-get install wget (пока wget-а нет, он будет качать через lynx)

И дальше по инструкции для Python

Ставим пакеты, настраиваем и приступаем к работе. Или просто берём готовую сборку.

В процессе установки пакетов есть риск подорваться. Если попытаться поставить их через ez_setup.py, то внезапно узнаешь, что urllib2.HTTPError: HTTP Error 403: SSL is required.

Это связано с тем, что Pip поменял правила доступа к репозиторию. И давно обзавёлся своим инсталлятором:

apt-cyg curl # если ещё не ставил
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
python get-pip.py

Далее настраиваем, как положено, и наслаждаемся vir­tualenv.

  • Создать: mkvirtualenv my-first-env
  • Запустить: workon my-first-env
  • Завершить: deactivate
  • Удалить: rmvirtualenv my-first-env

Как C и Perl захватили планету

Почему C и Perl стали стандартами в своих областях и до сих пор на коне?

Дело, конечно, не только в синтаксисе и парадигме. И даже не в простоте. C, конечно, прост, это по-человечески записанный кроссплатформенный ассемблер. Но Perl совсем не прост, это многослойная обёртка вокруг парсера регулярных выражений.

Весь секрет — в нечестных преимуществах.

Компиляторы C были под все платформы и бесплатно. А какой-нибудь Pas­cal был разный и платный.

Perl изначально создавался для работы с текстом, парсинга, преобразования и т.п. А протокол HTTP целиком текстовый. Вот и писались ранние скрипты на Perl-е.

Потом появился PHP, где были те же регулярки, но c привычными классами и он был тупо проще в освоении. И о Perl для веба стало неудобно говорить. Такое же логичное развитие Perl, как C++ — для C. И как Java — для C++.

А потом появился Python, паттерн MVC дал Ruby on Rails и всё стало как сейчас. Наконец, желание писать даже на сервере знакомым синтаксисом породило Node­JS.

Провал всех без исключения “функциональных решений” немножечко предсказуем — потому что нет области, где они были бы нужны и на голову превзошли конкурентов. Go выстрелил, потому что добавил в чистый C всё, чего там не хватало. Scala — потому что это лаконичная Java. Swift — потому что Mac.

 

Пишем Ruby gem для Yandex Direct API

Очень хотелось изучить Ruby получше, а рабочего проекта не было. И я попробовал написать gem для работы с Yan­dex Direct API.

Причин было несколько. Среди них: Yan­dex Direct API очень типичен для Яндекса и современных REST-сервисов вообще. Если разобраться и преодолеть типичные ошибки, то можно легко и быстро написать аналоги для прочих API Яндекса (и не только). И ещё: у всех аналогов, которые мне удалось найти, были проблемы с поддержкой версий Директа: одни были заточены под 4, другие под новую 5, и поддержке units я нигде не нашёл.

И вот на Хабре вышла моя статья — Пишем Ruby gem для Yan­dex Direct API.