As Sloth As Possible

可能な限りナマケモノでありたい

タグ:RubyCocoa

今週いろいろと忙しかったせいで「あとで書くと言ったまま書かないメソッド」が発動してしまって大分出遅れた感があるんだけど、RubyKaigi 2008に行ってきたの続き。

拡張ライブラリの書き方講座(artonさん)

RubyをCで拡張する方法の解説。朝からマニアックなセッションやるなぁ、と思ったら「朝のうちにマニアックなものをやっておく」という運営側の戦略だったらしい。朝一でつくばまでやって来てる人程マニアックな層なので、この戦略は当たりかもしれない。

Rubyの拡張ライブラリは結構簡単に書けるらしい。面白そうなので今度Cの勉強も兼ねて書いてみようかな。ruby拡張を書いてみるテスツ - 大学6年生のhogelogでサンプルがあがってるけど、これはちょっと面白そうだ。

あと個人的に興味深かったのは、artonさんがサンプルプログラムが上手く動かなくてその場でデバッグしはじめたとき。artonさんがあれこれ書き換えてる後ろで流されてるIRCのログに、みんなで「ここをこうすればいいんじゃないか」「arton、うしろうしろー!」などと協力してて面白かった。ペアプロならぬテラプロって誰が言ったんだっけ。

さらに仕事で使うRuby(ごとけんさん)

仕事で使うツールやその運用方法などの紹介。HikiとかRedMineとか。RedMine今回色んなセッションで紹介されてたし、Ruby本体のissue trackingにも使われてるらしい。今度使ってみようかな。

あとなんとオープンソース版Fastladderを紹介していただいた。日曜、月曜とFastladderのダウンロード数が増えてたのは間違いなくごとけんさんのお陰だろうと思う。

でもその後twitterで「Fastladderってでも最近全然開発してないよね。飽きちゃったのかな」とか言われてるのを見て焦った。いやいやいやいや、本当すいません、飽きてないですちゃんとやります。中の人二名(二人ともRubyKaigiに行ってました)が中々手が空かず放置気味になってしまってたのだけど、俺の今季の個人目標にはちゃんと「Fastladderの開発」が入ってますので!Googleグループの方にも反応できてなくて本当に申し訳ないんですが、バグレポートや要望など挙げてもらえたら頑張って対応します。

The future of Ruby in Mac OS X(Laurentさん)

RubyCocoaとMacRubyの紹介をApple社員のLaurent Sansonettiさんから。大変wktkする内容だったんだけど、それにしてもあの盛り上がりようはRubyistのマカー率の高さを示してるのかな。

前半はRubyCocoaの紹介で、後半はRubyCocoaが抱える問題点をMacRubyというアプローチで解決していこうとしている、という話。具体的なところは以前書いた記事をご覧下さい。要は「ブリッジではなくObjective-CでRuby処理系を実装することで、ラッパーを介する際のオーバーヘッドや複雑さを避ける」というのが要旨。当然ながら処理速度が飛躍的に早くなるよってところで歓声が上がってた。

RubyCocoa使いとしては「NSObjectが基底クラス」ってところが一番の目玉に感じたんだけど、Rubyist視点として興味深いのは、なるべく綺麗にObjective-Cのメッセージパッシングを実現するためにキーワード付き引き数を導入してること。MacRubyは今1.9ベースだけど、この機能は1.9にも無い。これが洗練されてくればMRIにも取り入れられるかもしれないってことで今後に期待。

あと、ちなみにMacRubyはiPhoneで動かすことは当分できないそうだ。メモリ管理にRubyのGCではなくObjC 2.0のGCを使っているので、GCサポートが無いiPhoneのランタイム向けにコンパイルできないらしい。これはちょっと残念。

それから質疑応答の光景が中々面白かった。Laurentさんはフランス語が母語?だったようで、込み入った質問になると「日本語で質問→フランス語で通訳→英語で回答→日本語で通訳」とかになってた。マルチリンガル!

Real-World Enterprise Ruby(大場さん、高井さん)

企業向けの開発でRubyを導入するにあたってのノウハウを伊藤忠テクノソリューションズの二人から。内容的には非常に真面目な話な上、二人ともスーツでステージに立ってたにもかかわらず、IRCでは「スーツがコスプレにしか見えなくなってきた」「漫才が始まった」などと盛り上がっていたのでなんだろうと思って行ってみたら、確かに面白いことやってた。なんでそんなことになったのかは高井さん大場さんのキャラクターから推してしるべし。

ちなみに内容はSI業界の人にはかなり参考になったんじゃないかと思う。yuguiさんの「わかっとらんやつは黙ってろ」とは対照的な、上司や顧客にRuby導入を承認させる方法とその効用についてがよくわかるセッションだった。

最後に

仕事柄大変Perl充な日々を送っているのだけど、久々に2日間丸々Rubyまみれな時間を過させてもらって本当に楽しかった。RubyKaigiスタッフの方々、スピーカーの方々、会場でご一緒させてもらった方々に心からの感謝を。

それから車を出してくれたsotarok、家に泊めてくれたdaftbeats、俺が頼まれてたyuguiさんのサイン入り初めてのRubyを代わりに確保してくれたfrom_kyushu、本当に助かりました。ありがとう!ハチロク世代++。

追記

あと俺何気にRubyConfのTシャツやらJRubyのTシャツやらを着てた。初めてのRuby片手にPHPTシャツを着たsotarokと、Sunと何の繋りもないのにJRubyTシャツを着てた俺が連れだって歩いてる光景は中々妙な感じだったんだけど誰にもつっこまれなかったのは、ツッコミ待ちなのがバレてたんだろうか。

正月休み中に形にするぞと息巻いてRubyCocoaのtwitterクライアントを作ってるのだけども、主にtwitterと関係ないところでハマってる*1。モデルの管理とIBとの連携が楽になると思って当初からCoreDataを使ってるんだけど、結構煩雑というかやぼったいというか。オブジェクトの追加は楽にできるんだけどオブジェクトの取得が面倒臭いんだよなぁ。

毎回NSFetchRequestを作ってNSEntityDescriptionを取得して…という処理を書くのがダルかったので、AR風のラッパを作ってみた。ベースのクラスを継承してモデル名と同名のクラスを作ると、そいつの操作が裏でCoreDataの操作になってるようなやつ。findとかdeleteとか、あとアクセサメソッドは定義しないでも勝手に拾ってよきにはからったりするとか、その辺は実装した。うーん、でも、このアプローチに自信が持てない。なんか車輪の再発明な気がしてならないし、多段ラッパになってて処理の効率悪そう。まぁ、勉強目的だから再発明上等だしtwitterクライアント程度でそんなにパフォーマンス気にすることない気もするけども…。RubyCocoaのdefine_wrapperとかARの拡張とかその辺りを補完するようなフレームワークを作れればいいんだけど。

こないだの補足

「CoreDataで管理してるデータは、正常終了時に自動保存されるのだけど、どこでどう処理されてるのかわからない」

テンプレートで自動生成されたAppDelegate.rbの中読んだらちゃんと書いてあった。applicationShouldTerminateメソッドの中で、managedObjectContextにsaveメッセージを送ってるのがそれですね。そこ以外ではデータの保存処理をしてないので、長時間つけっぱなしにしといて異常終了したりするとその間のログが全部ふっとぶのでどこかで定期的にsaveするようにしとかないとだ。まぁ、そもそも保存されなくても大して困らないけど。使えるものは使っておけと。

IBのチュートリアル

書こうと思ってたけど、むしろ俺自身が嵌ってるので書けそうにない。カスタムビューの作り方とか画像の扱いとかわかんないことだらけ。Objective-CやRubyCocoaはわからなくても、昔の資料から類推したりソース読んだりすればなんとでもなるんだけど、InterfaceBuilderの使い方は独力ではキツい。バージョン違うと資料が役に立たないし。今他のアプリのソース見て参考にしてるけど、誰か詳しい人がいたら助けて欲しいっす。

キーバリューコーディング

主にMVCのうちのCとVのバインディングに活躍してるキーバリューコーディングだけど、RubyCocoaと結構相性がいい。ハッシュかなんかをeachで回して全部ObjCのオブジェクトにobjc_send('setValue', value, 'forKey', key)とかしてやるだけでいいので、ラッパを作るのがすごい楽だった*2。素敵素敵。

いいから頑張れ俺

とかなんとか文章でいくら書いてもしょうがないので、作ったもの晒してみんなにツッコミ入れてもらった方が早い。さっさと投下しよう。

*1:二重の意味で

*2:具体的に言うとARでいうところのcreateあたりがまさにそう。あと、method_missingを捕捉してdelegate_object.objc_send('setValue', *args, 'forKey', name.to_s)とかやると後はよきにはからってくれるので、その辺も大して考えずに書けた。

RubyCocoaを極めるプロジェクト中でtwitterクライアントを作るという話が出てたので、正月休み中にみんなでいじって遊べる程度に動くものを作ってしまおうと目下がりがり書いてる最中なのですが、なかなか楽しいね、RubyCocoa。

e84fa15a.png

CoreDataが素敵

折角なのでCoreDataを活用してやろうと、HMDT本やリファレンスと格闘してました。CoreDataってなんぞ?ってレベルからのスタートだったので結構苦労したのだけども、CoreDataってのは要はCocoaアプリ中で簡易DBとO/Rマッパーを使えるようになるフレームワークなんだね。ActiveRecord+pstoreやsqlite、みたいなもんだと言っていいのかな。

で、これが非常に便利。Xcodeのモデリングツールでデータの定義をしておけば、勝手にDBとラッパオブジェクトを作ってくれるのでモデルクラスのとこのコーディングが格段に減る。モデル同士の関連もモデリングツールで作れるし、InterfaceBuilderとの連携でコントローラ部分も自分で作る必要がないので、簡単簡単。RubyCocoaから使う場合はCocoaから使う場合と若干構成が違うので最初躊躇ったけども。自分へのメモの意味でも、Xcode3でRubyCoca-CoreDataアプリを作る際のIBチュートリアル記事をあとで書いとこう。

ちなみに、twitterのデータの読み書きはこんな感じ

まずはデータの新規作成。

# NSManagedObjectのオブジェクトを新しく作ってDBに突っ込む
user = OSX::NSEntityDescription.objc_send("insertNewObjectForEntityForName",
            "User",
            "inManagedObjectContext",
            @managedObjectContext)
user.userId = '11111111'
user.screenName = 'rucotan'                                               
user.name = 'るこたん'

これでるこたんの情報がCoreData経由で使えるようになる。実はこの時点では「るこたんの情報が管理対象になった」だけで、自分でデータの保存処理をするか、CoreDataApplicationテンプレートからプロジェクト作ってるとアプリの正常終了時に自動で保存処理が呼びだされる*1か、そのタイミングで初めてファイルやDBに書き込まれるんだけど、「管理対象になった」時点でアプリ全体で使えるデータになるのでここではあんまり気にしない。

ちなみに、以前はNSManagedObjectのプロパティをいじるのに毎回valueForKeyやsetValue_forKeyを呼び出してたみたいなんだけど、RubyCocoaの改良でラッパオブジェクトを作るようにして、NSManagedObjectをまるでRubyのオブジェクトのように扱えるようになったらしい。軸がぶれてない、素敵*2。この辺がARっぽいとこ。

続いて既にあるデータの取得。

# NSFetchRequestを用意。RDBMSにSELECTクエリを発行するみたいな感じと言えばいいかな。
request = OSX::NSFetchRequest.alloc.init

# モデルを設定。SELECT文のFROMを指定するのに相当すると理解。
entity = OSX::NSEntityDescription.entityForName_inManagedObjectContext('User', @managedObjectContext)
request.setEntity(entity)

# 述語を設定。SELECT文のWHERE句相当、かな。
predicate = OSX::NSPredicate.predicateWithFormat('screenName == %@', 'rucotan')
request.setPredicate(predicate)

error = OSX::OCObject.new
users = @managedObjectContext.executeFetchRequest_error(request, error)

これで「screenNameがrucotanであるUserのリスト」を取得できる。NSFetchRequestとかNSPredicateってのが要はDBハンドラにプリペアードクエリを渡すのと手順は大して変わらないので、日頃DBを使うアプリに慣れてると違和感ないですね。注意点としては、executeFetchRequestの返り値はOSX::NSCFArrayなので、users.empty?とかusers.firstとかやると「そんなメッセージ、わたしが受け付けるとでも思ってるの!?この愚民は言葉もまともに話(ry」と怒られてしまう。Rubyで使うときは最初にto_aしておいた方が楽かも。

これだけだとRubyのARやPerlのClass::DBIに慣れきってる身としてはかったるくてしょうがないんだけど、Xcode上のモデリングツールで受信要求テンプレートというのを作ることができて、それを使うとNSFetchRequestの生成が大分楽になる。

variables = OSX::NSMutableDictionary.dictionary # 述語に渡すパラメータ
variables['screenName'] = 'rucotan'
request = @managedObjectModel.fetchRequestFromTemplateWithName_substitutionVariables('template_name', variables)
error = OSX::OCObject.new
users = @managedObjectContext.executeFetchRequest_error(request, error)

ちなみに、Xcode上で受信要求テンプレートを作る際には述語ビルダというのが使えて、複雑なリクエストでもiTunesやMailのスマートフォルダを作る感覚で述語を生成できてしまうので非常に簡単。だと思われる。いや、まだ使ったことないの。

キーバリューコーディング

に、ついても書こうと思ったんだけど、そろそろ長くなってきたのでまたの機会に。

仮名のRuchettaについて

Rubyの「る」とCocoaの「こ」がつくものがいいなあと考えて真っ先に浮んだのが「ルッコラ」だったんだけど、rucolaって開発環境があるのね、RubyCocoaの。ので、同じくルッコラを意味するイタリア語の「Ruchetta」にしてみた(安易)。ちゃんとr(uby)とc(ocoa)とt(witter)が入ったし、「ついった」と「るけった」で語感的にも悪くないかなと思ったんだけどどうだろう。みんなでいじれるようになったら名前も新しく考えてもらってもいいかな。

先を越された

これを書いてる最中に夏ライオン(OSXのtwitterクライアント)αリリースのお知らせが…。UIかっこいいなぁ。参考にさせてもらおう。

追記

夏ライオン見易くてなかなか良かった。自分でtwitterクライアント作ってる最中なのに当面夏ライオンユーザになりそうな予感。

*1:未確認。アプリ終了時に保存されるのは確かなんだけど、それがどこから何を呼び出してるのか実はわかってない。あとでちゃんと見る。

*2:そういえば絶望先生2期って今クールでしたっけ?

また開催されるようですね、Akasaka.rb。

Akasaka.rb、RubyCocoa、中川さん、はてな会議室…なんだこの魅惑のキーワードの列。まるでfaultierホイホイ。あうぁ。行きたい。是が非でも行きたい。

…その日が入社ガイダンスの日でなければ。その日何が行われるのかわからないので夜の予定を入れても大丈夫なのかどうか見当もつかない。聞いてみようかな。

↑このページのトップヘ