Обновление ViewModel в ExtJs 5

Sencha добавила в ExtJs 5 крайне удобную концепцию — ViewModel. Она позволяет динамически связывать данные с представлением. Причём данные могут зависеть друг от друга и вычисляться по сложным алгоритмам. Результат кешируется, и до тех пор, пока исходные данные не поменяются, конечный результат пересчитываться и обновляться не будет. Обязательно посмотрите, если ещё не сталкивались, — очень удобная штука.

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

Делюсь заклинанием:

viewModel.getRoot().descend(['info']).formula.react();

Эта конструкция заставит ViewModel пересчитать значение info и обновить все связанные View. Просто подставьте название вашей формулы вместо info.

Проверено на ExtJS версий 5.0 и 5.1. Пользуйтесь и не позволяйте мелочам портить настроение.

Apple

Не так давно я сменил место работы. И теперь я провожу треть своей жизни, работая с устройствами хорошо известной фруктовой компании. А учитывая, что раньше я с ними дела не имел, хочу поделиться своими впечатлениями.

Ну конечно, сразу было непривычно, да и сейчас тоже. Это всё микроклавиатуры, мышки с одной сенсорной кнопкой и ⌘C вместо Ctrl+C. Хотя, как говорится, привыкнуть можно ко многому. Но есть некоторые вещи, к которым привыкать совсем не хочется. Поэтому я нашёл в интернете грязный хак, который позволяет назначить переключение раскладок клавиатуры на CapsLock (или , как он нарисован на клавиатуре). Кстати, такого же хака, но чтобы переключать как в винде Ctrl+Shift или Alt+Shift, не существует.

А ещё напрягает отсутствие нормального файлового менеджера, однопанельный брат эксплорера из Windows не слишком приспособлен для работы без мышки. Зато все красиво, это да.

Приложения ставятся по большей части как Windows — скачал и запустил установку, малая часть из того, что требуется, есть в App Store, где они могут централизованно обновляться. Все-таки идеология работы с пакетами и менеджером пакетов (apt), как в давно уже ставшей родной Kubuntu, мне гораздо ближе.

За полторы недели работы я пока не увидел никаких особых преимуществ у Maс OS X по сравнению с другими операционными системами, кроме красивого логотипа при загрузке. А так, Google Chrome, какой-нибудь продукт производства JetBrains и что ещё требуется мне как Web-разработчику?

XMLHttpRequest, Content-Type и Content-Length: 0

Когда в из JavaScript отправляешься AJAX запрос1, ставишь ему заголовок Content-Type: application/json, но при этом оставляешь само тело запроса пустым, то браузер самостоятельно заменяет Content-Type на тот, который кажется ему более подходящим. Причем для Google Chrome это application/xml, а для Firefox — plain/text. А сервер смотрит на это безобразие и отвечает — 415 Unsupported Media Type, у него-то стоит проверка на заголовок Content-Type.

Как вариант решения отправлять пустой объект {}. Ну или поправить сервер, если есть такая возможность.


  1. DELETE в моем случае

MySQL, InnoDB и TEXT

Совершенно неожиданная проблема вылезла со стороны InnoDB. При записи реальных данных в таблицу сервер начал выдавать ошибку 1118 — «Row size too large».

Если кто не знает, MySQL хранит все данные вместе в одной строке-блоке, кроме данных типов TEXT и BLOB. Вместо них хранится ссылка на местоположение реальных данных. Вот и считаем сумму всех данных в строке — она не должна превышать некоторого значения. Если посмотреть в документации, можно увидеть, что максимальная длина строки для MyISAM — 64 килобайта, а для InnoDB — около 8000 байт.

Я как-то уже встречался с подобной проблемой, поэтому представлял, что делать: открываем таблицу, смотрим типы колонок, разбираемся, что можно заменить на TEXT или BLOB. Каково же было мое удивление, когда в нужной таблице оказалось 2 числовых поля и 40 полей с типом TEXT. Ну никак этот набор данных не может превышать 8Кб! Интерес добавляло еще то обстоятельство, что на тестовых небольших данных всё работало, данные записывались и гармония царила.

Оказывается, у InnoDB два формата хранения данных — Antelope и Barracuda. И у Antelope есть интересная особенность: текстовые поля хранятся не совсем так, как мы привыкли думать. У них первые 768 байт попадают в саму строку и только затем, если данных оказалось больше, ставится ссылка на остаток. Понятное дело, что 768*40 значительно превышает отведенные 8 килобайт. Так же понятно, почему всё хорошо работало на небольших объемах данных: все помещалось в строку и без всяких ссылок.

Мы решили эту проблему, выбросив все текстовые поля и заменив их одним, в котором все данных хранились в сериализованном виде. В интернете в качестве решения предлагался еще варианты разбить таблицу на несколько или сменить тип хранилица InnoDB.

Вот так живешь себе и не знаешь с какой стороны упадет сюрприз.

Subversion и хранение ревизий

Многие знают, что Subversion хранит историю в виде списка разниц-дельт между различными версиями файла. Это и понятно: обычно изменения в файлах происходят не глобальные и небольшое описание разницы будет занимать значительно меньше места. Но тут возникает вопрос, как сервер извлекает информацию из истории. Можно предположить, что самая свежая версия файла хранится целиком, а предыдущую можно получить, применив изменения (reverse-patch) к самой свежей версии. Но что делать, когда нужно посмотреть вариант, который был 100500 ревизий назад? Не зависнет ли сервер на этом действии? Кроме того, при таком подходе во время сохранения нужно изменять 2 файла: записать новый целиком и заменить старый на дельту.

Или еще вариант: делать всё в обратную сторону. Т.е. хранить не последнюю ревизию, а просто разницу. Тогда запись значительно упрощается, но вместе с тем чтение файлов с длинной историей превращается в ад. Я бы навскидку предложил добавить какие-нибудь контрольные точки, например, каждые 128 ревизий держать целую версию файла. Это не должно сильно увеличить время записи, но вместе с тем время поиска возрастет в разы. Кстати, примерно так поступают кодировщики видео, что обеспечивает возможность перемотки.

В любом случае, вариант, воплощенный на самом деле, во много раз лучше. Он называется skip-deltas. Приведу картину из документации.

0 <- 1    2 <- 3    4 <- 5    6 <- 7
0 <------ 2         4 <------ 6
0 <---------------- 4
0 <------------------------------------ 8 <- 9

Например, нам нужно записать ревизию 60. 6010 = 1111002. Правую 1 заменяем на 0 и получаем ревизию, относительно которой нужно построить разницу, т.е. 1110002 = 5610. Ревизия 0 для всех файлов одинаковая и соответствует пустому файлу. Вот и получаем быстрый доступ к любой ревизии на репозитории практически любого размера.

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

← Старше