dreamedge.net

ecbでのrubyのパース

2009-08-31T13:39:00+0000

ecbでもrubyスクリプトをパースしてくれるのだけど,デフォルトだとファイルの読み込み時にしか解析してくれない.
特に新規にスクリプトを作成した時はなにも表示してくれないので,非常に作業効率が悪かった.

気合い入れてマニュアルを眺めてみると,imenuやetagsで解析するファイルに関しては解析内容を自動でアップデートする設定が必要とのことだった.rubyはimenuで解析をしているので,imenu-auto-scanを設定すればOK.

(setq imenu-auto-rescan t)

ちなみにこの設定があれば,”C-c . r”で再解析をしてくれるようになる.

手動でimenuの解析を行う場合は,”M-x imenu RET Rescan“を入力するとよいらしい.
http://d.hatena.ne.jp/wagavulin/20090104/1231093612

このエントリーをはてなブックマークに追加
Bookmark this on Delicious

HTTP接続のタイムアウト設定

2009-08-26T21:36:00+0000

rubyのhttp通信は,60秒でタイムアウトするように設定されている.通常はそれで問題ないのだけど,自前のスクリプトとかで時間のかかるモノを動かす場合に困る.

このタイムアウト時間はNet::HTTPのinitializeプロセスで60秒に設定されて,その後read_timeoutメソッドで変更可能になっている.
net/http.rb(Debian系なら/usr/lib/ruby/1.8/net/http.rb)を見ると下のような感じに書かれている.

    # Creates a new Net::HTTP object for the specified +address+.
    # This method does not open the TCP connection.
    def initialize(address, port = nil)
      @address = address
      @port    = (port || HTTP.default_port)
      @curr_http_version = HTTPVersion
      @seems_1_0_server = false
      @close_on_empty_response = false
      @socket  = nil
      @started = false
      @open_timeout = nil
      @read_timeout = 60
      @debug_output = nil
      @use_ssl = false
      @ssl_context = nil
    end
---中略---
    # Seconds to wait until reading one block (by one read(2) call).
    # If the HTTP object cannot open a connection in this many seconds,
    # it raises a TimeoutError exception.
    attr_reader :read_timeout

    # Setter for the read_timeout attribute.
    def read_timeout=(sec)
      @socket.read_timeout = sec if @socket
      @read_timeout = sec
    end

この実装自体は自然なんだけれど,open-uriとかのラッピングされた状態で扱う場合にタイムアウトの変更ができなくて困る.どうしたらいいかと情報を探していたら,Net::HTTPを上書きしちゃう方法が照会されていた.

class Net::HTTP
  def initialize_new(address, port = nil)
    initialize_old(address, port)
    @read_timeout = 120
  end
  alias :initialize_old :initialize
  alias :initialize :initialize_new
end

かなり力ずくだけど確かに有効.

このエントリーをはてなブックマークに追加
Bookmark this on Delicious

gzipファイルの読み書き

2009-01-01T10:57:00+0000

リファレンスマニュアルのGzipReaderの項GzipWriterの項参照.

Zlibのライブラリを読み込むことによって,普通のIOと同様にgzipファイルの読み書きをできるようになる.

require 'zlib'

Zlib::GzipReader.open('hoge.gz') do |fin|
  while line = fin.gets
    p line
  end
end

Zlib::GzipWriter.open('moge.gz') do |fout|
  0.upto(9) do |i|
    fout.print i.to_s + "\n"
  end
end
このエントリーをはてなブックマークに追加
Bookmark this on Delicious

undefined method to_datetimeエラー

2009-01-01T10:47:00+0000

debian etchでgemのspreadsheetライブラリを使うと,to_datetimeメソッドがないぞというエラーが出て怒られる.

/var/lib/gems/1.8/gems/ruby-ole-1.2.8.1/lib/ole/types/base.rb:84:in `send': undefined method `to_datetime' for Fri Dec 19 11:39:04 +0900 2008:Time (NoMethod\Error)

これはetchのruby1.8.5だと,require ‘date’してもTime.to_datetimeが定義されないことによる問題.
最新の1.8.7のソースパッケージを取ってきてdate.rb, date2.rb等をコピーすることで回避できる.

$ wget ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.7-p72.tar.gz
$ tar xzf ruby-1.8.7-p72.tar.gz
$ sudo mv /usr/lib/ruby/1.8/date.rb \
          /usr/lib/ruby/1.8/date.rb.bak
$ sudo mv /usr/lib/ruby/1.8/date2.rb \
          /usr/lib/ruby/1.8/date2.rb.bak
$ sudo mv /usr/lib/ruby/1.8/date \
          /usr/lib/ruby/1.8/date.bak
$ sudo cp -r ruby-1.8.7-p72/lib/date* /usr/lib/ruby/1.8/
このエントリーをはてなブックマークに追加
Bookmark this on Delicious

coerceの活用した演算子メソッドの実装

2009-01-01T08:44:00+0000

自作のクラスに実数との加減算や乗算を定義したい場合,

baka + 9
baka * 9

といったように後ろに数値が来る場合は,演算子メソッド(def +(i)とか)を定義すればいいので簡単.

9 + baka
9 * baka

のように前に数値が来る場合に,いちいちFixnumクラスやらBignumクラスやらFloatクラスやらの演算子をオーバーライドするのは面倒.(かつ”stack level too deep”エラーを出しやすくなるのも困る)

そんな場合はcoerceを使って,IntegerやFloatクラスに型変換できるようにすればよい.
ここに詳しい解説がある.

class MyNumber
  def coerce(other)
    if Integer === other then
      [other,@value]
    else
      [Float(other),Float(@value)]
    end
  end
end
p 9 * MyNumber.new(9)  #81
p 0.9 * MyNumber.new(9) #8.1

ちなみにFixnumクラスの乗算演算子をオーバーライドする場合は以下のようにする.
なんというか,見るからに筋が悪いプログラム.

class Fixnum
  alias_method :old_product, :*
  def *(other)
    if other.class == MyNumber
      other * self
    else
      old_product(other)
    end
  end
end
p 9 * MyNumber.new(9)  #81
このエントリーをはてなブックマークに追加
Bookmark this on Delicious