Home > Tags > ruby

ruby

Ruby会議2008を聴いていて

RubyKaigi 2008 novelty signed

自分が話したことについてはこちらに書いたので、二日間聴いていて胸に留まったことを。

処理系のはなし

MVMは本格始動しているのですね。1.9.xに入るとかアグレッシブすぎる。興味津々なのでウォッチしとかないと。JRubyはアプリ展開のくだりに説得力があった。

なによりMacRubyがすごかった。Objective-C 2.0をベースにしてるからGCもそっちにおまかせ、Cocoaのフレームワークもつかえるよ、とかいう。 そんなのを1人で片手間でやってるとかすごすぎる。Laurent++。 MacRubyは、JRubyと同じくらいのレイヤに位置するんだと思いました。JRubyがランタイムとしてJVMをつかってるのに対し、MacRubyはAppleのObjective-C実装に基づいてる。 これから先は、LLVMをつかって高速化するとかも考えてるらしい。うは。

ぼくは、「iPhoneでうごくの? (currently, NO)」 とか、「昨夜書いたというHotCocoaは何行くらいのコード? (300行くらい)」 とかいう質問を投げていました。

RubyCocoaに対する立場はどうなるんだろ、と懇親会でhisaさんに聞いたり、kimurawさんが質問したりしていましたが、RubyCocoaがなくなることはないそう。よかった (これまでの資産的な意味で)。

るりま

そうだ、やらなきゃ! 去年も同じようなことを感じてた。 下々にならねば。

LT

情熱的なトークっていいですね。伝えたいことがある、だからしゃべる。シンプルだ。 おもしろネタはもちろん楽しいし華を添えられるけれど、心をゆさぶる話を生で聴けるというのはすばらしい体験です。来てよかったと思った瞬間。

Re^2jectTalks

同じ会場でマイクなしで2つのセッションがあるとか、それなんて魚市場カオスwww


総じて、どのトークもレベルが高かった。面白いとかためになるとかすげえとか、ジャンルはちがうけどどれも質の良さが感じられる。しかも同じ系統ばかりじゃないから飽きない。プログラムの組み方がナイスでした。

ライブコーディングをしてるひとが何人かいて、会場からデバッグ的な声が飛んだりして、とっても双方向ライブ感を楽しめました。せっかくイベントでみんな集まってるんだかし、みんな参加できるなにかが素敵ですね。そういう意味で、PostItをみんなで書いて壁に貼るというのは敷居が低くてナイスだと思いました。

Ruby会議2008でLTしてきた

mootoh talk

Ruby会議2008 1日目で、Folk Programming with Ruby という話をしてきました。あとで追記すると思いますが、とりあえず当日記憶がはっきりしているうちに書き留めておくメソッド。

5分前まで動いていたQuartzComposer Gainer Plugin が動かなくなってしまい、たいへん残念でgdgdなプレゼンになってしまいました >< すみません ><

2008.06.23 03:28 追記:

  • あとで書く: なんかスライドにいい評価を頂けてるのでスライドのつくりかたを書く
  • あとで書く: Ruby会議2008全体について書く
  • あとで書く: しゃべることについて書く書いた

言いたかったこと

Webアプリでなにかつくる、なんてみんなやってる。そんなコモディティ化されてることをやっててもおもしろくないんじゃない? もっと変てこりんなユーザインターフェイス (物理的なもの含め) を実験して遊びたくない? ブラウザの外にも、おもしろいことはたくさんあるよ。

続きはWebで!

My ID

ここからは続きはWebでメソッド

今日、話した内容のターゲットは、これからプログラミングを始めるひと仕事のプログラミングばっかりしてて、個人的なプロジェクトがないひと、です。 Ruby会議に来ているようなひとたちは、そもそもこの範疇にあたらないので、この話をRuby会議でやるというのはいかがなものか、という意見はさておき。

これからプログラミングを始めるひとに: たしかに、Webアプリのプログラミングは楽しいものです。コミュニケーションに基づいてる、迅速なフィードバック、etc etc。 でも、サーバサイドでデータベースをいじったり、ブラウザ内での表現を極めたりするのって仕事でもできそうじゃない? あなたの目の前にあるコンピュータって、もっとなにかすごいことできそうじゃない?

仕事のプログラミングばっかりしてるひとに: 組織の中で生きていると、すごい技術をもってるひとというのは、どこにでもいるものだと思うものです。でも、そのひとたちはプログラミングを仕事としてしかやってない。趣味でなにかつくり、それをたとえば 1000speakers で発表するとか、見ない。 なんかそういうのってもったいなくない? あなたはこんなにすごいのに、埋もれてない?


ぼくが言いたかったのは、そういうことです。 つくった例を4つ出しましたが、そんなのは瑣末なことで、ここで書いたことだけが伝わればいいなとおもってました。

明日も楽しむぞ!

IRCのログはつづきにて。

Continue reading

Ruby会議 2008 LTに出ます

Ruby会議2008LTに申し込んだところ、ありがたいことに採択されたLT駆動開発者です。

Rubykaigi08 Speaker

最近つくってたいろいろをまとめて発表する形になる予定です。おてやわらかにどうぞ ><

refe2.vim

Rubyリファレンスマニュアル刷新計画ですすめられている新リファレンスシステムを、Vimから引けるようにしてみました。

ダウンロード

コード

つかいかた

Rubyのファイルを編集中に、単語の上で K を押すと該当するリファレンスマニュアルのページに飛びます。

必要なもの

  1. Rubyリファレンスマニュアル → るりまWiki から
  2. --enable-rubyinterp つきでコンパイルされたVim

準備

0: refe2.vimの一式をcheckout。

1: ダウンロードしたRubyリファレンスマニュアルにパッチをあてます。

  % cd ruby-refm-1.9.0-dynamic
  % patch -p0 < /tmp/refe2-vim/bitclust.patch

2: refe2.vim の中の s:bitclust_path に bitclustのパスを指定します。

3: refe2.vim を ~/.vim/ftplugin/ruby あたりにコピー。

ToDo

  • 色付け
  • 文脈に沿ったリファレンスの表示。 たとえば、
arr = [1,2,3]
arr.first

というコードがあったときに、 arr.first で検索してもちゃんと Array#first にひっかかるようにしたい。 Vimスクリプトの中のRubyインタプリタで周辺をevalしたらできたりしないだろうか。

その他

今回はじめてVim (+Ruby) スクリプトを書いてみました。 てんで荒削りな実装なので、コードの添削、書き換え、forkなど、どしどしやってもらえると幸せです。

Rubigraph 0.1.0

Rubigraph を 0.1.0 にバージョンアップしました。 gem install rubigraph でアップグレードできます。

変更点

Ubigraph alpha-0.2.2 に対応

Rubigraph 0.0.1 だと、Ubigraph alpha-0.2.2 でうまく動きません。(XML-RPCの返り値が変わったため) バージョンアップ推奨です。


Ubigraphの中の人と、ブログコメントやメールでのやりとりを行い、Ubigraph alpha-0.2.2 から、Rubigraph が含まれることになりました。やった!

証拠魚拓:

公式ドキュメントの中に、ちゃんとクレジットはいってます。


しょぼくてもいいから、とにかくなんかつくって素早く公開する、ということが大事ですね。最初からすごくなくてもいい。公開したあと、徐々に良いものにしていけばいい。

Rubigraph

一行でサマリ

Rubigraph という、Ubigraph のRubyラッパを書きました。

Ubigraphとは

Ubigraph というグラフ生成ツールを最近見つけました。 Graphvizが静的なグラフ生成をしてくれるのに対して、Ubigraphは動的にノードやエッジを追加/削除/属性変更できるのがミソです。これがたのしい。 どれくらい楽しいかについては、デモを見ていただければと思います。

クライアントサーバ型であり、サーバのコードは非公開だけれどXML-RPCのAPIが用意されているので簡単にクライアントがつくれます。なので、クライアント側の言語は問わないと謳ってるわけですね。サーバのバイナリはMacとLinuxが用意されてます。

Rubigraphとは

ですが、いちいちAPIリファレンス見ながらXML-RPCを書いてられない。 なので、簡単なクラスをつくってラップしたものをRubigraphとして公開します。

インストール

Rubyforgeにプロジェクトをつくっておきました。 gem install rubigraph としてインストールできます。

コード

どう書けるようになるのか

require 'rubigraph'
 
Rubigraph.init        # XML-RPCクライアントの初期化などする
 
v1  = Vertex.new
v2  = Vertex.new
e12 = Edge.new(v1, v2)
 
v1.color  = '#003366'
v2.shape  = 'sphere'
e12.label = 'edge between 1 and 2'

かんたんですね!

まとめ

ダイナミックにグラフで可視化するのはたのしいものです。ぼくは関数コールトレーサにつかっていて、とても便利に感じています。 Ubigraph++。

第三回Award on Rails LT で話してきた

第三回Award on Railsライトニングトーク にお呼ばれしたので、話してきました。ありがとうございます!

RailsといえばイントラBTSもどきくらいしかつくったことがないぼくが、Railsの会に行って何をしゃべるのか。実際なかなかのアウェイっぷりでした。しかもネタがニッチ。 2007-11-14 に書いたRubyでTwitter bot を書く というエントリをベースに、デモを加えて話しました。

伝えたかったこと

  • JabberでつくるとAPI制限なくていいよ
  • Webアプリのメール通知はうっとうしい → IMで通知 (Jabber) がもっと広まればな

よかったこと

  • daisakuさんと話せた。List共有のつくりこみを3週間で、ていうのはすごい
  • technohippy さんのcrayon physicsプレゼン。ライブラリはオープンになってるとか。使うしか
  • negipo さんと話せた。可視化とかエロギークとか。優秀なひとオーラがあった
  • クックパッドのCTOの人と話せた。Railsでお仕事してる人たち、と初めて話せたんじゃなかろうか。「毎日たのしいよ!」とにこやかだったのが印象的
  • ごはん激うます

その他

  • これからは祇園バレー
  • みんな若い

クックパッドのオフィスはマンションの一室。キッチンがすぐ横にあっていい匂いがする素敵な場所でした。仕事しにいくといいんじゃないかな。おいしい料理も食べれるし。

ふだんとぜんぜ違う人たちに交わると、ものを見る目をまたひとつ獲得できる気がします。みんなどんどん外に出ていくといいよ!

もっとRubyCocoaでQuicksilverプラグインを書く

RubyCocoaを使ってQuicksilverプラグインを書く の続編です。 前回書いたあと、hisaさんからアドバイスをもらい、RubyCocoaプラグインを書くことができるようになりました。

ポイントは以下の2つ。

  • NSPrincipalClass
  • RubyActionClass < OSX::QSActionProvider

コードは、CodeReposのものをupdateしておきました。 hisaさんコードがたくさん入っていますが、煮るなり焼くなり好きにせよとのことなので、前回と同じ修正BSDライセンスとします。

NSPrincipalClass

Quicksilver プラグインに限らず、Cocoaで何らかのBundleを書く際には、Info.plistの NSPrincipalClass にクラス名を指定しておくと、そのクラスの +load() メソッドが呼ばれてプラグインが組み込まれるようです。 なので、ここでRBBundleInit()を呼んでRubyCocoaを初期化すると。とてもスマート。 前回はこのことを知らずに、無理矢理なハックをしていたのでした。

RCLoader.m:

ここでは、NSPrincipalClassにRCLoaderというクラスを指定しています。

@implementation RCLoader
 
+ (void)load {
  static bool installed = 0;
 
  if (! installed) {
    if (! RBBundleInit("load_ruby.rb", [self class], self)) {
      installed = true;
    }
  }
}

load_ruby.rb:

そんで、RubyCocoaの初期化の中で、必要な.rbを読み込んでおく、と。

def load_ruby_programs(bundle, logger)
  path = bundle.resourcePath.fileSystemRepresentation
  rbfiles = Dir.entries(path).select {|x| /\.rb\z/ =~ x}
  rbfiles -= [ File.basename(__FILE__) ]
  rbfiles.each do |path|
    require( File.basename(path) )
  end
end
 
OSX.init_for_bundle do |bundle, param, logger|
  load_ruby_programs(bundle, logger)
end

RubyActionClass < OSX::QSActionProvider

前回説明したように、QuicksilverのActionを記述するには、QSActionProviderを継承したクラスでメソッドを用意します。 今回は、RubyのクラスでQSActionProviderを実装します。RubyCocoaのパワーがすごすぎる。

class RubyAction < OSX::QSActionProvider
  def act(arg)
    val = arg.stringValue
    OSX::QSObject.objectWithString('Hello world, ' + val)
  end
end

あとは、このRubyActionクラスを、Info.plistのactionClassに、actionSelectoract:に指定しておけば、ちゃんとactが呼ばれます。

疑問

  • OSX.require_framework とか使わないで、QSActionProviderとかのQS frameworkが使えてるのはなぜ?
  • hisaさんは、この方法だとCPU usageが高くなると懸念されているのですが、僕のところではいまひとつ高くなってるように見えません。why?

まとめ

RubyCocoaで、Quicsilverプラグインを書く方法をまとめました。 これで、あとはRubyのクラスとInfo.plistを書くだけでどんどんプラグインが書けますね。みんながんばれ!

あと、自分でもイマイチだなーと思うことでも、何かしら書いて晒すことが大事なんだなと。そんで改善していければOKなんだ。 hisaさん、ありがとうございました。

Write a Quicksilver plugin with RubyCocoa

I wrote a Quicksilver plugin with RubyCocoa, that adds “hello world” to the passed string.

  • Xcode project codes : in CodeRepos
  • License : revised BSD

It should work on Tiger/Leopard if RubyCocoa is installed.

How does it work

As I mentioned in QuartzComposer CustomPatch with RubyCocoa, we just call RBBundleInit() function in plugin initializaiton phase to write some plugin with RubyCocoa. But wait, where should be the initializaiton code in Quicksilver plugin ?

We write actual plugin behavior in the class that inherits QSActionProvider, so I tried to call RBBundleInit() in the init() method in that class… however, that resulted in crashing Quicksilver :(

Then I called RBBundleInit() at only first time in performActionOnObject() of the actual Action class, and made references between Objective-C and Ruby class instances.

After that, I implemented an actual action behavior in Ruby class, and delegates from Objective-C to Ruby method, thats’ all. This is ugly, confusing, … I know, but it does work well :)

Code Snippets

ActionProvider in Objective-C:

 (QSObject *)performActionOnObject:(QSObject *)dObject{
  // initialize RubyCocoa
  static bool loaded = false;
  if (!loaded) {
    if (RBBundleInit("qs_action.rb", [self class], self)) {
      NSLog(@"[RubyCocoaPluginAction.performActionOnObject] RBBundleInit failed"
);
      abort();
    }
    loaded = true;
  }
 
  // delegate actual action to Ruby class
  QSObject *ret = [QSObject objectWithString:[rb_ act:dObject]];
  return ret;
}

RubyCocoa side:

class Action
  def initialize(logger)
    @logger = logger
  end
 
  # write something great :)
  #  - arg : QSObject
  def act(arg)
    val = arg.stringValue
    @logger.info(val)
    'Hello world, ' + val
  end
end # Action
 
require 'osx/cocoa'
OSX.init_for_bundle do |bdl, owner, log|
  # bdl    - the bundle related with the 2nd argument of RBBundleInit
  # owner  - the 3rd argument of RBBundleInit as optional data
  # log    - logger for this block
 
  act = Action.new(log)
  owner.setInstance act
end

Future works

  • Better initializaiton. It should be in constractor of some class)
  • Inherits QSActionProvider by Ruby class (more pure Ruby)
  • Use ns_import ?

It should not be “With RubyCocoa”, but rather “By RubyCocoa”.

Conclusion

I made a start point to write a Quicksilver plugin by RubyCocoa. It is timing of initialization that is to be considered about writing some bundle in RubyCocoa. I made it in this article somehow. This article is for someone who wants to create Quicksilver plugin by Ruby, not learning unfamiliar Objective-C.

Reference

RubyCocoaを使ってQuicksilverプラグインを書く

RubyCocoaを使って、Quicksilverのプラグインを書いてみました。 受けとった文字列に、”hello world” をくっつけるだけのものです。

プロジェクト一式のコードは、CodeReposに。 ライセンスは修正BSDで。 RubyCocoaがインストールされていれば、TigerでもLeopardでも動くと思います。

仕組み

RubyCocoaでQuartzComposer CustomPatchのときに書いたように、 CocoaアプリじゃなくてプラグインをRubyCocoaで書くには、RBBundleInit() という関数をプラグインの初期化の際に呼んであげればよいわけです。 ところが、Quicksilverプラグインの初期化ってどこなんだろうという。

QSActionProviderを継承したクラスで実際のプラグインの動作 (Action) を記述するので、このクラスのinit()で RBBundleInit() を呼べばいいかなーと考えてやってみたところ、Quicksilverをクラッシュさせてしまいます。こまった。

しかたないので、Actionを記述する performActionOnObject() の中で、RBBundleInit()を最初の一度だけ呼ぶようにしました。その中で、Objective-CからRubyクラスのインスタンスを参照できるようにしておきます。

あとは、RubyのクラスでActionを実装し、Objective-CからRubyのメソッドを呼んで移譲します。これでできあがり。 かなり強引で美しくないのですが目的は果たせるかな、というダーティハックです。

コード片

Objective-CのActionProvider:

 (QSObject *)performActionOnObject:(QSObject *)dObject{
  // initialize RubyCocoa
  static bool loaded = false;
  if (!loaded) {
    if (RBBundleInit("qs_action.rb", [self class], self)) {
      NSLog(@"[RubyCocoaPluginAction.performActionOnObject] RBBundleInit failed"
);
      abort();
    }
    loaded = true;
  }
 
  // delegate actual action to Ruby class
  QSObject *ret = [QSObject objectWithString:[rb_ act:dObject]];
  return ret;
}

RubyCocoa側:

class Action
  def initialize(logger)
    @logger = logger
  end
 
  # write something great :)
  #  - arg : QSObject
  def act(arg)
    val = arg.stringValue
    @logger.info(val)
    'Hello world, ' + val
  end
end # Action
 
require 'osx/cocoa'
OSX.init_for_bundle do |bdl, owner, log|
  # bdl    - the bundle related with the 2nd argument of RBBundleInit
  # owner  - the 3rd argument of RBBundleInit as optional data
  # log    - logger for this block
 
  act = Action.new(log)
  owner.setInstance act
end

あと、やるとしたら

  • もうちょっときれいに初期化する (何らかのクラスのコンストラクタが望ましい)
  • QSActionProviderをRubyのクラスで継承する (よりRubyだけで書けるように)
  • ns_importとかつかってみる?

「RubyCocoaを使って」 よりも、「RubyCocoa」、スマートにプラグインを書けるようにしたいものです。 まぁ、まずは第一歩ということでひとつ。

まとめ

RubyCocoaを使って、Quicksilverプラグインをつくるためのとっかかりについて書きました。 RubyCocoaでバンドルを書くときに悩むのは初期化のタイミングだと思います。 今回はここを無理矢理解決しました。 Objective-Cを学んでる時間があったら、慣れ親しんでるRubyでちゃちゃっと コード書きたいよ! という方の参考になればと思います。

参考


2008.02.03 追記

RubyCocoaのhisaさんにコメントいただき (!)、もっとよい方法を教えてもらいました。 こちらについても、まとめて別エントリにします。

Home > Tags > ruby

Feeds

Return to page top