| @技術/プログラミング

Ruby 1.9、Rails 3、RSpec 2で開発してる。いままでRubyとRailsになれるのに一杯一杯でテスト駆動開発できてなかったので、きちんとテストファーストでやることにした。

そんで環境を整えてたんだけど、RSpecはRails 3に合わせてVersion 2が出てるみたい。しかも結構変わってる。

$ spec -c spec/*

とかやってもエラーが出る。 which spec すると /usr/bin/spec と出ちゃう。どうやら spec で発動されるのはRSpec 1.3のものみたい。

RSpec 2からはコマンド名が変更されており、テストコードを実行したいときは以下のように書くみたい。

$ rspec -c spec/*

これできちんとテストコードが実行された。かと思いきやFailureが。

Ruby 1.9で動かしてるから、コードの中に日本語を書くときは一行目に

# -*- coding: utf-8 -*-

と書いてテキストエンコーディングを明示してあげないといけない。

| @技術/プログラミング

動かしてるサイトのCakePHPのバージョンを最新版の1.3.4に上げようと思って、Media PluginもCakePHP 1.3対応バージョンの1.3alphaにアップデートしようとした。

とりあえず本体を git clone http://github.com/cakephp/cakephp.git し、Media Pluginを git clone http://github.com/davidpersson/media.git してみた。

Media Plugin 1.3での設定方法とか調べてみようと思って、GitHub上のWikiのページを探すんだけど見つからない。なんと、作者サマはVer 1.3からWikiを消しちゃったみたい! そんまま動かしてみたところではMedia Plugin動いてないみたい。Mediumヘルパーがないというエラーが出る。プロジェクトの中の docs ディレクトリにドキュメントが格納されていたのを発見したので(docs at 1.3 from davidpersson's media - GitHub)そこを参考にしながらMedia Plugin 0.6から1.3へのMigration作業をやったんだけど、とうとうできなかった。

まず第一に、クラス名が変わってる。Media.Medium だったのが Media.Media になってる。Viewファイル内での変数も $medium ではなく、 $media になってる。そしてメソッドとかもHTML5対応とかで結構変わってるみたい。

さらに、media processing 関連のクラスが分割されて別のライブラリとしてMedia Pluginの中に含まれてる(davidpersson's mm at master - GitHub)。これが結構わかりにくい。なんかImagick必要ぽくて、本番環境じゃインストール権限ないので使えないし、結局ここで諦めてしまった。

Media PluginはVer 0.6のWikiがあった頃もなんかドキュメンが見づらかったし、1.3になってドキュメントはただのテキストファイルになり、しかもメソッドについての解説がないので結局本体のコードを読むしかない。

RubyのライブラリはたいていRdocとかついててドキュメントが充実してるので、あれに慣れるとドキュメントがわかりにくいライブラリやプラグインは億劫に感じてしまう。

| @技術/プログラミング

いやまぁテキストエディターにはいろいろあるわけでして、皆さんEmacsとかVimで日夜しこしこコードを書いておられると思うんですけど、僕はGUIしか使えない情報弱者なので主にTextMateを使ってます。

TextMateで便利なのが "Run" っていう機能です。Rubyのコードを書いていて、 + R でさくっと実行結果を確認できます。いちいちTerminal開いて

$ ruby hogehoge.rb

とか面倒くさいことをやらずにすみます。

で、これからが本題なんですけど、先月Ruby 1.9.2がリリースされて、さらに gem update でRails 3が入るようになってしまったので、お試しでRuby 1.9.2とRails 3を使ってみることにしました。しかし1.8系を完全に捨てることは恐ろしいので、RVMを使って複数のバージョンのRubyを切り替えながらしばらく過ごしてみることにしたわけです。

上に書いたとおり僕ちゃんは情報弱者なのでTextMateに依存したコーディングライフを送っており、 + R で動くRubyもRVMのRubyにしたいと思ったのですが、これが分からなかった。RVMのサイトを見たらいろいろごちゃごちゃやり方が書いてあるんだけど(RVM: Ruby Version Manager - Textmate Integration with RVM)、結局この通りにやってもうまくいかず。

しかし先ほどなにげなく

$ rvm 1.9.2 --default

としてあげたところ、TextMateでもRVMのRubyが走るようになりました。

| @技術/プログラミング

みなさん、クリッカブルマップしてますか? あんなくそみたいなもの使って地図をつくるなんて発狂しそうなこと、ここを読みそうな人はやってないと思いますが、僕の職場のお客さんとか上司は「Google Mapsには心がこもってない」とか言うので、クソみたいイラストをクリッカブルマップにして地図を作ってるんですよ。まじでかわいそうな僕ちゃん。

ご存じない方のためにクリッカブルマップの作り方を説明しておくと、まず画像を作り、それをHTMLに貼り付け、HTMLオーサリングツール(うちの職場ではDreamWeaver)のGUIエディタでちまちま画像上のクリッカブルにしたい位置を選択するという、血尿が出そうなくらい面倒くさい作業を強いられます。

最悪なことにこのクリッカブルマップのあるページ、頻繁に更新依頼が来るのですよね。依頼が来る度に就業時間中の快適なネットサーフィンが妨げられるので、一発JavaScriptを書いて画像上の座標を取得することにしました。いちいちクソみたいに重いAdobe DreamWeaverとか立ち上げてられるか。

コードはこんな感じ。

<html>
  <head>
    <script>
      function getPosition(){
        var x, y;
        var image = document.getElementById('image');
        image.onclick = function(e) {
          x = e.layerX;
          y = e.layerY;
          document.getElementById("pointX").value = x;
          document.getElementById("pointY").value = y;
        }
      }

      window.onload = getPosition;
    </script>
  </head>
  <body>
    <div>
      <img src="path/to/image" id="image" style="position: absolute; top: auto; left: auto; width: 500px; height: 332px" />
    </div>
    <form action="/" method="post">
      <input type="text" id="pointX" name="pointX" value="" />
      <input type="text" id="pointY" name="pointY" value="" />
      <input type="submit" value="発射!" >
    </form>
  </body>
</html>

Firefoxでしか動作確認してないけど多分IEでは動かないと思います。ここのサイトを参考にさせてもらいました。

| @技術/プログラミング

RubyKaigi 2010に行ったのでその感想を軽く。

自分のスペック

Rubyは使い始めて8ヶ月くらい。元々何もできなかったのでいまも初心者レベル。プレゼンテーション聞いてても分からないことが多かった。

感想

永和システムマネジメント永和システムさんの「Head First ふつうのシステム開発」は面白かった。プログラミングのやり方を人から教わったことがないので、普通の会社はこうやって開発してるんだってのが分かった。テストの様子を見られて参考になった。あとVimがすごくカスタマイズしてあってすごかった。用事があって途中までしか見られなかったのが残念。

MongoDBについてのプログラム(Practical Ruby Projects with MongoDB)で、気にはなっていたけどよく分からなかったMongoDBのことがより一層気になった。情報の連結とかそういうコムズイことはSQLでやるんじゃなくてプログラム側でやるべき、ってことなのかな。

クックパッドのセッションも見学した。CTO氏が質疑応答で「専属デザイナーはいなくてデザインもできるプログラマーがデザインやってる」って言ってたのにびっくりした。大規模サービスをやってたら負荷分散のテクニックとか参考になったかもだけど、自分が作ってるサイトは多くても5000UU/日くらいなので「ふーん」という感じで聞いてた。

東京とつくばの移動に時間がかかったこと、他にも予定があったこと、帰りの飛行機の都合、などなどであまりゆっくり参加できなかったのが残念だったです。28日は用事があったので基調講演見られないから生Matzを拝むの諦めてたけど、Jeremy Kemperの基調講演がキャンセルになったかわりにトークセッションがあってて、そこにMatzも登場しててRubyの教祖を拝めたのでまぁ良かったと思います。あとジュンク堂RubyKaigi支店でで技術書買いすぎて散在した!

2010年9月26日修正

すみません、永和システムマネジメントさんのことを「永和システムさん」と書いてました。はてブのコメント欄で角谷さんに指摘されてた!

| @技術/プログラミング

シャレオツプログラマーはみんなMacPortsからHomebrewに移行しつつあるっぽいので、真似してみることにした。

なんでHomebrew?

そもそもなんでみんな移行するのか? なんかMacPortsはバッドノウハウの塊らしい。

MacPortsの何がバッドノウハウなのかちょっとよく分からなかったんだけど、でもよく考えてみたらMacPortsは .bash_profile とか .zshrc とかにへんてこりんなパスを埋め込まないといけないし、PerlとかRubyは一行目に

#!/usr/bin/perl

とか

#!/usr/bin/env ruby

とか書くのに使ってるバイナリ本体は /opt/local/bin/ にあるとかは気持ち悪いっちゃ気持ち悪い。

HomebrewはLinuxのパッケージ管理ソフトみたいに /usr/local/bin/ とかに何でもインストールするので精神衛生上ベターだ。

Homebrewのインストール自体はとても簡単。パッケージ管理スクリプトをRubyで書くってのも、UNIXのことよく分かってない僕にはなかなかよいかもしれない。詳しいことは公式Wikiとかを見て下さい。

Vimのインストールではまった

Homebrew自体は簡単に入った。試しにVimをAppleがコンパイルしたVersion 7.2のものから新しめの7.3に上げて、ついでにRubyオプション入りでコンパイルしたかったので

$ brew install vim

してみた。しかしながら

Error: No available formula for vim

と出た。GUI版のMacVimはFormulaパッケージがあるらしいけど、フツーのVimはないらしい。「えー、自分でFormulaファイルを書かなきゃいけないの〜?」って感じだったんだけど、GitHubでテケトーに検索したらいろいろ出てきたので、 /usr/local/Library/Formula/vim.rb を作ってコピペした。

そんで今度は意気揚々と

$ brew install vim

してみたんだけど、なんとmakeに失敗する。Python.frameworkを参照してるときにエラーが出てるっぽい。

ld: warning: in /Library/Frameworks//Python.framework/Python, missing required architecture x86\_64 in file

Appleが配布したのではないPythonを使ってるとこういうエラーが出るとかなんとか外人が言ってる。

要するに64bit版のPython.frameworkを入れれば良さそうだった。何も考えずにHomebrewで brew install Python とかやって /usr/local/bin/python に新しいPythonを入れてみたりしたんだけど、これは意味なかったっぽい。大人しくPython公式サイトからPython 2.7のインストーラーパッケージをダウンロードしてきてGUIでインストールした。

その後、もう一度 brew install vim をしてみたところ、無事make完了。vim --version |grep ruby

+ruby

となった。

まだApacheとかRubyGemsとかはMacPorts版を使っているけど、割と早い段階でHomebrewに移行して、シャレオツプログラマーの仲間入りをしようと思います。

| @技術/プログラミング

80個近くある静的HTMLファイルをシステム化する必要が生じたので、HTMLをHpricotでスクレイピングしたあと、抽出したデータをSQLiteにぶっ込んだ。しかしSQLiteにぶっ込んだあとでデータの一部をいじりたくなった。そこでRailsのActiveRecordを単体で使ってみた。

なんでわざわざActiveRecordを使うのか

いやそりゃもちろんSQL書くのが怖いからですよ。というのは半分冗談なんですけど、CakePHPはSQLite 2にしか対応しておらず、SQLite 2は何かと制限が多い。replace関数が使えんとか。temp tableとか作るのかったるいし、フレームワークばっかり使っててSQLはあんまりよく分からないのでActiveRecordを使った次第です。

作業詳細

このシステム化するプロジェクト自体はCakePHPで動いており、DBはSQLite2。デフォの状態だとRailsは sqlite3-ruby しかインストールしないので、ActiveRecordからSQLite2なDBを操作することができず若干まいっちんぐだったんだけどなんとかでけた。ちなみにやったのはCRUDのReadとUpdateね。

やったこと

とりあえず以下のようなファイルを用意。各レコードの name フィールドの "hogehoge" という部分なのが邪魔なので削りたかった。

#!/usr/bin/env ruby

require "rubygems"
require "sqlite"
require "active_record"

ActiveRecord::Base.establish_connection(
  :adapter => "sqlite",
  :database => "path/to/db"
)

class Hoge < ActiveRecord::Base
end

hoges = Hoge.find(:all)
hoges.each do |hog|
  hog.name.gsub!(/hogehoge/, "")
  hoge.save
end

まず最初に、 no such file to load -- sqlite みたいなエラーが出た。要するに「お前SQLite 2のアダプター入れてねえだろ」というエラー。とりあえず sudo gem install sqlite-ruby したんだけど、それでも no such file to load — sqlite が出るのでMacを再起動したら「Rails 3ではSQLite 2はdeprecatedだからさっさとSQLite 3に移行しろや」みたいなメッセージは出るもののちゃんとDBの内容を読み込めた。CRUDのReadはでけた。

しかしUpdateの部分で失敗。Railsの感覚で hoge.save とかやったんだけどこれは意図したとおりに機能しなかった。しょうがないのでRailsのAPIリファレンスを見ながら、 update_attribute() というメソッドをぶちかましてやった。こんな感じ。

hoges.each do |hog|
  if hog.name =~ /hogehoge(.*)/
    hog.update_attribute("name", $1)
  end
end

これで狙ったことができました。

Rubyいいわー。ほんといいわー。