全国1億3千万の設定ファイルフリークの皆さんこんにちは。 手動管理するような設定ファイルフォーマットで JSON ライクなのを欲しいなと以前から思っていたので書いてみました。
コメント、ケツカンマ、ヒアドキュメント、クオート不要なキー、2/8/16進数リテラルが書ける JSON をイメージしてもらえれば問題ないはず(詳細は spec 参照)
{
email: "foo@example.com",
password: "s3cret",
}
現状 Perl 5 実装しか無いですが、他言語のイシューを dotconfig/specに登録していただければ organization に招待します。 普通に parse してるだけなのでほぼ写経でも移植できるくらいにはなっていると思います。 こういった仕様系では珍しくテストケースも用意したので気軽に開発できますね。
実装も仕様も詰めが甘々なので(主に例外処理など)何か妙な挙動や矛盾があれば patches welcome なのでお気軽にどうぞ。
明日は bayashi さんのワンライナーです!
Perl Advent Calendar 24 日目の 2 記事目です(厳密)
カジュアルに HTTP サーバを建てるコマンド PAD の紹介をします。
Plack::App::Directory
の略です。
数年前 YAPC の LT-THON で話しただけで文字起こししていなかったネタですが、一部界隈では細々と使われているようです。
使い方は至って簡単で、インストールして起動するだけです。
$ cpanm PAD
$ pad
HTTP::Server::PSGI: Accepting connections at http://0:5000/
これでカレントティレクトリ以下がポート 5000 でサーブされるようになります。ポートを変えたい場合は次のように。
$ pad Static --port 8080
プラグインを実装すれば特定のファイルに処理をかませたレスポンスを返せます。
デフォルトで Markdown Plugin が入っているのでこれを真似て実装すれば、
などなど夢がひろがりんぐですね。
CLI のインターフェイスの悪さがあって、変えたいと思いつつも解決策が思いつかないのでいい感じなインターフェイス作れそうならぜひパッチください。
あたりを解決できたら嬉しい感じ。
plackup -MPlack::App::Directory -e 'Plack::App::Directory->new->to_app'
よりタイピング量 95% 減で便利。
ちなみに PAD と何の関係もないですが、 データベースのコネクション管理は DBIx::Handler がロバストな実装になっているのでおすすめです。
明日は大取り @songmu さんによる神エントリーです。
全国1億2000万の Docker ファンの皆さんこんにちは。
MySQL の起動がとてつもなく遅いのは有名な話。 ところが Docker コンテナの起動はなかなか早いので、 MySQL を使っているようなテストを高速化するケースで有用性が認められるのではないかと思って PoC を書いてみた。
(宣伝)こういった話も含めて YAPC でトークしたいので SNS 等で upvote お願いします: ( ✌'ω')✌ 楽しいモデル層開発 - YAPC::Asia Tokyo 2014 (宣伝おわり)
MySQL を使ったテストをする場合、だいたい次の 2 パターンになる。
DROP TABLE
や TRUNCATE
でクリーンな状態にして使うだけど、「起動が遅い」「setup/teardown に時間がかかる」「並列にテストできない」といった問題を抱え、最終的にはスローテスト問題に帰結する。
都度 MySQL を使うようなテストは MySQL の起動が高速化さえすれば既知の問題は解消でき、更にそのままテスト時間の短縮に繋がる。
そこで Test::Docker::MySQL を PoC として書いてみた。結果としては、
と、トータルのテスト時間は相当短縮できる結果になって今後の方針に影響を与える結果になった。
ドキュメントに書いてあるとおりに docker をセットアップすれば次のように使える。 Docker Hub 便利。
use Test::Docker::MySQL;
my $dm_guard = Test::Docker::MySQL->new;
my $port = $dm_guard->get_port;
my $dsn = "dbi:mysql:database=mysql;host=127.0.0.1;port=$port";
my $dbh = DBI->connect($dsn , 'root', '', { RaiseError => 1 });
ポイント
Test::Docker::MySQL#get_port
で docker run ...
が走る
Test::Docker::MySQL
のインスタンスがスコープを抜けると docker kill ...
を自動的に実行してくれる
だいたい次のようになって、インスタンス起動数が増えるごとにどんどん差が広がる。
Test::Docker::MySQL
$ cat tdm.pl
use Test::Docker::MySQL;
my $dm_guard = Test::Docker::MySQL->new;
my $port_1 = $dm_guard->get_port;
my $port_2 = $dm_guard->get_port;
$ time perl tdm.pl
real 0m4.020s
user 0m0.134s
sys 0m0.059s
Test::mysqld
$ cat tm.pl
use Test::mysqld;
my $mysqld_1 = Test::mysqld->new(
my_cnf => { 'skip-networking' => '' }
);
my $mysqld_2 = Test::mysqld->new(
my_cnf => { 'skip-networking' => '' }
);
$ time perl tm.pl
real 0m30.291s
user 0m1.002s
sys 0m1.200s
docker run ...
コマンドが戻った直後には実は MySQL に接続できなくて、 1.2 秒後くらいに接続できるようになる。
なので、ライブラリの内部では 0.2 秒ごとに接続をリトライしている。
原因がわかっていなくて、 port forwarding か何かがネックになっているのかとか邪推しているけど、理由知っている人がいたら教えて欲しい。
Rails 使ってもいいんじゃないかと思えるケース、個人的にはだいたいこんな感じ。
どれかひとつでも当てはまれば使うメリットありそう。
MVVM パターンの ViewModel にフォーカスしたライブラリ。結構便利。
Wikipedia に書いてある通りで、
Viewを描画するための状態の保持と、Viewから受け取った入力を適切な形に変換してModelに伝達する役目を持つ。すなわちViewとModelの間の情報の伝達と、Viewのための状態保持のみを役割とする要素である。Viewとの通信はデータバインディング機構のような仕組みを通じて行うため、ViewModelの変更は開発者から見て自動的にViewに反映される。
http://ja.wikipedia.org/wiki/Model_View_ViewModel#ViewModel
試しに使ってみたものがこちら (ColorPicker) HEX/RGB の値を変えると、それに対応した HEX/RGB へと値が追従する感じ。
<div id="color-value-container">
<input v-model="hex" v-on="keyup: hexChanged">
<div id="color-space">{{hex}}</div>
</div>
<script>
var demo = new Vue({
el: '#color-value-container',
data: {
hex: '#000000'
}.
methods: {
hexChanged: function() {
this.$el.querySelector('#color-space').style.backgroundColor = this.$data.hex;
}
}
});
</script>
このように書いておくとだいたい次のようなことができる。
<input>
に入力された値が div#color-space
の {{hex}}
にバインドされる
<input>
で keyup
イベント発火時に methods
内に定義した hexChanged
メソッドが呼ばれる
v-model="hex"
は Vue に渡されたオブジェクトの data.hex
に相当するthis.$data.hex
でアクセスできるthis.$data.hex
の値を変更すると、変更された値が View に自動的に適用されるこのあたりをおさえておけば基本的に迷うことなく、あとはドキュメントを見て何とかできるので今後何かに使ってみたい。
Immutable な hashref, arrayref たまに欲しくなりますが Internals::SvREADONLY()
はクセが強すぎてあまりオススメできないです。
たとえ次のコードの挙動を言い当てられたとしても、赤の他人(≒ 半年後の自分)が見た時に分かるかどうかは怪しいかと。
use strict;
use warnings;
use Data::Lock 'dlock';
my $foo = { bar => "baz" };
dlock($foo);
eval { my $b = $foo->{b} };
if ($@) {
warn "oops: $@";
} else {
warn "yay";
}
謎めいたランタイムエラー起こすよりも定数は全部サブルーチンとして記述してあった方がコンパイルに失敗してくれて嬉しい感じがします。
ちなみにConst::Commonというのを書いた | おそらくはそれさえも平凡な日々 を見て思ったんですが、似たような事やってくれるのは過去にかいてました( 定数を定義するのを楽にする Constant::Exporter を書いた - stfuawsc) 他にも Exporter::Constants とかもありますね。
日本の祝日を機械的に取得したいケース、たまにありますね。
use 5.18.0;
use URI;
use URI::Escape;
use LWP::UserAgent;
use JSON::XS;
use Encode;
my $api_key = 'YOUR_API_KEY';
my $calendar_id = uri_escape 'ja.japanese#holiday@group.v.calendar.google.com';
my $uri = URI->new("https://www.googleapis.com/calendar/v3/calendars/$calendar_id/events");
$uri->query_form(
orderBy => 'startTime',
singleEvents => 'true',
key => $api_key,
);
my $res = decode_json +LWP::UserAgent->new->get($uri)->decoded_content;
for my $item (@{$res->{items}}) {
say encode_utf8 "$item->{start}{date}\t$item->{summary}";
}
__END__
2013-01-01 元日
2013-01-02 銀行休業日
2013-01-03 銀行休業日
2013-01-14 成人の日
2013-02-11 建国記念の日
2013-03-20 春分の日
2013-04-29 昭和の日
2013-05-03 憲法記念日
2013-05-04 みどりの日
2013-05-05 こどもの日
2013-05-06 こどもの日 振替休日
2013-07-15 海の日
2013-09-16 敬老の日
2013-09-23 秋分の日
2013-10-14 体育の日
2013-11-03 文化の日
2013-11-04 文化の日 振替休日
2013-11-23 勤労感謝の日
2013-12-23 天皇誕生日
2013-12-25 クリスマス
2013-12-31 大晦日
2014-01-01 元日
2014-01-02 銀行休業日
2014-01-03 銀行休業日
2014-01-13 成人の日
2014-02-11 建国記念の日
2014-03-21 春分の日
2014-04-29 昭和の日
2014-05-03 憲法記念日
2014-05-04 みどりの日
2014-05-05 こどもの日
2014-05-06 みどりの日 振替休日
2014-07-21 海の日
2014-09-15 敬老の日
2014-09-23 秋分の日
2014-10-13 体育の日
2014-11-03 文化の日
2014-11-23 勤労感謝の日
2014-11-24 勤労感謝の日 振替休日
2014-12-23 天皇誕生日
2014-12-25 クリスマス
2014-12-31 大晦日
2015-01-01 元日
2015-01-02 銀行休業日
2015-01-03 銀行休業日
2015-01-12 成人の日
2015-02-11 建国記念の日
2015-03-21 春分の日
2015-04-29 昭和の日
2015-05-03 憲法記念日
2015-05-04 みどりの日
2015-05-05 こどもの日
2015-05-06 憲法記念日 振替休日
2015-07-20 海の日
2015-09-21 敬老の日
2015-09-22 国民の休日
2015-09-23 秋分の日
2015-10-12 体育の日
2015-11-03 文化の日
2015-11-23 勤労感謝の日
2015-12-23 天皇誕生日
2015-12-25 クリスマス
calendarId
は ja.japanese#holiday@group.v.calendar.google.com
'"' expected, at character offset 35 (before "}\n") at ....
などと言われて壊れたJSONをなおす必要があるときに便利。
この場合は :go 35
とすれば修正すべき箇所に移動できる。はやく JSON5 普及しないものか…。
JavaScript にはヒアドキュメントが存在しないので無理やり再現するしか無いらしい。
方法としては、 Function.toString()
を呼ぶと関数の定義がコメント部分も含めてテキストとして取れる(!)ので、
次のように複数行コメント中にヒアドキュメントを書いて正規表現でマッチさせて取得する。
var doc = (function() { /*
<ul>
<li>不動産</li>
<li>自動車</li>
<li>掲示板</li>
<li>ブログ</li>
</ul>
*/ }).toString().match(/\/\*([^]*)\*\//)[1];
console.log(doc);
デメリットもあってなんとも言えない…