Archive for the ‘Ruby’ Category

‘Save This Page’ 件数表示の実装

Saturday, May 19th, 2007

今回の 表示機能 の実装は、

  • del.icio.us・はてブ の API をたたき、JSONP (JSON with Padding) 形式のデータを出力する Ruby スクリプト
  • JSONP 形式データを受け取り、整形・表示する JavaScript

の 2 つから構成される。実装にあたり、以下を参考にさせていただいた。

以下、個別にまとめておく。

はてなブックマーク の API をたたくスクリプト

はてなの場合、自分のブログに被ブックマーク数を表示する にあるような簡単な方法があるが、画像形式で表示され、デザインの調整がきかないことから、XML-RPC で API をたたく方法をとった。作成した getHatenaBookmarkCount.rbx の内容は以下のとおり。

#!/usr/bin/ruby -w
require 'cgi'
require 'xmlrpc/client'
require 'json/pure'

cgi = CGI.new
print cgi.header("type"=>"text/html")
end_point = 'http://b.hatena.ne.jp/xmlrpc'

url = cgi.params['url'][0] ? cgi.params['url'][0] : ""
callback = cgi.params['callback'][0] ? cgi.params['callback'][0] : nil

unless url =~ /^http:\\/\\/blog\\.shimazu\\.org\\//
	exit
end

urls = [ url ]
client = XMLRPC::Client.new2(end_point)
begin
	result = client.call('bookmark.getCount', *urls)
rescue XMLRPC::FaultException => e
	data = { 'error'=>e.faultCode, 'detailed'=>e.faultString }
	print data.to_json
	exit
end

data = [ { 'url'=>url, 'total_posts'=>result[url] } ]
if callback
	print callback ,'(', data.to_json ,')'
else
	print data.to_json
end

Ruby XMLRPC はてなブックマーク件数取得API というその名もずばりな参考資料があったので、それをベースにしている。

Ruby の json ライブラリは JSON implementation for Ruby から取得でき、rubygems でのインストールも可能。C で書かれたバージョン (json) と Pure Ruby のバージョン (json_pure) があるが、なぜか Debian GNU/Linux (Sarge) に前者 (json) がインストールできず、代わって後者 (json_pure) をインストールした。

del.icio.us の API をたたくスクリプト

del.icio.us / help / json / url にあるとおり、del.icio.us では普通に JSONP 形式の API が提供されてはいるものの、URL の指定に MD5 の暗号化が必要とのこと。Paul Johnson’s implementation of MD5 in JavaScript という凄腕ライブラリはあるものの、クライアント(ブラウザ)での処理は極力減らしたいので、MD5 処理する Ruby スクリプトをはさむかたちとした。作成した getDeliciousCount.rbx の内容は以下のとおり。

#!/usr/bin/ruby -w
require 'cgi'
require 'digest/md5'
require 'open-uri'

cgi = CGI.new
print cgi.header("type"=>"text/html")

api = 'http://badges.del.icio.us/feeds/json/url/data?hash='

url = cgi.params['url'][0] ? cgi.params['url'][0] : nil
callback = cgi.params['callback'][0] ? cgi.params['callback'][0] : nil

unless url =~ /^http:\\/\\/blog\\.shimazu\\.org\\//
	exit
end

request = api + Digest::MD5.hexdigest(url)
response = OpenURI.open_uri(request).read.chomp!

if callback
	print callback ,'(', response ,')'
else
	print response
end

出力結果

両者いずれも URL と callback 関数名 をパラメータ指定して、JSONP 形式のデータを出力するようになっている。出力例は以下のとおり(わかりやすくするため整形済み)。

例:getDeliciousCount?url=http://blog.shimazu.org/archives/95&callback=getDeliciousResponse

getDeliciousResponse([{
	"hash":"f021170bb35f553b70b7f392412babe4",
	"top_tags":{},"url":"http://blog.shimazu.org/archives/95",
	"total_posts":1
}])

例:getHatenaBookmarkCount?url=http://blog.shimazu.org/archives/89&callback=getHatenaBookmarkResponse

getHatenaBookmarkResponse([{
	"url":"http:\/\/blog.shimazu.org\/archives\/89",
	"total_posts":1
}])

なお、http://blog.shimazu.org/ で正規表現をかけているのは、http://blog.shimazu.org/ 以外のドメインでの利用を制限するため( XMLHttpRequest ではないので、クロスドメインでのアクセスが普通にできてしまうがそれを抑える目的)。

JSONP 形式データを受け取る JavaScript

データを受け取る処理を getcount.js としてまとめた。

function getDeliciousResponse(data){
if(!data||!data[0]||!data[0].total_posts){return false;}
var str = data[0].total_posts + (data[0].total_posts==1?'user':'users');
document.getElementById('delicious').innerHTML = '<a href="http://del.icio.us/url/' + data[0].hash + '">' + str + '</a>';
}
function getHatenaBookmarkResponse(data){
if(!data||!data[0]||!data[0].total_posts){return false;}
var str = data[0].total_posts + (data[0].total_posts==1?'user':'users');
document.getElementById('hatenabookmark').innerHTML = '<a href="http://b.hatena.ne.jp/entry/' + data[0].url + '">' + str + '</a>';
}
var el_delicious = document.createElement('script');
el_delicious.src = '/utils/getDeliciousCount?url=' + location.href + '&callback=getDeliciousResponse';
document.getElementsByTagName('head')[0].appendChild(el_delicious);
var el_hatena = document.createElement('script');
el_hatena.src = '/utils/getHatenaBookmarkCount?url=' + location.href + '&callback=getHatenaBookmarkResponse';
document.getElementsByTagName('head')[0].appendChild(el_hatena);

’Save This Page’ 件数表示

Sunday, May 13th, 2007

以前取り付けた ’Save This Page’ Button に「このページは何件ブックマークされているか」を表示させる仕組みをつけてみた。今回も del.icio.usはてなブックマーク の両方に対応している。

savebutton.png

目に見えるものはたったこれだけなのに、実装にやたら時間がかかってしまった。実装方法などについては、追ってまとめることにする。

追記
‘Save This Page’ 件数表示の実装 に実装詳細を記載。

Debian GNU/Linux 4.0

Tuesday, April 17th, 2007

バージョン 3.1(コードネームSarge)のリリースから約2年。Debian GNU/Linux の新バージョン(コードネームetch)がリリースされた模様。

Debian GNU/Linux 4.0
http://www.debian.org/News/2007/20070408

文字コードが UTF-8 だとか、メディアが DVD で 3 枚・CD で 21 枚 (!) とか、いろいろびっくりなところはあるけど、以前の Debian に比べ、採用ソフトウェアが比較的新しめのバージョンで、おもしろそうな予感。package 的には以下に興味をもった。

とはいえ旧バージョンにいまのところ不満はないので、しばらくこのままのバージョンで使い続けていくつもり。

制約は創造性をはぐくむ

Friday, March 16th, 2007

戦うWebデザイン―制約は創造性をはぐくむ

矛盾?ともとれるフレーズだけど、思い当たるようなところもあり、興味深いフレーズとして印象に残っている。

もともとは「戦うWebデザイン」という書籍のサブタイトルについていて、どんな意味で使われていたかほとんど忘れてしまったけれど、無の状態に創造性は生まれない・逆境ともいえるところにホントの創造性が発揮される、みたいな感じで、憂き目にあってる人々へのエールとしてだけでなく、創造性を生みはぐくむための普遍的な法則を明らかにしているような気がして、興味深い一冊だった。

これ「戦うWebデザイン」というヘンなタイトルの書籍が言っているヘンなフレーズ、と言われればそのとおりなのだけど、でも最近、同様のフレーズを Ruby on Rails の作者 David Heinemeier Hansson が講演のたびに使っているらしく、おもしろいことになっている。

Constraints are liberating (制約が自由をもたらす)というのがそれ。このフレーズは、Convention(規約)が車輪の再発明を抑制し、プログラマがホントにあたるべき機能の開発に専念できるようになる、という Rails の基本コンセプトを意味していると思われるが、このフレーズが意味するものは、Rails に限らず、デザインなどにも応用できそうな考え方のように思う。

創造力を豊かにするための一つの方法として、例えば、まず制約を仮説的に構築し範囲を限定した上で次のフェーズに進める、とか。仮説と検証、といわれれば普通だけど、デザインなど他分野にしても、仮説を立てることを創造力が発揮する土壌づくりと位置づけると、いま以上によく進められるかもしれない。

スマートじゃない DOM 拡張

Sunday, February 25th, 2007

この数ヶ月、理解しがたい JavaScript の不思議の一つ。json.jsobject.toJSONString() ような感覚で、以下のような感じで DOM にメソッドを追加してみると、

HTMLElement.prototype.hogeHogeHoge = function() {
//  something procedure releted to HTMLElement
};

Firefox などでは問題ないが、IE だとうまくいかない( IE では HTMLElement という考え方がないため)。

prototype.js の場合、 この状況を次のように処理して問題解決している、ように見える。(まるごと JavaScript & AJAX より引用)

// Extending DOM object
var element = Element.extend(document.createElement('div'));

// observe() is extended function
element.observe('click', eventHandler);

// If the element isn't extended, it's able to use observe() by this code.
Element.observe(element, 'click', eventHandler);

Firefox、Safari、IE など主要ブラウザでこのコードで必要な処理ができてはいるが、毎回 Element.extend() するのが冗長な気がする。

それくらいなら document.createElement() で返す DOM そのものを拡張したものに、と思うのだけど、IE では document.createElement() のオーバーライドはできるものの、関連する document.getElementById() などがオーバーライドできないという問題があり(例外になる)、あまりスマートではない。

HTMLElement のラッパーオブジェクトをつくり、そこにメソッドを追加という方法もあるが、それはプロトタイプベースオブジェクト指向言語には冗長なつくりだし、ここはやはり既存オブジェクトの拡張で進めたい、ところではあるが、なかなかうまくいかない。

たとえば Ruby on Rails では、付属の ActiveSupport ライブラリで自動的に数字の型が拡張され、

puts 3.days.ago

みたいな書き方ができる(Integer=>Time の変換)。もちろん 3 は普通の Integer としても扱える。とても自然でスマートで、プログラミング言語とは思えないくらいの直感さがあるように思う。

これ厳密には IE の実装の問題なのだけど、こういった問題がなくならない限り、JavaScript の不可思議さはなくならない気がする。

RubyKaigi 2006

Tuesday, June 13th, 2006

日本では初めてというRubyの本格的カンファレンス、RubyKaigi 2006 に行ってきました。写真はこちらにおきました。以下、自分的に気になったところをまとめておきます。

「State of the Dominion」 Ruby開発者まつもとゆきひろさんによる講演。「プログラミングRuby第2版」邦訳版が7月中旬発売(上下巻構成)。今後の課題としては、Ruby普及に向け、いかに CHASM を超えるか、ということ。Rubyの特徴としては、「素性が良い」「普通のひと(プログラマ)向け言語」の2つ。開発言語としての新味はRubyにはないが、LispやSmalltalkなど以前の言語が持つ機能の積み上げ方が良かった。

「Ruby 2.0」 まつもとさんをはじめとする開発メンバーによるパネルディスカッション。2007年クリスマスまでに、安定志向版たる「Ruby 1.9.1」を出す。鬼車、ブロック内での変数の扱いの変更、YARV の導入などが変更点。セッションの中で eigenclass.org RCR 237 について言及された。

「Railsによるメタプログラミング入門」 NaCl の前田修吾さんによる講演。「メタプログラミング」とは、プログラムをつくるプログラムの開発といった意味。自己言及的、という表現もあった。他の言語では、Lisp のマクロ、C++のテンプレートなどがそれにあたる。Ruby には3つの eval 関数(eval、instance_eval、module_eval/class_eval)があり、メタプログラミングが容易とのこと。

「dRubyをもう一度」 関将俊さんによる講演。drubyRinda といった分散処理ライブラリの紹介。(他のシンポジウムでも講演をされているとのことで、それと思われる 資料はこちら

「Perl の会社で使われる Ruby の利用法とは!?」 はてなの舘野祐一さんによる講演。Ruby 導入事例の紹介。Capistrano(旧SwitchTower) はデプロイツールのひとつ。「はてなスクリーンショット」では、Rails を利用している。

「One controller, many ins, many outs」 Ruby on Rails の開発者、David Heinemeier Hansson さんによる講演。通訳なしの英語での講演につき、断片的な理解となってしまったが、実のある内容だった。URLをシンプルにする、ということに重きを置いていて、そのための方法をいくつか提示している。現在GETとPOSTしか使われていないHTTPのメソッドの全て(GET、POST、PUT、DELETE)を使う、というもの。また、ひとつのデータをリクエストされたファイル拡張子にあわせ別々の表示処理を行うというのもあった。ActiveResource という新しい Rails の機能も紹介された。