そういえば、貧困な思考はいつも あなたのパターンを 安易なイメージ処理して
のところの最後をしばらくの間「アニメーションにして」と勘違いしていた。
遊体離脱の空耳
Flickr は親切だった。
めんどくさがって例外処理しなくても http://static.flickr.com/0/buddyicons/ 以下は全てリダイレクト。
アイコンが設定されていないときは、特別に http://www.flickr.com/images/buddyicon.jpg をアイコンとして使うんだけど、なんとなく面倒くさくてこの処理をしていなかった。というか、どういうレスポンスが返ってくるかわからなかったから放置していた。
で、なんとなくアレしてコレして見てみたら、iconserver=0 がレスポンスされるらしい。例外処理しとくかーって思ったけどリダイレクトだった。細かい配慮ないす。
ログインに使ってるスクリプト
weblogin.rb, 名前失敗したけどもういいや。
そのうち忘れるので使い方をめもる。
@cgi.header を使うことを前提にしてる。
api_keys = {
"Flickr" => {
"api_key" => "Flickr70c55b82e10021ffaaapi_key6",
"secret" => "Flickrdf5secret3"
},
"TypeKey" => "fsakfsTypeKeyafasAPI"
} require "weblogin.rb"
@cgi = CGI.new
WebLogin.open(@cgi, api_keys) do |login|
begin
case login.auth
when :login
# login したときの処理
# DB にユーザ ID とユーザ情報を保存したり
end
rescue WebLogin::NoActionError => e
puts @cgi.header("type" => "text/plain")
puts login.services # 有効なサービスの配列
end
end
上のようなのを認証スクリプトとしておいとく。このサイトだと /login.rb がコレ。ログインスクリプトの query_string が logout だったらセッションを破棄してリファラにリダイレクトする。ちょっとアレ。
/login.rb/Flickr?return_path= のようなリクエストをすると Flickr にリダイレクトして認証させる。認証されるとコールバック (Flickr の対応する API key のコールバックには http://example.com/login.rb/Flickr/callback のように指定しておく) にリダイレクトされるので、セッションに情報をセットして、return_path にリダイレクトする。
login.auth は、path_info に何も指定されていなかったりすると NoActionError を投げる。
require "weblogin.rb" @cgi = CGI.new WebLogin.open(@cgi, api_keys) do |login| if login.service # login している場合 login.service #=> "Flickr" login.id #=> "25514198@N00" login.user_name #=> "cho45" login.profile_uri #=> "http://www.flickr.com/photos/25514198@N00/" login.icon #=> "http://static.flickr.com/23/buddyicons/25514198@N00.jpg" login.full_name #=> "Hiroh Satoh" else # login していない場合 # id その他上記メソッドは全て nil end end
いまいち気持ち悪いんだけどどうにもこうにもわからんのでこんな感じ。ブロックをとっているのはセッションファイルを確実に閉じるため。fcgi 環境で死ぬことがあったのでこういうことやってる。
WebLogin クラスは、それ以下にある、サービス名に対応するクラスをインスタンス化してメソッドを呼び出す。例えば /login.rb/Flickr?return_path=somepath の場合、WebLogin::Flickr.new(@cgi, @session, @api_keys["Flickr"]).auth が呼ばれる。
各サービス名の auth メソッドはサービスの認証画面にリダイレクトする。サービスは /login.rb/Flickr/callback にリダイレクトする。
callback が指定されている場合、インスタンス化されたサービスクラスの callback メソッドを呼ぶ。callback メソッドはユーザ情報をまとめて Hash にして返す。WebLogin はその Hash をセッションに保存して、最初に指定された return_path にリダイレクトする。
いろいろアレなことが思い浮かんだけどあとで考えよう。
new にブロックって一般的じゃないんじゃ?という指摘をうけたので open にした。確かに new にブロックは微妙だった。
説明書を読むのが好き。
結構説明書読まない人って多いみたいだ。
小学生のときはそれこそ読まない人が全く理解できなかったけど、最近説明書を読みたくないときがあって、もしかしたらこういう感じなのかなぁって分かり始めたかもしれない。それはなんかとにかくいじくりまわしたい衝動が先にくる感覚だったのだけれど。
まぁでも結局そのあと説明書を最初から最後まで読んだわけです。何ができて何ができないのか、よくやる操作はどうやるのが一番スマートなにかを頭に入れておきたい。結構何度も説明書を読んでいると、新しい機能の発見があったりする。最初は「使わないだろう」って思って見逃しちゃうものを再発見できる。結構楽しい。
仕様書やら、プログラミングのリファレンスなんかもそういう感じでよく読む。一時期は XSLT と XPath の仕様書が常に開きっぱなしだった。ECMAScript の仕様書 (日本語 HTML 版) はむしろリファレンスとして使ってる。Ruby リファレンスマニュアルは気が付くと何故か上下になんどもスクロールしながら見てる。
暇だからできることだけど、とにかく自分が使うものは隅々まで一応知っておきたい。もし必要な機能じゃなかったら、頭の片隅にその機能があることだけを覚えておけばいい。使い方はまたあとで見ればいいから。
認証付きコメント実装
この日記にもつけてみた。
結局大して書く人がいないだろうってことでログインごとにユーザー情報を保持している XML を更新し、それを XSLT から document() 使って読み込むようにした。
Ajax では URL が変わらない?
そうとは限らないし、ちゃんと変わったほうがいいことも多い。
Ajax なりなんなりを含めて、JavaScript でいいことって画面遷移がないことであって、URL が変わらないことじゃない。
UI の補助ではなく、コンテンツを書き換える場合はむしろ URI は変わったほうがいい。要はあとでそのリソースにリンクを貼りたいとき、困るか困らないかが分かれ目だと思ってる。
外部認証
外部認証をコメント投稿に導入したくていろいろやっているんだけど、なんともかんとも。
Flickr, TypeKey を用いてログインするところまでは作った。とりあえず、コメントを投稿するとき、アイコンやら、名前やらもそのまま記録するような方式のをやってみたのだけど、やっぱ認証サービス側で名前とかが変わったら、こっちの過去の名前とかも変えたいなぁ、と思った。
サービス名と、サービス内で特定できる ID だけをコメントの情報につけて、ログインするごとに他のデータを更新するような感じにしたい。でもめんどい。RDB でテーブル複数つくって関係付ければ簡単なんだけど、いかんせん全てのデータを XML に入れてしまっているのでめんどうくさい。かなり重くなるだろうし……
というところで、諦めて全部一気に保存して更新しないようにするか、ちゃんと更新するようにするかで悩む
秘密がある。HIMITSU GIRL。ヘッドフォン
ZAZEN BOYS の HIMITSU GIRL'S TOP SECRET がかっこよすぎる。特にカシオマン。
そういえば、ここ最近 UR/40 を使っていたんだけど、ひさしぶりに ATH-A500 をつけたら付け心地がよすぎて困る。きもちいい。
この前でかけたとき、明大前でアートモニターシリーズの何かのヘッドフォンをつけた人を見た。男だったけど
黒かったけどなんだろ。A900LTD なのかなぁ。男だったけど
もっといかにもゴツイヘッドフォンつけてる人は見かけるけど、アートモニターはあんまり見ないなぁ。男だったけど
見ないなぁっていうか、そもそも外に出ないんだった。男はいらない。
どうでもいいけど、女子高生って存在しないんだってね。最近知った。よく考えてみると女子高生なんて見たことなかったんだ。見たっていうおぼろげな記憶は妄想だったみたいだ。でもさ、もし女子高生の存在を信じている人がいても、余計なことは言わないようにしようと思う。サンタクロースの存在を信じるのも、女子高生の存在を信じるのも、夢があっていいことだからね。
あひるほしい!
ruby-xslt の parameters=
parameters= に渡す値はすべて自分でクオートしとこう。
libxslt はもともとパラメータの値に XPath そのまんま書けるんだけど、なぜか ruby-xslt の parameters= ではクオートして必ず文字列で渡す。しかしながら、なんかこのクオートの実装が狂ってて、自分でクオート付け足してる癖に Invalid expression とか言い出してくれちゃう。やれやれだぜ!
正確に言うとクオートを付与する段階で、与えた文字列を中途半端に破壊的に変更するらしく、クオーテーションがかたっぽだけ付く。セッションとかで保存させながらのコードでもうハマったハマった。dup してどうにかしたけど、自分でクオートして明示的に文字列にしたほうがよさげ。
ソースは読んでないので間違っているかも。あくまで挙動からの推測
なんかもうめんどうくさい
なんか静的に XSLT で変換している /about とかの再構築さえめんどうくさくなってきた。動的にしたいなぁ。
って思って簡単な CMS (といえるものじゃない) を作ったんだけど、なんかいまいち使う気になれない。こうね、IPv4 と IPv6 の違いみたいになっちゃって、ね。要するに互換性がなくてめんどい。もちろんそれだけじゃなくて、URL とかを変えたくないから、mod_rewrite で全て CGI に渡すハメになるんだけど、なんで CGI でウェブサーバを再実装みたいなことをしないといけないんだって感じに。
もうね。例えばこれが自分のサーバーで、lighttpd で動いてて、FastCGI を使えるなら、まだ導入する気にもなれるんだけど、ね。だめね。もっと考えないとね。
コメントのポスト方法をちょっと変更
Ajax るようにした。UI がイマイチ。
- Comments を押したらとりあえず消えて欲しい。
- 投稿したあとガックンってなるのがちょっとキモイ。
なんかいい方法はないかなぁ。
Opera でおかしい。めんどいので Opera はじく。
なんだか、この今のスタイルがまずだめみたいで、Opera だと挙動不審になる。
クッキーに保存を実装しろといいたい。誰に。俺に。
Ajax のほうのフォームはクッキーに保存するようにした。Singleton Cookie オブジェクト
はてブと del.icio.us を同時に使うように
CGI 設置するのとかめんどいので xpost-del-hatena.user.js, GM スクリプトにした。
はてなの認証方法がややこしいので、はてなをメインにして、del.icio.us をスクリプトで同期するように。新規ブックマーク, 編集, 削除がそれぞれ del.icio.us にも反映される。ただ、編集の場合、del.icio.us で上にあがってしまう問題がある (はてなの編集画面にはポスト時刻が表示されないのでめんどい)。
最初なぜか API 使わないで実装してた。頭が悪い
ちょっと補足します。
Fx 1.5.0.1 + GreaseMonkey 0.6.4 ではとりあえず動いています。中身で無駄に E4X 使っているので、1.5 未満では絶対に動かないです。
ついでに動いてても何も言われません。淡々と del.icio.us に追加されたり削除されたりします。(最初の一回は del.icio.us の API Basic 認証がでます。これには del.icio.us のユーザ名とパスを入れます。)
del.icio.us 側の操作ははてブに反映されません。「はてなをメインにして」はそういう意味です。
はてダ の2カラムさえ
はてダ の2カラムさえなんか邪魔になってきたので ignore-hatena-2c.user.js 書いた。
GM ばっか書きまくり!!
GM の Edit ボタンが効かなかったんだけど、改めて about:config で設定しなおしたら使えるようになった。前より簡単につくれる><
てきとう E4X
どうにも使い道が少ない E4X をちょっとメモる。
基本的に XPath (の省略記法) に似ているので、相違点とかあげつつみたいな。XPath は E4X に似せるため省略記法を使います。省略しないと全然違う。
var doc = <root> <foo>hoge</foo> <bar>huga</bar> <baz> <foo name="neko"> <bar>pqpq</bar> </foo> </baz> </root>;
doc.baz..foo/root/baz//foo- E4X ではルートノードがない。
doc..foo.(@name == "neko")//foo[@name = 'neko']- E4X では括弧の前にドットがいる。括弧の中は ECMAScript の式そのまま。すなわち
orは||,andは&&。 doc.*/root/**はそのままの意味。@*もそのまま書ける。doc..foo[0]//foo[1]- 数値は普通の ECMAScript 配列とかとと同じように 0 基準。
doc..foo.length()count(//foo)- XPath の例はどうでもいいけど、数を知りたいときは
length()を使う。括弧をつけずlengthと書くと length 要素を選択しようとするので注意が必要。
for each とかいう構文がある (構文?)
for each (ele in doc.*) {
// hoge
}
XMLList とかいうオブジェクトがある。無名の要素をルートにして作る。ちょっときもい。
// XMLList (DOM の DocumentFragment みたいなの) var xmlList = <> <li>1</li> <li>2</li> <li>3</li> </>; var doc = <root> <li>999</li> </root>; doc.appendChild(xmlList); doc.toString() //=> <root> <li>999</li> <li>1</li> <li>2</li> <li>3</li> </root>
名前空間
var rssDoc = <rdf:RDF
xmlns="http://purl.org/rss/1.0/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel rdf:about="http://example.com/">
<title>Example</title>
<link>http://example.com/</link>
<items>
<rdf:Seq>
<rdf:li rdf:resource="http://example.com/3"/>
<rdf:li rdf:resource="http://example.com/2"/>
<rdf:li rdf:resource="http://example.com/1"/>
</rdf:Seq>
</items>
</channel>
<item rdf:about="http://example.com/3">
<title>ex3</title>
<link>http://example.com/3</link>
<dc:date>2006-03-01T13:52:32+09:00</dc:date>
</item>
<item rdf:about="http://example.com/2">
<title>ex2</title>
<link>http://example.com/2</link>
<dc:date>2006-03-01T13:52:30+09:00</dc:date>
</item>
<item rdf:about="http://example.com/1">
<title>ex1</title>
<link>http://example.com/1</link>
<dc:date>2006-03-01T13:52:24+09:00</dc:date>
</item>
</rdf:RDF>;
var rdf = new Namespace("http://www.w3.org/1999/02/22-rdf-syntax-ns#");
var rdfs = new Namespace("http://www.w3.org/2000/01/rdf-schema#");
var rss = new Namespace("http://purl.org/rss/1.0/");
// var dc = new Namespace("http://purl.org/dc/elements/1.1/");
for each (i in rssDoc.rss::channel.rss::items.rdf::Seq.rdf::li) {
var item = rssDoc.rss::item.(@rdf::about == i.@rdf::resource);
alert(item.rss::title);
} 見ればわかるように Namespace オブジェクト作って :: を解決に使うみたい。使わないなら別に宣言しなくてもいい。あくまで E4X でアクセスするために名前をつける (=変数に代入する) ので、別にどんな名前でもいい。
var h = new Namespace("http://www.w3.org/1999/xhtml");
default xml namespace = h;
var HtmlDoc = <html>
<head>
<title>E4X</title>
</head>
<body>
<h1>for (;;)</h1>
</body>
</html>;
みたいなこともできるみたい。
XPath における following-sibling 軸のようなメソッドはないっぽい?とりあえず眺めてみたらないっぽい。よくわからん。
しかし、GreaseMonkey で E4X を使うにしても、XMLHttpReqeust のハンドラぐらいでしか使えなくてなんともかんとも。もちろん生成するのは自由なんだけど……
@ の働きがいまいちわからない。ちゃんと仕様読もう
けいたいかえた
そういえばおとといぐらいに携帯変えた。前に解約云々言っていたけれどなかったことに。
別に特別変えたかったわけじゃないのだけれど、二週間に一回ぐらい機種変する?とか親父が聞いてくる (去年ぐらいから) ので変えてみた。俺には基本的にメリットしかないわけで……よくわからん。
前のやつは 4年ぐらい前 J-Phone 時代なやつでして、予測変換さえないおもろい携帯でした。まぁ携帯でメール書かないので困らなかったわけですが。まぁ携帯にメール来ることがないので困らなかったわけですが。まぁ携帯に電話来ることがないので古くても困らなかったわけですが。
友達がいない僕は携帯を連絡手段じゃなくてカメラとして使います。あーあと時計?なんか俺は腕時計つけるのが苦手らしくて、今は腕時計を持っていない。というか同じような理由で靴下も履かなかったんだけど、冬はさむずぎるので履くようにした。意味わからん。
flickr で CC じゃない写真を消す GM スクリプト
実際は消すんじゃなくて半透明にします。適用先は他の人の写真一覧のページ (/photo/username/)
以下スクリプトの説明
実は Set があるときとないときとで構造化の度合いみたいなのが違っててややこしい。具体的には Set がない人の一覧では div.StreamView 一個に対し、一つの写真と写真の情報が含まれる望ましい構造であるのに対し、Set がある人の一覧では、写真一覧が全部 div.StreamView 一個に含まれている。
ということで、Set がある場合とない場合にわけてる。きもいー。
Set がある場合、div.StreamView 以下の要素を一旦構造化する。
DocumentFragmentを作っておく。div.StreamView以下列挙してループh4がでてきたら div (class="__GM_Photo") という要素を作る- 他の要素だったら
div.__GM_PhotoにappendChild(一旦ノードは削除される) - また
h4がでてきたらDocumentFragmentに突っ込む - ループ終わったら残ってる
div.__GM_PhotoもDocumentFragmentに突っ込む div.StreamViewにDocumentFragmentをappendChild(戻す)
DocumentFragment は DOM における無名ノードみたいなもの。名前そのまんまだけど!!!
appenChild は既に同じドキュメントにあるノードを追加するとき、一旦そのノードを取り除く。すなわち移動したいときはいちいち削除する必要はない。逆にコピーしたいときは cloneNode する必要がある。
そいでもって、Set がない場合は div.StreamView のクラス名に __GM_Photo を追加するだけしとく。
あとは、Set のあるなしに関わらず、CC の画像を含んでいない div.__GM_Photo にアレしてコレした的な何か。