Mysqlのスキーマと初期レコードをpdfのテーブル/マスタ定義書として書き出す

dotimpact/pdf-db-spec: mysqlの既存テーブルからpdfのドキュメントを作る


いまやってる仕事(わりと堅い)で詳細仕様書の一部としてDBのテーブル定義書を作ることになり、手でつくるのは面倒なのでDBマイグレーションツールで作成したDBのテーブルと初期データをドキュメント化する方法をいろいろ試して、最終的にMysqlのXML/HTML出力を加工してpdfにするスクリプトを作ったので公開しておいた。Mysql限定で、wkhtmltopdfも必要。

最初schema2rstを試して、Htmlドキュメントとしてはなかなかよかったんだけど、ドキュメントとして共有するのにpdf化するにはあんまり向いてなかったので、続・MySQL データベースからテーブル定義書を生成する - 私と私の猫の他は誰でも隠し事を持っているの出力をwkhtmltopdfでpdfにするアプローチにした(xsltとhtmlのスタイルはほぼそのまま使ってます。ありがとうございます)。wkhtmltopdfでレンダリングされるhtmlドキュメントのサイズがあんまりうまく制御できなかったので、--zoomで適当に拡大している。あと長いテーブルの途中で改行されるときにテーブルヘッドがちゃんと表示されるように

1
2
3
thead { display: table-header-group }
tfoot { display: table-row-group }
tr { page-break-inside: avoid }

を入れた。

あと、今回DBマイグレーションツールにPhinxを使ってみたらわりと便利でよかった。ほんとはこれのマイグレーションにフックしてドキュメントを生成できたるするといいのかな。


iOSのブラウザでは外部キーボードのカーソルのキー入力イベントが出ない

菅さんがiOSデバイスでscrapboxがうまく使えないというツイートをしていて、自分はそんなに困ってないけどなとやりとりしていたら、菅さんはiPadに外部キーボードをつなげてscrapboxを使おうとしていて、カーソルキーを使った編集作業ができないので実質使えないのだそう。手元でiPhoneにbluetoothキーボードをつないで試してみたらたしかにそうだった。

ネイティブアプリではカーソルキーが使えるのでどういうことなのかなと調べてみたら、どうやらiOSのブラウザでは(JavaScriptCoreでは?)外部キーボードのカーソルキー操作時のキーイベントが出ず、カーソルキーを使った操作の実装が不可能みたい。

Official answer from Apple:

Thank you for contacting Apple Developer Technical Support (DTS). Our engineers have reviewed your request and have concluded that there is no supported way to achieve the desired functionality given the currently shipping system configurations.

ぜんぜん知らなかった。カーソルキーはページスクロールにも関わるからタッチとの齟齬を考慮して殺してあるのかな。ちなみにAndroidは問題ないようだった。


『第2回Webメディアびっくりセール』参加WebメディアのRSS配信状況を調べた

RSSリーダーなんてメジャーなインターネットユーザーは使っていないというのは事実だろうから、そんなに声高に主張する気はないんだけど、いわゆるWebメディアと称するサイトでRSSを配信していなくて、気になるメディアだから新着情報が知りたいなと思ってRSSリーダーに登録しようとしてガクーとすることが多い気がしている。

WebメディアのくせにRSSないじゃん事案にもいくつかパターンがあって、一つはシンプルに新着RSSを生成するようなシステムになってないらしきメディアで、そういう場合はしぶしぶtwitterアカウントをフォローしたりする。あとRSSは生成されててよく見るとサイト上にはリンクがあるんだけど、RSS AutodiscoveryのlinkタグがなくてRSS周辺技術が検知できないパターン。これもまあニコニコしつつ手動でRSSを登録するわけだけど、最近目立って由々しきと思うのは、RSSは生成している(あるいは使用しているCMSがデフォルトで生成している)にもかかわらず、それを知ってか知らずかサイトで公開していないというパターン。登録しようとしてRSSリーダーがフィードを認識しない時は、とりあえず/rss/atom/feedをたたいてみて、フィードが隠れてないか探るのが定番になってきた。

なんてことをつぶやきつつ、実際WebメディアでRSSってどのくらい配信されているのか気になっていたところ、デイリーポータルZの「第2回Webメディアびっくりセールのサイトに参加Webメディアがずらっと並んでいるのを見てちょうどいいやと参加している36メディア(実際にはWebメディアではないのではというところもあったけど)のRSS配信状況を調べてみた。

第2回Webメディアびっくりセール参加WebメディアのRSS配信状況 - Google スプレッドシート

結果は

  • 1) RSS Autodiscovery率 62.16%
  • 2) RSSじつはある率 16.22%
  • 3) RSSがそもそもない率 18.92%

となった。なんとなく想定してたよりは多い気がするけど、Webメディアびっくりセールに参加するのは古株も多いしやる気のあるメディアだからかも。なんにしろRSSあるならAutodiscoveryにはして欲しいところだな…


AVAをWallaby.jsで使う

ひさしぶりに完全な新規プロジェクトでプロトを作ることになったので、「Modern JavaScript概観、そしてElectronへ」を参考に、JavaScriptの最新環境を入れて使ってみている。このエントリ、「ここまで長い解説を読み通しても終わっているのは開発の事前準備だけなんだよね…」というつぶやきも読んだけど、モダンJSの環境(トランスパイラと型システム拡張、静的解析環境、テスト、UIフレームワーク、ビルドなど)について選択肢とシンプルさを重視するようなご本人の選択と、なぜそのツールが必要なのかの解説が明快でとてもうれしい。フレームワークはまだ検討段階だけど開発環境については基本的にこの解説の通りにしてる(ボイラープレートは使ってない)。

使ってみていまのところいちばんこれいいなと思っているのはAVA。先エントリに書いてあるとおりシンプルで高速でPowerAssert、That’s itというテスティングフレームワークで、しかもこれはすでにWallaby.jsに対応している。Wallaby.jsごしでもPowerAssertのアサート情報はとてもわかりやすく表示されるので、こけたテストを直すときの手数が明らかに減ってとても快適。

ava on wallaby.js

http://dm.gl/2016/04/26/wallaby-sublime-electron-ava/ より

現状バグがあるのかAVAのコールバックモード(test.cb)だと挙動が怪しいけど、これはPromiseを使えば解決するのでPromiseを使うための強制ギブスになるのも結果オーライだった。


Webpackモジュールのプライベート関数をユニットテストしたい

レガシーなJavaScriptソースをWebpackでビルドできるようにモジュールに切り分けてテストを書くことをしている(わりとヒマなので)。

jsモジュール内の機能をプライベート関数に分割して書く場合に、そのプライベート関数部分の単体テストを書きたい場合があると思うんだけど、それをどうやればいいのかわからなくていろいろ調べた。

unit testing - How to access and test an internal (non-exports) function in a node.js module? - Stack Overflow

こういう話で、ここではrewireを使えという事になってるんだけど、これはうまくいかなかった。rewire-webpackというのもあるんだけど、これもだめだった。

でうまくいったのは、exports-loaderでプライベート関数を指定してエクスポートする方法で、

1
2
3
4
5
6
7
8
9
10
11
function privateFunc() {
return "private";
}
function exportFunc() {
return "export";
}
module.exports = exportFunc;

こういうモジュールのテストを

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
describe('test', function() {
it('モジュールのテスト', function() {
var exportFunc = require('export-module.js');
expects(exportFunc()).toBe('export');
});
it('プライベート関数のテスト', function() {
var privateFunc = require("exports?privateFunc!./export-module.js");
expects(privateFunc).toBe('private');
});
});

こんな感じにしたらうまくいった。


ハイブリッドチャットUI

LOHACOのAI「マナミさん」すごすぎ。6.5人分の人件費を削減した実例公開 - BITA デジマラボ」という記事を見てどんなもんだろうと思ってLOHACOのマナミさんを見てみた。要するにFAQやマニュアルの検索に対話型インターフェイスをかぶせたようなものなんだけど、アバターからレスポンスが即座に、適度な量返ってきて、やりとりの中で欲しい情報への絞込が自然に行えるようなものになっていれば、大げさな技術がなくてもたしかに効果ありそうだなーと感心した。

もうひとつ感心したのはチャット風の吹き出しメッセージとボタンなどのGUIが混在した独特のUIになっているところで、チャットベースだからって全部テキストで指示するんじゃなくて状況に応じたGUIが提示できるようになってればいいわけで、これもこういうのでいいんだなーと思った。

チャットボットAPIもこういうふうになっていくのかなーと思って試しにイメージをつくってみたんだけど、

スマホサイトでLINE風の幅可変ページを作成する | Creator Clip」を改変

調べてみたらふつうにFacebook Messenger PlatformにはボタンとかカードのUIを表示する仕組み(Structured Template)があった。そりゃそうか。

Send API Reference - Messenger Platform


devdによるクロスプラットフォームのローカルjsアプリ配布

cortesi/devd

最終的にサーバで動作するjsアプリをローカルで開発/テストしてもらおうとすると、ローカルファイルとして開くと他のローカルコンテンツをajaxで取得するのに制約があるのでちょっと策を講じる必要がある。開発者ならpowを使うなり好きな方法でローカルサーバごしにアクセスしてもらうようにすればいいけど、非開発者でwindowsユーザのことも考えるといろいろインストールさせる説明をするのが憂鬱だしChromeをオプション付きで起動というのも大げさな感じ。マルチプラットフォームで実行ファイルから簡単に立ち上げられるローカルサーバないのかなと探していてdevdというgo製のシンプルなwebサーバを見つけた。これでいけそう。

アプリのデータを置いたディレクトリにdevdもいれておいて、windowsなら

みたいなバッチファイルを開いてもらえばdevd.io:8000でローカルサーバごしにjsアプリを触れる。

OSXはこう。

-lオプションもつけるとファイル更新時にリロードしてくれるんだけど、これはまだ不安定なのか環境によってはクラッシュするみたいだったので今は外してある。


iframe内のsvgではfillパターンが使えない(バグ?)

先日開発ではまったやつ。iframe内のhtmlページに方眼線のようなものをsvgで作って敷こうとしていたら、通常のhtmlなら問題ないsvgがiframe内だと正しく表示されない。いろいろ試した結果、svg内で登録したパターンを塗りつぶし色として使うfillパターンがiframe内だと適用されないのがわかった。これバグなのかな。

とりあえずfillパターンでの繰り返しじゃなくてsvgのユニットをbackground-imageのリピートで敷き詰めるようにしてみた。


AspectMockを使うクラスでyieldを使ってるとき

AspectMockでモッキングするクラス(に依存するクラス)でyieldを使ってると、AspectMockが注入するコードがreturnで値を返そうとするためエラーになる。

PHP Fatal error:  Generators cannot return values using "return" in /...

とりあえずキャッシュコードのreturnをyieldに変えて動かしてたけど、もうissueになっててdev-masterでは解消されているっぽい。

Generators result in fatal error · Issue #50 · Codeception/AspectMock

Composerでdev-masterのモジュールをインストールする(”minimum-stability”: “dev”にしてもいいけどこれだと全モジュールのdev-masterが入る)

"require-dev": {
   ...
   "codeception/aspect-mock": "dev-master"
   ...
}

上記修正は返り値のキーワードをPHPDOCの@returnで判別するものなので、AspectMockのキャッシュを消して、yieldを使ってるメソッドのPHPDOCの@returnに \Generator を書く(Generatorだけだとだめだった)

/**
 * @param $name
 * @return \Generator
 */
public function generatorMethod($name)

これで動いた。AspectMock黒魔術感あってハマると苦しい…。