| @技術/プログラミング

CircleCI.png

もうすぐ Ruby 2.5 が出そうだけど、このブログの Ruby のバージョンを 2.4 に上げた。

Ruby 2.4 がリリースされたあとすぐに Lokka を Ruby 2.4 に対応させようと頑張ってみたのだけど、 Ruby 2.4 に上げるためには ActiveSupport のバージョンアップが必要だった。しかし padrino-helper 0.11.4.1 が古いバージョンの ActiveSupport に依存しており、 Ruby 2.4 に対応した ActiveSupport を利用するためには padrino-helper をバージョンアップする必要があった。 padrino-helper をバージョンアップしてみると 0.12 から大幅な変更が入ったようで、ビューの表示がぐちゃぐちゃになった。 layout が適用されず中身の partial ビューだけ表示されたり、 HTML が過剰にエスケープされたり。 padrino-helper は 0.11 時代にあった脆弱性を修正して標準ですべての文字列出力を escape するようになったっぽい。しかし Lokka の方がそれに対応できておらずビューがぐちゃぐちゃになっているようだった。

Lokka はヘルパーメソッドやモデルで HTML を文字列から生成しているところがあって、そういうところをこまめに html_safe していったところ余分なエスケープは解消されていった。利用している gem でも文字列から HTML タグを生成しているところがあったので、そういうところもつぶさに調べていって無心で html_safe したり mark_safe していった。

とりあえずこのブログを Ruby 2.4.2 でしばらく運用してみて問題なかったら Lokka 本体の方に Pull Request を出すことにしよう。

あと今回ついでに CircleCI でテストしてテストが通ったら勝手に Production に deploy されるようにしておいた。 CircleCI ほんと便利。

追記 2017-12-03

Pull Request 出しておきました。

| @ブログ

このブログ( Lokka )の DB は MySQL を使っている。 MySQL のバージョンは 5.7 なので、 column encoding を utf8mb4 、 collation を utf8mb4_general_ci とかにしておけば emoji を使えるかと思ってたけど使えなかった。長らく DataMapper が 対応してないかと思ってたけどリポジトリを覗いてみたら随分前に対応されてた。どうも Lokka 側に問題があるっぽい。

Lokka の DB 接続設定は dsn を URL として記載するようになっている。 DataMapper は ActiveRecord のように Hash オブジェクトを DB 接続の引数に渡せるので、 encoding: 'UTF-8-MB4' をオプションとして渡せるようにしてやればよいっぽいが、いまの Lokka のコードでは encoding オプションを指定できないのでこれではダメっぽい。

ちょっと Lokka 側のコードをいじって encoding オプションを渡すようにしてみたところ無事 emoji が使えるようになったので lokka/lokka に Pull Request 出しておこう ⌨️

| @技術/プログラミング

ブログの管理画面にファイルアップロード機能をつけてみた。 GitHub の Issue みたいにドラッグアンドドロップでアップロードしてくれる。こんな感じ。

file upload demo.gif

いまのところ埋め込みフォーマットは Markdown にしか対応してない。

Lokka は heroku とか PaaS を使うことを前提に作られているのでファイルをアップロードする機能が提供されてこなかった( heroku は永続的なファイル書き込みができない)。 heroku で動かしている人でも使えるように Amazon S3 に上げるようにしてみた。 AWS のアカウント作成とかが必要なのでレンタルサーバーに設置してある WordPress にファイルアップロードするのに比べたら敷居が高いけど、設定するのは1回だけだし全くアップロードする手立てがなかったこれまでに比べたら劇的に快適になるはず。自分で使ってみたけどめっちゃ便利になった。

ファイルアップロード、ちゃんと作るなら Paperclip みたいにファイルのチェックを厳密に行なわないと危ないと思うけど、管理画面から上げるの前提なのでチェックなしで雑にアップロードできるようになっている。 AWS の token 系の設定画面を作ったら Lokka 本体に Pull Request 出します。

なお一つ前の記事でアプリケーションサーバーを puma に変更 - portal shit!というのを書いたけど、このファイルアップロード機能がうまく動かなかったので unicorn を捨てたのだった( pow で動かしている環境や bundle exec rackup して WEBRick で起動しているサーバーではちゃんとアップロードできる)。なぜか unicorn で multipart/form-data な POST リクエストを rack アプリケーションに適切に渡すことができず EOFError が発生してしまう。

仕事で unicorn で動いてるサーバーにファイルアップロードする仕組み入れたことは何度かあるけどこんなエラーになったことはなかったのになぁ。謎い。

| @技術/プログラミング

ブログのアプリケーションサーバーには unicorn を使っていたのだけど puma に変えてみた。

2011 年から使っていたようなので丸 5 年は unicorn を使っていたことになる。 puma はスレッドセーフにしないと死ぬ、ということは聞き及んでいたのでおそるおそる変えてみたけどいまのところ問題なさげ。

手元で確認したときには scss のコンパイルで怪しい雰囲気があった(特定ページにアクセスしたあとレスポンスを返さなくなってしまう)ので 0.12.7 だった compass のバージョンを 1.0.3 に上げてみたところ問題が解決した。結果オーライということで深追いはしてないけど、リポジトリを見に行ってみたらメンテナンス停止しているようだった。最近はフロントエンドは JavaScript でやるのが当たり前ですもんね。

Lokka のフロントエンドは 2010 年頃ナウかった Ruby ベースの技術が満載で最近の傾向とは異なるので、フロントエンドで利用してる gem がメンテされておらず Ruby のバージョンアップ時のボトルネックとなってくることが考えられる。この前 Ruby 2.4.0 で動くか素振りしてみたけどダメだった。padrino-helpers 、 slim 、 haml 、 coffeescript (この機能は自分が追加した)あたりとどういう風に折り合いを付けていくか考えないといけない。

| @ブログ

Lokka の管理画面をスマートフォン対応させた。携帯から記事を投稿したりスパムコメントを削除したいなと思うことがあっても Lokka の管理画面はモバイルフレンドリーではなくて非常に厳しかった。とても便利になったと思う。ドッグフーディング最高。

専業フロントエンダーではないのでマークアップと CSS コーディングは適当だけどこの様に寝床でごろんとしながらでも駄文を投稿できるようになって便利。 Lokka ご利用中の方はご活用ください。

ダッシュボード 記事一覧 投稿画面

| @技術/プログラミング

糸島の海

自作の Lokka プラグインに Amazon の Product Advertising API に問い合わせてアフィリエイトリンク付きの商品画像を返すやつがある。 Amazon 上の商品管理番号を <!-- ASIN=XXXXXXXX --> みたいな感じで本文中に書いとくと良い感じに小銭を稼げるかたちのリンクにして画像を表示してくれるという便利なやつ。

Amazon の規約上、 Amazon Product Advertising API に対しては一秒間に一リクエストしか送ってはいけないことになってるので、データを取得する度に 1 秒 sleep するようにしていたけど、一ページ内で複数のリンクがあるときにキャッシュがエクスパイアして Amazon の API を叩くとめっちゃレスポンス遅くなってださかったので非同期で取るようにした。ページコンテンツ本体はサクッと返して、商品情報などの取得はページがレンダリングされたあとに JavaScript で行う。 Amazon から JSON を取ってくる処理自体は Ruby にやらせる。

+----------+            +----------------+             +--------------------------------+
|          | +--------> |                | +---------> |                                |
|  client  |            |  Ruby (Lokka)  |             | Amazon Product Advertising API |
|          | <--------+ |                | <---------+ |                                |
+----------+            +----------------+             +--------------------------------+

最初は雑に body の innerHTML を正規表現で replace したりしてたんだけど、そうすると Twitter のウィジェットなど本文内に埋め込んである script タグが動かなくなる問題に気がついた。 HTML 5 の仕様で、 innerHTML = で挿入されたコンテンツの script タグは無視されるらしい。なるほど〜。

ということでもうちょい調べたら DOM には Node.nodeType というプロパティがあって、COMMENT_NODE など type を持っているらしい。

<!-- ASIN=XXXXXXXX -->COMMENT_NODE として扱われるので、こいつの後ろに document.createElementして JavaScript で動的に生成された要素を突っ込むようにした。 Promise を使ってナウでヤングな感じに書いた。

let promise = new Promise(function(resolve, reject) {
  request.open('GET', url);
  request.onreadystatechange = function() {
    if (request.readyState != 4) {
      // リクエスト中
    } else if (request.status != 200) {
      // 失敗
      reject(request.response);
    } else {
      // 取得成功
      let formatter = new Formatter(request.response);
      let result = formatter.formatItem();
      resolve(result);
    }
  };
  request.send();
});
promise.then(function(result) {
  let previous = node.previousSibling;
  let parent = node.parentNode;
  let d = document.createElement('div');
  d.className = 'amazon';
  d.innerHTML = result;
  parent.insertBefore(d, previous.nextSibling);
}).catch(function(error) {
  console.log(error);
});
return promise;

意地でも jQuery 使うまいと思ってやってみたけど意外と大丈夫だった。楽をせずに素の JavaScript を書いていると精神が浄化されるような感覚があってよい。写経に通じるものがある。写経やったことないけど。

| @ブログ

一時期に比べたら Lokka 使ってる人減ってて、 Jekyll/Octopress ブームのあとは Go lang 製のスタティックサイトジェネレーターかはてなブログに移っていってしまった。自分は自分で使うツールを自分でいじるのが好きなので Lokka 使い続けていきたい。ということでいろいろやった。

最近やったこと

テスト通るようにした

Lokka の master ブランチ、しばらくコミットされてなくて Travis CI のビルド 1 年半くらい走ってなかった。久々に Pull Request 出したらビルド成功しなかったので通るようにした。 Travis がコンテナベースの環境から Docker ベースに移行したぽくて、その影響で PostgreSQL がらみで bundle install がこけるようになってた。なのでテキトーに addon を追加しといた。

同じコミットでもうメンテナンスが終了している Ruby 1.9 系の CI をやめるようにした。

Ruby 2.2 に対応させた

json 1.5.5 は Ruby 2.2 系では install に失敗するようなのでいろいろ bundle update した。 ActiveSupport も 3.1 ではエラーが出てしまうので bundle udpate して 3.2 の edge にした。

XSS 直した

コメントで教えてもらったので直した。

ただ実はまだ完全には直せてないので近日中に直したいのだけどテンプレートをレンダリングする仕組みをまるっと変えないと直らなそうなので結構きびしい…。

これからやりたいこと

フロントエンドよくしたい

具体的にはプラグインに同梱された CSS や JavaScript とテーマのやつをくっつけて配信したい。 Asset Pipeline 的な。

高速化

なんか遅い。このブログのトップページのレスポンス返すのに 1 秒くらいかかってるの改善したい。 DB にインデックス張るのとクエリのチューニングかな。

ActiveRecord 化

Fjord の皆さんで開発が続けられていたけど停滞しているっぽい。 DataMapper 、耐えられないほど不便なわけでもないし ActiveRecord にない便利な機能もあるのだけど、 N+1 起こらないという触れ込みなのに N+1 起こったり、ちょっと込み入ったクエリを投げたいと思ったときにやり方がわからないもしくは出来ないということがあるので、 Ruby エンジニアの皆さんが日常的に使ってる ActiveRecord を使うようにするのが良いだろうと思った。そもそもあまりメンテもされてないし、 DataMapper に引きずられて Lokka が停滞するのも残念だし。高速化のためにも ActiveRecord 化有効そう。


最近「仕事外でコードを書かないエンジニアは人間のクズだ」、「いやクズはそっちだ、エンジニアの業務時間外の学習に依存する会社こそ真のクソ」みたいな議論多いけど、自分で使うツールのメンテナンスくらいやらないと本当にプログラマー廃業しないといけない気がするし、自分がプログラミングに触れたの自体 P_BLOG の改造がきっかけだったので、プライベートを犠牲にして歯を食いしばりながら取り組んでいきたい。