ラベル ruby の投稿を表示しています。 すべての投稿を表示
ラベル ruby の投稿を表示しています。 すべての投稿を表示

2007-04-16

青木峰郎/Rubyist Magazine出張版 正しいRubyコードの書き方講座

たまには、プログラミングの本を読まないと、ぼくのアイデンティティが、ただのサッカー好きのおじさんになってしまう、ということで、久々に本を購入して読んでみた(ちなみに、ぼくの読書は、ほとんど図書館で読むか、図書館で借りるかで行なわれる)。

で、この本だが、るびま

http://jp.rubyist.net/magazine/

で連載されたものを、書き下ろし1章とコラムを付けて本にまとめたもの。連載の方をある程度見ていたので、本の方もサクサク読めた。

Rubyは、PerlからTMTOWTDIのポリシーを受けついで、さらにリフレクションの機能が強力なので、プログラムをどのようにも書けてしまうという特徴があるのだが、そうすると、今度は、書けることは書けるが、じゃあ、どう書くのが正しいのかという問題にぶちあたる。例えば、ぼくがCでプログラムを書くときには、読む人間がANSI Cの仕様を熟知していることを前提に、括弧は必要最低限しか書かないことにしている。こうすれば、括弧が付いているのは、アルゴリズム的に意味のあるところしかなくなるので、結合順序を知っていれば、コードは読みやすくなる、とぼくは考えている。しかし、これをRubyに適用しようと思ったら大変なことになる。括弧が省略できすぎてしまうのだ。

じゃあ、どうするかと悩んで、ぼくが出した結論は、二項演算子の結合順序は、プログラマが把握すべきだから余計な括弧は付けない、しかし、関数(メソッド)の適用の括弧は必ず付ける(引数が0のときを除く)というもの。しかし、これでもRuby的には、やや括弧を付けすぎなような気がする。他の人のソースコードを読むと、結構みんな関数の適用でも括弧を省略するんだよね。仕様を熟知すべきという前言を翻すようだが、学生時代に関数型言語に慣れ親しんだせいか、これはなんとなく気持ち悪い。

例えば、Haskellでリストの先頭の要素を取ってきて1を足すというプログラムを書くと、

head [1, 2, 3] + 1

となるだが、rubyで同じようにhead関数を定義して実行してもエラーになってしまう。なぜかと言うと、この文はHaskellでは、

(head [1, 2, 3]) + 1

と解釈されるが、Rubyでは、

head ([1, 2, 3] + 1)

と解釈されるのだ。一般的に関数型言語では、関数の適用時の括弧を省略することが多く、関数の適用はかなり強い結合順位になる。この感覚があるので、Rubyで関数適用の括弧は外したくないのだ。

括弧の話が長くなってしまったが、Rubyでは、このように細かいことでも、どう書くか悩んでしまう言語なのだ。Rubyには、歴史が浅いせいか、Cで言うところのK&Rみたいな、ある程度コンセンサスのあるコーディングスタイルというのもない。そういう中で、Ruby界の重鎮の青木氏がこの本を書いた意味は大きいと思う。

もちろん、この本に書いてあるのは、コーディングルールだけではない。protectedなどのRubyの文法の落とし穴や、少しマイナーなメソッドを使ってコードを短かく書く方法など、Rubyを書く上で役に立つことがたくさん書いてある。特に感心したのが、eval系メソッドの使ってDSL(Domain SpecificLanguage)を作るという箇所。Rubyの文法の柔軟性をうまく利用して読みやすいコードになっていた。RakeなんかもDSLにRubyをそのまま採用しているんだよな。リフレクション系は、自分でやるとなるとかどうかは悩みどころではあるのだが、Rubyの文法のポテンシャルの高さが分かった。

プログラミングの技術の習得というのは、文法を理解したあと、ひたすら他人のコードを読むことでしか身につかないんだけど、この本を読めば、Rubyの習得に関しては、随分ショートカットできると思う。プログラミングって、こういう細かいことが重要だと思うんだよね。小さい問題を解決していくと、大きな問題が見えるというか、逆に設計から考えていっても、最初はどうでもいいと思って無視していたところで、必ず躓くからね、しかも致命的に。「神は細部に宿る」ですよ。よくわからんけど。

2007-01-28

bloggerpostで証明書の検証をしていないという警告が出ていたので修正

bloggerpost-0.0.5.tar.bz2

正直、よく分かんないんだけど、

warning: peer certificate won't be verified in this SSL session

ずっとこんなのが出ていて、気にはなっていたんだけど、放置してた。でも、やっぱりちょっとまずいんじゃないかと思って修正した。

http.verify_mode = OpenSSL::SSL::VERIFY_PEER
store = OpenSSL::X509::Store.new
store.set_default_paths
http.cert_store = store

見よう見まねでこんな感じのを追加してみたのだが、あっているのだろうか? たぶん、あってると思うけど。


2007-01-26

RubyでBloggerに投稿(その4) 投稿HTMLの改行削除に対応

うわ、よく見たらブログのエントリーが大変なことになってる! 「改行の変換」をオフにすると、過去のエントリーまで全部適用されるのか、なんてこったい!これじゃ、一度「改行の変換」をオンにしたらオフにできないじゃん。トラップだ。

というわけで、bloggerpost.rbの方で対応しなきゃいけないな。と言っても問題はpreタグだ。こりゃ完全対応は難しそうだな。とりあえず、タグの後ろの改行とpタグの中の改行を削除するように修正。

bloggerpost3.rb

つーか、改行の変換は投稿時に行うべきだろ。常識的に考えて。

RubyでBloggerに投稿(その3) RDでの投稿に対応

RDとHTMLの両対応にしてみた。

bloggerpost2.rb

使い方は

% ruby bloggerpost2.rb entry.rd

もしくは

% ruby bloggerpost2.rb -t rd < entry.rd

HTMLのときは、拡張子を.htmlにするか、オプションを-t htmlとすればよい。つまりテキストの種類は、ファイルの拡張子か、標準入力のときは明示的に指定するという感じ。もちろん、ラベルの機能もあります。

ちなみに、このエントリーはRDで書いている。RDを知らない人のために、このエントリーの元のRDファイルも置いておこう。

このエントリーの原稿

しかし、HTML手書きよりはかなりマシだけど、実はRDもそんなに好きじゃなかったりする。テーブルが書けないし、preタグを書くのにスペースでインデントするのも面倒臭い。なんかいいのないかな。

あと、Bloggerのフォーマットの設定で「改行の変換」ってやつ、Atom経由でも適用されるんだよ。あれがちょっとウザい。仕方がないので切ったけど、コメントにも適用されるから、コメントする人は自分でbrタグを入れなきゃいけない。

いや、コメントついてないんだけどさ、このブログ。

RubyでBloggerに投稿(その2)

# テストで間違ってこのエントリーを消してしまったので、再掲載。

というわけで、RubyでBloggerに投稿するスクリプトを書いてみた。

bloggerpost.rb

使い方は
% ruby bloggerpost.rb -l "label1 label2" < entry.html
って言う感じ。

と作ってみたはいいが、これは激しく使いづらい。インターフェースの問題以前にHTMLの手書きはキツい。RDとかplain2とかからの変換を考えないといかんね。

2006-12-20

2006-12-19

RubyでBloggerに投稿

EmacsでBlogger投稿はとりあえず断念したわけだけど、それじゃ、どうやればBloggerに投稿できるかを調べてみた。それで、ここに詳しく書いてあるらしいんだけど、悲しいことに読んでも全然分からない。

色々検索したらPerlでBloggerに投稿している例に遭遇。早速コピペして動かしてみると、動いた! すげえ。

しかし、ぼくはRuby脳なわけで、Rubyで動かしたい! ということで、このコードをRubyに移植してみた。それが、これ。

#!/usr/bin/ruby

require 'net/https'
require 'uri'

GAUTH_URL = "https://www.google.com/accounts/ClientLogin"

email = "user@gmail.com"
passwd = "passwd"
feed_url = "http://www.blogger.com/feeds/###################/posts/default/"
#feed_url = "http://beta.blogger.com/feeds/###################/posts/default/"

entry = <<ENTRY
<entry xmlns='http://www.w3.org/2005/Atom'>
<published>2006-06-09T10:27:00.000-07:00</published>
<updated>2006-06-09T10:31:55.120-07:00</updated>
<title type='text'>Marriage!</title>
<content type='xhtml'>
<div xmlns="http://www.w3.org/1999/xhtml">
<p>Mr. Darcy has <em>proposed marriage</em> to me!</p>
<p>He is the last man on earth I would ever desire to marry.</p>
<p>Whatever shall I do?</p>
</div>
</content>
<author>
<name>Elizabeth Bennet</name>
<email>liz@gmail.com</email>
</author>
</entry>
ENTRY

url = URI.parse(GAUTH_URL)
req = Net::HTTP::Post.new(url.path)
req.form_data = {
"Email" => email,
"Passwd" => passwd,
"source" => "companyName-applicationName-versionID",
"service" => "blogger"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true if url.scheme == "https"
res = http.start { |session|
session.request(req)
}
res.body =~ /Auth=(.+)/
auth_token = $1

url = URI.parse(feed_url)
req = Net::HTTP::Post.new(url.path)
req["Authorization"] = "GoogleLogin auth=" + auth_token
req["Content-Type"] = "application/atom+xml"
req.body = entry
res = Net::HTTP.new(url.host, url.port).start { |http|
http.request(req)
}
case res
when Net::HTTPSuccess
puts "ok"
when Net::HTTPRedirection
url = URI.parse(res["Location"])
req["Host"] = url.host
Net::HTTP.new(url.host, url.port).start { |http|
http.request(req)
}
else
puts "error"
res.error!
end

書いてみた思ったのは、Rubyのnet/httpはやっぱり使いづらい。open-uriはPostできないし。おれがへまっているのかもしれないけど、PerlのLWPの方が全然使いやすいよなあ、と思ってしまった。

あと、sargeのRubyだと、このコードが動かないことが判明。1.8.2で、net/httpsがないのだ。そんな最近までなかったっけ? sarge面倒臭いなあ。