ryhmrt’s blog

意識低い系プログラマの雑記

livedoor to はてな

少し前までlivedoorのブログを使っていたのですが、管理画面がなんかイケてないような気がしたのと、同じサービスばかり使っていて飽きたので、はてなに移行してみました。

こんな時に独自ドメインで運用していると、何の気兼ねもなく移れて気持ちが良いです。 個別記事へのリンクが途絶えたりなんて小さいことは気にしてはいけないのです。

ざっと触ってみた感じ、livedoorブログよりも使いやすい感じがします。 料金はlivedoorの倍以上ですが、おおむね満足です。

Gitで差分ファイルをZipに固める

いろいろなオトナの事情でお客さんのリポジトリに直接アクセスできなかったりすると、差分ファイルを作ってZipに固めて渡すとかいうことがあります、というか現在進行形でやっています。

Gitの --name-only オプションで差分ファイルの一覧を取って、Zipの -@ オプションでアーカイブするファイルを指定するのが便利だったのでメモを残しておきます。

次に差分を出すときのために差分出したらタグを打ちましょう。

$ git diff Release20150729 --name-only | zip diff.zip -@

PostgreSQL 8.2 の暗黙の型変換の罠

はじめに

PostgreSQL 8.2 を使ったプロジェクトに携わることになったのですが、他のミドルウェアのバージョンの関係で手元にできあがったのが PostgreSQL 8.4 の環境になりました。

ダウングレードするのは面倒くさいし、大してバージョンも違わないから大丈夫だろうとタカを括ったら思いの外動きませんでした。

問題点

PostgreSQL 8.2 までは暗黙の型変換でいろいろなデータが文字列型に変換されて実行されるケースがあったのですが、PostgreSQL 8.3 からはそんな汚い動作はしないようになったそうです。

そのため、PostgreSQL 8.2 までは実行できたクエリも、PostgreSQL 8.3 以降では型エラーで実行できないケースがあるとのこと。

例えば select length(1); とか実行すると、PostgreSQL 8.3 以降では以下のようなエラーが出るはず。

ERROR:  function length(integer) does not exist at character 8
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
STATEMENT:  select length(1);

解決方法

将来的にPostgreSQLのバージョンアップとかもあるかもしれないし、と思い、PostgreSQL 8.4 で動くようにすることにしました。

自動キャストの設定を追加することである程度 PostgreSQL 8.2 の動作を再現できるということなので、まずはそれを設定。

そもそも型変換する必要がない箇所もあったので、そこはクエリをちまちま修正。

見事動作致しました。

本当は型変換が頻繁に発生しているのはおかしいので、根本的にデータ構造を見直さなきゃいけないんだろうけど...

参考

CakePHP3のメッセージ定義でJavaScriptを多国語化

フィリピンでシステムを作って日本に納めるために、英語版を作って日本語化するというアプローチを取っているのだけれど、React.jsをシステムに取り入れたところJavaScriptローカライズする必要が生じて、えいやっとやってみました。

これで CakePHP と同じように __('Hoge') という感じでローカライズできるようになります。

同僚からは笑われましたが、ローカライズはお前の担当だから好きにしろとのことなのでこいつを正式採用することにします。

無駄に力を入れて、メッセージ定義ファイルから生成したJavaScriptをキャッシュしているのが個人的なネタポイントです。

ちなみに、一般公開するページと管理者用のページを分けていたりする場合は、メッセージの内容で中身を推測されてよろしくない事態が発生するかもしれないので、そんなときはメッセージ定義を分けるとかすると良いと思ったり。

app/src/Controller/JsController.php

以下のファイルを作成。

<?php
namespace App\Controller;

use App\Model\Table\StudentsTable;
use Cake\Cache\Cache;
use Cake\I18n\I18n;
use Cake\I18n\MessagesFileLoader;

class JsController extends AppController {

    public function initialize() {
        parent::initialize();
    }

    public function i18n() {
        $this->autoRender = false ;
        $this->response->type('js');
        echo $this->_getI18nJs(I18n::locale());
        echo "\n";
    }

    private function _getI18nJs($locale) {
        $cacher = Cache::engine('_cake_core_');
        $key = "js.i18n.$locale";
        $js = $cacher->read($key);
        if (!$js) {
            $js = $this->_generateI18nJs($locale);
            $cacher->write($key, $js);
        }
        return $js;
    }

    private function _generateI18nJs($locale) {
        $messages = $this->_readLocaleMessages($locale);
        $messages = array_filter($messages, function($message){ return !empty($message); });
        $messages = array_map(function($key, $message){
                return  "'" . preg_replace("/([\\\\'])/", "\\$1", $key) . "':'" . preg_replace("/([\\\\'])/", "\\$1", $message) . "'";
            }, array_keys($messages), $messages);
        return '__ = (function(messages){return function(key){ return messages[key] ? messages[key] : key; }})({' . implode(',', $messages) . '});';
    }

    private function _readLocaleMessages($locale) {
        $loader = new MessagesFileLoader('default', $locale);
        $package = $loader->__invoke();
        return $package->getMessages();
    }

}
?>

app/config/routes.php

以下の記述を追加。

Router::scope('/js', function($routes) {
  $routes->extensions(['json', 'js']);
  $routes->connect('/:action', ['controller' => 'Js', 'action' => '(:action)']);
});

app/src/Template/Layout/default.ctp (もしくは他のレイアウトファイル)

以下の記述を追加。

<?php echo $this->Html->script('i18n.js'); ?>

Git 2.4

一週間ぶりくらいにMacPortsを更新したらGitの2.4が振ってきた。

Gitは既に誕生から10年を迎えたらしい。前職から使ってたから自分が使っている期間もそこそこになる。

Atomic Pushes

複数のブランチをpushするときに、一つでもpushが失敗したら他のpushも取り下げるようなことができるようになった。--atomicオプションを使用して以下のようにpushする。

$ git push --atomic origin branch1 branch2 ...

Push-to-deploy の改善

Git 2.3 で導入されたPush-to-deployについて以下の改善が施された。

  • push-to-checkoutフックの追加により、pushされたブランチに対してサーバ側のワーキングツリーに変更があった場合の挙動を定義できるようになった。
  • コミットが一つもないブランチに対してもPush-to-deployが正常に設定できるようになった。

自分はPush-to-deployをまだ使ったことがないので、これらの改善点の嬉しさがいまいちわからない。

git log の --invert-grep オプション

git log コマンドのオプションの --grep=<pattern>, --author=<pattern>, --committer=<pattern>, --grep-reflog=<pattern> それぞれのパターンに一致しないものを検索するためのオプション --invert-grep が追加された。

例えば以下のようにして、自分以外のコミットを確認できる。

$ git log --invert-grep --author=Ryohei

該当するコミットのSHA-1ハッシュだけをリストする git rev-list コマンドをネストすることで、複雑な検索が可能になる。

以下はRyohei、Keisuke、Gissan以外のコミットを検索するコマンド。--stdin--no-walk オプションと共にパイプして、最後だけ git log にする。

$ git rev-list --no-merges --invert-grep --author=Ryohei master |
      git rev-list --stdin --no-walk --invert-grep --author=Keisuke |
      git log --stdin --no-walk --invert-grep --author=Gissan

git status -vv

git status コマンドに -v オプションを2つ付けると、コミットされていない変更差分が一緒に出力されるようになった。git status に続けて git diff --cachedgit diff が出力されてる感じ。

参照

自分は一時情報としてブログ記事 Git 2.4 — atomic pushes, push to deploy, and more を参照しました。

詳細はGit 2.4 リリースノートを参照。

PostgreSQLのスロークエリ追跡

最近 PostgreSQL でシステム運用をしていて便利だったのが postgresql.conf にある log_min_duration_statement という設定。

実行時間がこれに設定したミリ秒を超えるクエリはログファイルに吐き出されるようになる。

以下のように設定すると100ミリ秒を超えるクエリがログ対象となる。

log_min_duration_statement = 100

ログファイルのデフォルトの場所はディストリビューション毎に違うようだ。Debian系は /var/log/postgresql に、RedHat系はデータフォルダ以下にある感じがする。

ちなみに、 auto_explain という追加モジュールもあって、こっちを使うと EXPLAIN した結果も一緒にログに記録してくれるらしい。

Git 2.3

MacPortsのパッケージをアップデートしたら Git 2.3 が降ってきた。 メジャーバージョンアップになるので新機能や変更点を確認。

個人的に気になったのは以下2点。

Push to deploy

Gitで管理してるプロジェクトをサーバにデプロイするとき、サーバで git pull して更新するような運用をしている場合、新しい機能を使うと自動的に更新を push できるようになるらしい。

以下のコマンドをサーバのGitリポジトリで実行すれば自動更新が始まるとか。

$ git config receive.denyCurrentBranch updateInstead

後は githooks の post-update あたりで必要なサービスの再起動とか実行すれば良いのかな。

2年くらい前に立ち上げたサーバに git pull を cron で定期実行してるやつがあるので、そいつをこれに変更したい。

git branch -d supports a --force/-f option

これからは git branch -D hoge じゃなくて git branch -df hoge で強制削除できる。

参照