l'essentiel est invisible pour les yeux

Sunday, September 17, 2006

パビリオン山椒魚でドーン


















はーい、息吸ってー、とめて!ドーン!
本物とか、偽者とかどっちでもいいの。

前作「亀虫」をみていないので、富永ワールドを始めて見ることになった。

山椒魚の名前は、キンジロー。生誕150年でパリの万国博覧会にも出されたすごい歴史をみてきた山椒魚だそうだ。キンジローが、すげーかわいい。

そのキンジローを盗んでレントゲンをとり、本物かどうか確かめるようにオダギリジョー演じる天才レントゲン医師の飛鳥が依頼をうける。

・・・んな、まともな説明は必要ないような・・正直わからない!!

なぜ山椒魚なのか?なぜレントゲン医師の次は山賊なのか?第二農響って何なんだよ!!
まったくわからない(笑
そんな理屈は必要ないんだろうな。でも、もう1回見ないと多分満足できない。
ジャジーな音楽と映像がカッコよく、キャストが豪華で、色んな人間を演じている映像ががたまらなくカッコよくて面白かった。左上の写真は、購入したサントラ。

メゾンド・ヒミコの時のオダギリジョーも最高にセクシーだったけど、レントゲン医師のオダギリジョーもぬめぇっーとした色気がでていて、やっぱカッコいいししかも笑わせてくれる。

女優役は、最近注目の若手女優(らしい。最近テレビを見なくなったので全くしらなかった。)香椎由宇。プロフィール見たら、1987年生まれ!いや、ビビッった。。

最近大切なものを失って、ずっと低空飛行している気分だったが、そんなわかっていながらもださださだった俺もぶっとんだ。






















話は変わるけど、東京人は祭り好きなの?シネセゾン渋谷を出ると、ドーン!ドーン!太鼓の達人の10倍くらいの音が聞こえてきた。

って出ようと思ったら、ムキムキのお兄ちゃん達が扉の前に座っていて開かない。おみこしが通り、太鼓が鳴り響き、道玄坂は祭りムードになっていた。

この前原宿でも、表参道の通りを全部車とめて祭りをやっていた。あんなでかい通りよくとめるよなとふと思った。東京ではこういう祭りをよく開催しているのかな?

Tuesday, September 05, 2006

国分寺のパスタ屋 せもりな

京都に帰ってきた。
3週間東京にいると結構疲れるので、2週間滞在→京都→2週間滞在。

東京では、グルメな友達を持つにかぎる!情報がないと、なかなか美味しいお店までたどりつけません。
そこで、先日のフットサルでの筋肉痛をこらえ、日本一うまいと書いている人もいるぐらいの国分寺のパスタ屋 せもりなまで足を運んでみました。

井の頭線で吉祥寺まで出て、JR中央線乗り換えで国分寺へ。
駅から歩くこと10分。

昔からそこにあるような小さな食堂らしき家を見つけた。
看板をみると、せもりなでした。


















これは、よさそうな感じ。
期待を抱いて店内へ。

メニューを見せてもらうと、パスタの種類もピザの種類も豊富でかなり悩む。

ワインのおすすめを聞くと、白ワインのGaviというワインを勧められたので、
とりあえず、それをハーフボトルでお願いしますで。

アラカルトが300円で超おすすめ!
とブログに書いている人がいたことが頭によぎったが、ここは最近ずっと食べたかった牡蠣を注文。


















大きな岩かきがそのまま出てきて、身がぷるぷる言ってる・・・。
レモンをしぼり牡蠣から出ているスープと一緒に食べた。実がぷりぷりしていて、美味しかったです。

次は、パスタ。
最低2種類食べたかったので、一人前の量を聞くと100g.
二つ頼むと、「少し一皿の量を減らしましょうか?」とシェフの人が気をつかってくれました。

一皿目は、フレッシュトマトのカペリーニ。



トマトとカペリーニのパスタは冷性パスタとしてにんにくとバジルで食べるとうまくて、よく食べるけど、これは温かいパスタ。

トマト・にんにく・パセリがカペリーニと絡んで美味しかったけど、トマトから水分が出て少し大味になっていた感じがした。


二つ目のパスタは、クリームパスタと決めていたので、
ほたてとうにのクリームソース 生パスタを注文。




これは、うまい!!
ほたてからこんなに濃厚な味が出るとは驚き。生パスタがいい感じに絡んですごくおいしかったです。
クリームソースも一滴たりとも残さず完食。

ハーフボトルを飲み干したので、2本目を注文。
何にしようか迷ったので、となりの常連さんぽい夫婦にオススメしていた、
Gavi di Gaviというワインをまたボトルで注文。

こういうとき、「いつも大丈夫ですか?」と聞かれるが、「いいんです。大丈夫なんです。」と答える。

こちらのワインは、おいしい!一気に飲み干してしまいそうなのを抑えて、ワインのあてになるようなメニューを物色。後で調べると、「Gavi中のGavi」という意味らしく、そらGaviよりもおいしいはずだな。

生ハムは残念ながら、置いてなかった。
で、前を見ると、ピザのメニューが目に留まる。

迷わず、アンチョビピザを注文。



チーズ・アンチョビ・バジルのみのシンプルな薄生地のピザ。
その分、アンチョビのうまみが引き立っていて最高でした。
右手に見えるのは、タバスコではなく、唐辛子をつけたオリーブオイル。

で、ピザを食べながら、Gavi di Gaviも一気に飲み干して大満足。

お店の人に「インターネットでブログで日本一のパスタ屋って書かれているのを見て来たんですよ。」と言ったら、著作権の了解も無しにと笑っていました。店に来ていた人も毎週のように来ているという感じの人が一杯で、よそ者がたくさん来てお店の感じがかわると嫌かなとも思ったのですが、おいしかったのでブログに書いてしまいました。すみません。。

是非また、行きたい。
国分寺の少し手前の武蔵小金井あたりは、再開発中で今なら土地も安く結構おすすめだと、hoge山さんに教えてもらったので今度チャリンコのって見に行きます。

Sunday, September 03, 2006

Rubyのexpect.rbの使い方

SSHでつないで何か操作を行ったり、パスワードの入力を自動化したり、対話形式のプログラムをプログラム中から利用する場合は、expectモジュールを使用するのが一般的です。

Rubyは標準ライブラリ中にexpect.rbが存在していますが、IO#exceptとしてIOのメソッドとして定義されていて、このままでは扱いにくいので、仮想端末を扱うPTYライブラリとあわせて使用します。


require 'pty'
require 'expect'

module Expect
def spawn(cmd)
  puts "CMD: #{cmd}" if $expect_verbose
PTY.spawn(cmd) do |r,w,pid|
@input_stream = r
@output_stream = w
@child_pid = pid
PTY.protect_signal do
yield
end
end
end

def expect(pat, timeout=10)
ret = @input_stream.expect(pat, timeout) do |match|
raise "expect %s timeout " % (pat.kind_of?(Regexp)? pat.source : pat) unless match
put_cmd(yield(match))
end
end

private
def put_cmd(cmd)
@output_stream.puts(cmd)
end
end
PTY#protect_signalでブロックを実行しないと、SSHで接続後、exitしたときなど子プロセス終了時に例外が発生します。

例えば、rootにログインしてホームディレクトリに移動して、lsコマンドを実行する。

def root_ls
include Expect
spawn("su root") do
expect(/\$$/) {|match| "su root"}
expect(/Password:/) {|match| "myrootpass"}
expect(/\$$/) {|match| "cd"}
expect(/\$$/) {|match| "ls"}
end
end

Saturday, September 02, 2006

Prototype.jsのCHANGELOGまとめと自分なり拡張

Prototype.jsが Updateされいくつかの機能が追加されました。
メソッドチェーンによるメソッドの呼び出しが完全にサポートされたのは大きな変更かと思います。

CHANGELOG

Element, Form, Form.Elementメソッドの仕様変更
Elment, Form, Form.Elementが配列ではなく、一つの要素(or ID)を引数に取るように仕様変更され、返り値として引数で渡したオブジェクトを返すようになりました。

この修正により、

$('div').each(function(val) {Element.show(val);}); // Before
$('div').each(Element.show); // After

$('input[type="text"]').each(function(val) {Field.clear(val);}); // Before
$('input[type="text"]').each(Form.Element.clear); // After
eachメソッドにElement.*関数を高階関数と渡すだけで全要素に処理を適用できます。

ただし、この仕様変更により次のようなレガシーなコードは変更が必要になります。


Element.show('page', 'sidebar', 'content');// Before
['page', 'sidebar', 'conent'].each(Element.show); // After



Field.*はForm.Methodsに統一
Fieldオブジェクトに定義されていたメソッドは、Form.Elementに統一されました。FieldはForm.Elementへの参照として定義されているため、後方互換性は保たれています。


Form中の要素を全て有効化/無効化するメソッドの追加
Form中の要素全てを有効化/無効化するためのメソッドとして、Form.enable, Form.disableが追加されました。


$('form').disable();
$('form').enable();


$(), $()で返される要素にForm.Methods, Form.Elementがmixinされるようになった
Element.extendメソッドに、FORM要素にはForm.Methodsが、INPUT, TEXTAREA, SELECTの場合には、Form.Element.Methodsがmixinされるようになった。
この変更により、$()の結果に対しての完全なメソッドチェーンでのメソッド呼び出しがサポートされた。


$('input1').clear();
$('input2').focus();



Objectのコピーを生成する、Object.cloneの追加
オブジェクトのコピーを生成し返すメソッドが追加されました。

clone: function(object) {
return Object.extend({}, object);
}


Object中に定義されているキーと値を取得するメソッド
Object.keys, Object.valuesメソッドが追加され、それぞれ引数に渡したオブジェクト中に定義されているキーとその値を取得して配列で返します。

Object.keys(Array); // => ["from","bind","bindAsEventListener"]
Object.values(Array); // => [function (iterable) {...},function () {...},function (object) {...}]



$()関数で参照した要素の子要素に対してのクラス名・CSSセレクタでの参照が可能に。
Element.Methods.getElementByClassName, Element.Methods.getElementsBySelectorが追加され、$()で参照した要素の子要素に対してクラス名・CSSセレクタでの参照が可能になりました。

$('form').getElementsByClassName('item');
$('form').getElementsBySelec('input[type="text"]'); // => テキスト入力フォームのみ取得


Array.reduceメソッドの追加
配列中の要素が一つの場合は、要素を返し、複数要素を含む場合には配列自身を返すメソッドです。
配列内の要素が1つかどうかいちいち確認するのをDRYにします。


[1, 2].reduce() // [1, 2]
[1].reduce() // 1
[].reduce() // undefined


PUT/DELETEメソッドをPOSTメソッドでエミュレートする
DHHによる変更です。Ajax.Requestに渡すオプション中で、method: put, method: deleteと指定している場合は、methods: postに置き換え、_method: put, _method: _deleteを定義して、PUT/DELETEをエミュレートします。
ActiveResourceをJavascriptからも利用しやすくするための変更だと思われます。

個人的に機能拡張しているところ。
prototype.jsは、便利で活用しているのですが、細かいところで「こんな機能あったらなぁ・・」と思って、自分で拡張して実装しています。そのいくつかを書いておきます。

Hash.mapの変形バージョン
HashクラスもEnumerableクラスをmixinしているため、Hash.mapが使えるのですが、ハッシュに高階関数を適用すると次のように適用した結果の値を取り出した配列が返されます


Hash.collect2 = function(iterator) {
var result = $H({});

this.each(function(value, index){
result[value.key] = iterator(value, index);
});
return result;
}
Hash.map2 = Hash.collect2;
function inc_value(val){return val.value+1;};

$H({fruits: 2, apple: 3, melon: 4}).map(inc_value);
//=> [3,4,5]

console.log($H({fruits: 2, apple: 3, melon: 4}).map2(function(val){return val.value+1;}).inspect());
// =>
#<hash:{'fruits':3, apple: 4, melon: 5}>


Hash.toQueryStringの拡張
prototyp.js中に定義されている、Hash.toQueryStringはハッシュをURLパラメータ形式の文字列にして返してくれます。しかし、ハッシュ中に配列が含まれたり、ハッシュがネストしている場合には、次のようになります。

$H({fruits: ["apple", "banana", "melon"]}).toQueryString();
// => "fruits=apple%2Cbanana%2Cmelon"
$H({fruits: {name: "apple", size: 3, color: "red"}}).toQueryString();
// =>
"fruits=%5Bobject%20Object%5D"


人により差異はあるかもしれませんが、これは意図した通りにサーバ側でパースされません。
そこで、Hash.toQueryStringを変更し、次のように返すようにしています。

$H({fruits: ["apple", "banana", "melon"]}).toQueryString();
// =>"fruits[0]=apple&fruits[1]=banana&fruits[2]=melon"
$H({fruits: {name: "apple", size: 3, color: "red"}}).toQueryString();

// => "fruits[name]=apple&fruits[size]=3&fruits[color]=red"


と返されるように、Hash.toQueryStringを次のように定義しています。


Hash.toQueryString = function(){
return this.map(function(pair){
if(pair.value instanceof Array) {
var key = pair.key;
return pair.value.length == 0 ? "" : $A(pair.value).map(function(val){return key+"[]="+val}).join('&');
} else if(pair.value instanceof Object) {
var key = pair.key;
return $H(pair.value).map(function(_pair){return key+"["+_pair.key+"]="+_pair.value}).join('&');
} else {
return pair.map(encodeURIComponent).join('=');
}
}).compact2().join('&');
};


Array.compact2については下記で説明します。

Array.compact2-NULLとundefinedと空文字列(==falseと評価される値)を配列から取り除く
Array.compactの変形バージョンです。


Array.prototype.compact2 = function(){
return this.select(function(value) {
return value != undefined && !(value == false);
});
};



Array.unique - 重複した要素を取り除いたユニークな配列を返す。
Array.prototype.unique = function(){
var ret = [], sorted = this.sort(), cur;
for(var i=0,l=this.length;i<l;++i) i="" return="" ret="">


String関連の拡張
全角スペースを半角スペースにとか。

String.prototype.empty = function(){
return (this == "");
};
String.prototype.full2harf = function(){
return this.gsub("\u3000", "\u0020");
};



書式付き日付出力
そういえば、Prototype.jsには日付関連の拡張は一切無い。
/**
* Date.strftime
*
* Inspired by
* http://www.mattkruse.com/javascript/date/date.js
* Author: Matt Kruse <matt@mattkruse.com>
*/

Date.MONTH_NAMES = 'January February March April May June July August September October November December Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec'.split(' ');
Date.DAY_NAMES = 'Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sun Mon Tue Wed Thu Fri Sat'.split(' ');
Date.prototype.strftime = function(format) {
function LZ(x) {return(x<0||x>9?"":"0")+x}
format=format+"";
var result="";
var i_format=0;
var c="";
var token="";
var y=this.getYear()+"";
var M=this.getMonth()+1;
var d=this.getDate();
var E=this.getDay();
var H=this.getHours();
var m=this.getMinutes();
var s=this.getSeconds();
var yyyy,yy,MMM,MM,dd,hh,h,mm,ss,ampm,HH,H,KK,K,kk,k;
// Convert real date parts into formatted versions
var value=new Object();
if (y.length < y="" h="=">12){value["h"]=H-12;}
else {value["h"]=H;}
value["hh"]=LZ(value["h"]);
if (H>11){value["K"]=H-12;} else {value["K"]=H;}
value["k"]=H+1;
value["KK"]=LZ(value["K"]);
value["kk"]=LZ(value["k"]);
if (H > 11) { value["a"]="PM"; }
else { value["a"]="AM"; }
value["m"]=m;
value["mm"]=LZ(m);
value["s"]=s;
value["ss"]=LZ(s);
while (i_format < c="format.charAt(i_format);" token="" result="result" result="result">


タグベースのイテレータ

ネタ元は、Enctymedia blog.

/**
* Tag base iterator
*/
(function() {
/* Tag base iterator */
var tags = "div p span ul ol li span form input select textarea h1 h2 h3 h4 h5 h6 dl dt em strong a";
var methods = {};
$A(tags.split(' ')).each(function(tag){

methods["each"+tag.charAt(0).toUpperCase()+tag.substring(1)] = function(element, iterator) {
element = $(element);
element.cleanWhitespace();
$A((element).getElementsByTagName(tag)).each(iterator);
}
});
Object.extend(Element, methods);
})();


正規表現文字のエスケープ

RegExp.quote = function(str){
return str.replace(/([\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:\\\-])/g, '\\$1');
};