Netbeans 6.5 で Fast Debugger を使う

rails 書くときには、Netbeans をつかっていて、6.5が出たらしいので、入れた。

が、Ruby を選択した場合では Fast Debugger が動かなかったので*1、それを動かすまでのメモ。

現状

# gem list | grep ruby-debug-ide
ruby-debug-ide (0.4.1, 0.4.0, 0.1.10)

という状態では、

とか

という感じで、使えない*2

対処

そのため、

# sudo gem install ruby-debug-ide -v 0.3.1

とやってあげて、0.3.1 の ruby-debug-ide を入れてあげると、

という感じで、Netbeans 側から認識されて、無事使えるようになる。

*1:jruby だと、うごくっぽい。

*2:インストールをクリックしても、gem をインストールするにはルート権限が必要なため、失敗する

java で memcached に入れたものを ruby で取り出す (その逆も)

タイトル通り。
memcached つかうほどのものをいじっていないのだけれども面白そうなのでメモ。

以下、javahttp://www.whalin.com/memcached/
rubymemcached-client を前提とする*1

普通につかう。

普通にサンプル通り書くと、java なら

String[] servers = { "localhost:11211", };

SockIOPool pool = SockIOPool.getInstance();
pool.setServers(servers);
pool.initialize();

MemCachedClient mcc = new MemCachedClient();
mcc.set("one", 1);
mcc.set("two", 2);
mcc.get("one");

こんな感じ*2

ruby だと

require 'rubygems'
require 'memcache'

mem = MemCache.new("localhost:11211")

mem["three"] = 3
mem["four"] = 4
mem["three"]

こんな感じ。

普通に使う分にはこれで十分っぽい*3

java で入れたものを ruby から取り出す

でも、ここで java で入れたやつを ruby から取ろうとして、

p mem["one"]

とかやっても、

/opt/local/lib/ruby/gems/1.8/gems/memcache-client-1.5.0/lib/memcache.rb:214:in `load': marshal data too short (ArgumentError)
from /opt/local/lib/ruby/gems/1.8/gems/memcache-client-1.5.0/lib/memcache.rb:214:in `[]'
from mem.rb:8

とかそんな感じで、怒られる。
これは、ruby の memcache-client が値がマーシャルであることを期待しているため*4

該当個所はここらへん。

  ##
  # Retrieves +key+ from memcache.  If +raw+ is false, the value will be
  # unmarshalled.

  def get(key, raw = false)
    server, cache_key = request_setup key

    value = if @multithread then
              threadsafe_cache_get server, cache_key
            else
              cache_get server, cache_key
            end

    return nil if value.nil?

    value = Marshal.load value unless raw # ここでエラー!!!

    return value
  rescue TypeError, SocketError, SystemCallError, IOError => err
    handle_error server, err
  end

ちなみに話がずれるけど、get なんて使ってないのにここでエラーになっているのは、以下のようにエイリアスが定義されているから。

alias [] get

まあということで、

p mem.get["one",true]

とやってあげればOK、とおもいきや、java で入れた値の場合、

"\000\000\000\001"

という値が返ってきてしまう。
これに関しては、javamemcached ライブラリのサイトの http://www.whalin.com/memcached/HOWTO.txt にコメントがあって、

Multi-client Example:
=====================

If you need to support multiple clients (i.e. Java, PHP, Perl, etc.)
you need to make a few changes when you are setting things up:

// use a compatible hashing algorithm
pool.setHashingAlg( SockIOPool.NEW_COMPAT_HASH );

// store primitives as strings
// the java client serializes primitives
//
// note: this will not help you when it comes to
// storing non primitives
mcc.setPrimitiveAsString( true );

// don't url encode keys
// by default the java client url encodes keys
// to sanitize them so they will always work on the server
// however, other clients do not do this
mcc.setSanitizeKeys( false );

ということらしい。ということで、java 側を

String[] servers = { "localhost:11211", };

SockIOPool pool = SockIOPool.getInstance();
pool.setServers(servers);
pool.setHashingAlg( SockIOPool.NEW_COMPAT_HASH ); // ここと
pool.initialize();

MemCachedClient mcc = new MemCachedClient();
mcc.setPrimitiveAsString( true ); // ここと
mcc.setSanitizeKeys( false ); // ここ
mcc.set("one", 1);
mcc.set("two", 2);
mcc.get("one");

てな感じでかえてあげると、ruby からも値が取り出せるようになる。

ruby で入れたものをjava からとりだす

ruby の memcache-client の場合、値をマーシャルにして保存しようとするので、そうさせないようにする。

該当部分のコードは以下。

  def add(key, value, expiry = 0, raw = false)
    raise MemCacheError, "Update of readonly cache" if @readonly
    server, cache_key = request_setup key
    socket = server.socket

    value = Marshal.dump value unless raw # ここでマーシャルにしてる!!
    command = "add #{cache_key} 0 #{expiry} #{value.size}\r\n#{value}\r\n"

    begin
      @mutex.lock if @multithread
      socket.write command
      socket.gets
    rescue SocketError, SystemCallError, IOError => err
      server.close
      raise MemCacheError, err.message
    ensure
      @mutex.unlock if @multithread
    end
  end

つまり、ruby

 mem.add("one","1",0,true)

として値を入れてあげれば java から

mcc.get("one");

という形でとりだせる。

ここで、注意しなきゃいけないのは、add の定義のなかで、

 command = "add #{cache_key} 0 #{expiry} #{value.size}\r\n#{value}\r\n"

となっている点。ruby の場合、

 1.size #=> 4
 "1".size #=> 1

なので、値は Fixnum とかじゃまずい*5

 mem.set("one",1,0,true) # 第二引数が String じゃない!

とかやるとエラーになる*6

サイズがあうものを入れると入れられちゃう分、気がつきにくそうで怖い。
つまり、以下はOK。

 mem.set("hoge",1234,0,true) # 第二引数が String じゃないけど、通る!

…。

まとめ

ruby の memcache-client は デフォルトだと値をマーシャルにして入れているということ。
マーシャルじゃなくて保存したいときには、add と get の引数に true を指定してあげればよい。
ruby,php,perlでmemcacheの中身を使い回す | Parse Errorとかをみる限りだと、perl とか php はそのまま入れてるっぽい。

*1:gem install memcached-client で入るやつ

*2:import とかは省略

*3:多分

*4:ちなみに add するときもデフォルトでは、マーシャルにして入れている

*5:だからマーシャルにしてるのかなーとか思ったり

*6:というか反応が返ってこなくなる

will_paginate について

最近railsはじめた。
で、will_paginate*1

# sudo gem install will_paginate

で、入れたのだが、これだと古いものが入ってしまうらしい。

これは、Home · mislav/will_paginate Wiki · GitHub

The name of the will_paginate gem is now “mislav-will_paginate” because it’s being built by GitHub. If you have a gem named “will_paginate”, it is old and you are advised to remove it from your system.

という文章があったため判明した。

そこで、http://github.com/mislav/will_paginate/wikis/installationをみながら、

# sudo gem uninstall will_paginate
# sudo gem sources -a http://gems.github.com
# sudo gem install mislav-will_paginate

と、やってあげて、ねんがんのwill_paginateをてにいれた。

*1:railsでページ送りをするためのやつで、ググったところ一番メジャーっぽかったやつ

ニコニコの右上でFortuneのデータつくった

まず、http://www.nicochart.jp/static/comment.htmlから右上の発言集をとってくる。

require 'open-uri'

open("http://www.nicochart.jp/static/comment.html") do |f|
  f.each do |line|
    line.scan(/<dd>(.*?)<\/dd>/){|a|puts a.first.gsub(/<.*?>/,""); puts "%"}
  end
end

上記のスクリプト(ここではmigiue.rbとする)だと、標準出力にでてくるので適当なファイルにリダイレクト。

ruby migiue.rb > nico

で、nicoの中身は以下のような感じ。

ニコニコしている時のあなたが一番輝いていて、………好き。
%
泣くな!ニコニコしろ!!
%
たまに空見上げてみるのもいいもんだよ
%
みんな〜、ニコニコしてるかな?
%
右上の夏休みは一日もない。
%

これに対して、strfileする。

strfile nico nico.dat

これで完成。

で、このファイルを指定してfortuneを実行すれば、

bubbles% fortune nico
朝、目を覚まし、横を見るとなぜかニコニコが同じふとんに
bubbles%

という感じに。

あとは、ログイン時に表示されるように適当に.zshrcとか.bashrcをいじる。

Carbon Emacs の夏版が出たらしいので入れたのだが、前のように(mac-toggle-max-window)では、全画面にならない。

http://www.sooey.com/journal/2008/07/19/ では、起動時に全画面になる設定が書かれていたが、自分は、全画面にしたりもどしたりしたかったので以下のように、.emacs に書いた。

(defun my-mac-toggle-max-window ()
  (interactive)
  (if (frame-parameter nil 'fullscreen)
      (set-frame-parameter nil 'fullscreen nil)
    (set-frame-parameter nil 'fullscreen 'fullboth)))
(global-set-key "\C-cm" 'my-mac-toggle-max-window)

はじめは、関数定義して、global-set-keyしてあげればいいのかなー、と思ってたがうまくいかず、いろいろググったところ、http://www.kabipan.com/computer/emacs/

(global-set-key "\C-cz" (insert "a"))
よくあるキーバインディングの誤り。
リストの第三要素は任意の式でいいわけではない。

(global-set-key "\C-cz" (lambda () (insert "a")))
第三要素をラムダ式にしても、まだ使用時にエラーが出る。
ただの関数では駄目。

(global-set-key "\C-cz" (lambda () (interactive )(insert "a")))
コマンドだと宣言してある関数ならうまくいく。

http://www.kabipan.com/computer/emacs/

と書いてあり、関数定義のなかに(interactive) を加えたらうまくいった。超参考になりました。

で、とりあえずC-cmで全画面との切り替えができるようにした。

あんまり自信はないが、とりあず動くのでOKということにする。

やらなきゃいけないことがたくさんあるのに、だらだらしてしまうので、ldrmixiとニコニコを/etc/hostsにつっこんで見れないようにした。

どうせ自分で編集できちゃうから意味ないかもしれないけれど、少しは効果があることを期待。

本当にやばそうなので

ruby -ropen-uri -e 'open("http://rpc.reader.livedoor.com/notify?user=*****"){|f|`say #{f.read.gsub("|","")}`}'

とかやってldrの未読数を喋らせて遊んでるばあいじゃない*1

*1:****のとこは自分のldrのid。そしてMac限定