A Day in the Life

2006-11-07

伺かIO

  1. おもむろに require 'ukagaka_io'
  2. 適当に UkagakaIO を open する
  3. STDOUT/STDERR と差し替える
require 'ukagaka_io'

UIO = UkagakaIO.open('192.168.155.200', 9801)
STDOUT.reopen UIO
STDERR.reopen UIO

ほぼ全部の出力が伺かに…!

伺かIO

最初、test の結果の UI でなんか console 以外に表示させたくて伺かの接続用インタフェつくって、って思ったけどそもそも Socket 自体 IO の子クラスだし、つーことで UkagakaIO を作ってみた。write ラップして 1書き込みごとに伺かに出力だと、間隔が短すぎてわけわかんなくなったのでんげぇ適当にタイマーとバッファ処理。

require 'socket'
require 'nkf'
require 'thread'

class UkagakaIO < TCPSocket
  def to_utf8(str)
    NKF::nkf('-m0 -w', str)
  end

  HEADERS = {
    'Sender' => 'Ruby UkagakaIO',
    'Script' => '',
    'Charset' => 'UTF-8',
  }
  BREAK = "\r\n"

  def write(msg, force = false)
    @msg_buffer ||= ''
    @msg_buffer << to_utf8(msg).gsub(/\r?\n/, '\n')
    if force
      headers = HEADERS.clone.update('Script' => @msg_buffer)
      h = ['SEND SSTP/1.4']
      h << headers.map{|k,v| "#{k}: #{v}"}
      message = h.join(BREAK).concat(BREAK * 2)
      result = super(message)
      @msg_buffer = ''
      reconnect!
      result
    else
      timer
    end
  end

  def timer
    @mutex ||= Mutex.new

    @mutex.synchronize {
      return if @timer_stated
      @timer_stated = true
    }

    begin
      Thread.new {
        sleep @sec || 0.1
        write('', true)
      }
    ensure
      @timer_stated = false
    end
  end

  def reconnect!
    reopen(self.class.open(*@args))
  end

  def self.open(*args)
    @at_exit_set ||= at_exit { Thread.list.each {|t| t.join(0.1) rescue nil} }
    io = super
    io.instance_variable_set(:@args, args)
    io
  end
end

r14

Test::Base#spec_type を廃止して Test::Base::Spec オブジェクトが渡ってくるように。spec.foo でも spec[:foo] でもデータを取得できるようになった。あとリファクタリング。

instance のとある変数名から特異メソッド作る方法って、

instance.instance_eval "def #{method_name};end"

ってやる方法しか無いんだっけ?もっとベターな方法あったら誰かおしえて><

特定インスタンスの binding 取得し隊

あー。instance.instance_eval { binding } じゃなくて instance.__send__(:binding) でもいいのね

LDR で特定レートをすべて既読にする bookmarklet

未読たまりまくるとそのレートを読む気がなくなるのでそれをリセットするのに! sub.rate == 1 の値を 0~5 で適当に変更。LDR の開発者様におしえてもらった><

javascript:(function(){var o=Ordered.list;Ordered.list=subs.model.list.filter(function(sub){return sub.rate == 1}).pluck("subscribe_id");Control.mark_all_read();Ordered.list=o;})();

r13

Test::Base.spec_type で spec のタイプを hash or struct で選べるように。デフォルトだと struct。ていうか spec という名前で良いのだろうか、という最大の疑問。

require 'test/base'

class SpecTypeHashTest < Test::Base
  default_filters %w(.strip)
  spec_type :hash

  def run_tests(spec)
    assert_equal spec[:foo], 'example'
    assert_equal spec[:bar], 'example'
    assert_equal spec[:baz], 'example'
  end
end

__END__
===
--- foo: example
--- bar: example
--- baz: example

===
--- foo: example
--- bar: example
--- baz: example
Loaded suite spec_type_hash_test
Started
..
Finished in 0.001326 seconds.

2 tests, 6 assertions, 0 failures, 0 errors

r11

run_tests が無くても test が走るように。つかなんだ。class 作らないでも test 走るようにすべきかどうすべきか。。

require 'test/base'

class RunEvalTest < Test::Base
end

__END__
===
--- run_eval eval
assert true
Loaded suite run_eval_test
Started
.
Finished in 0.000875 seconds.

1 tests, 1 assertions, 0 failures, 0 errors

これはひどい

http://rubyforge.org/users/gorou/

すかっりわすれてたこのアカどうすんべ。。

autotest でしょでしょ?

ZenTest に含まれる autotest だが、rails + autotest の方法以外さっぱり解らなかったのでソース読んだ。

で、autotest は カレントディレクトリの .autotest もしくは ~/.autotest があったら読み込む事が解った。んでそこで様々なところに hook かけるプラグインなどをロードできる。例えば require 'autotest/html_report' とか。詳しくは example_dot_autotest.rb を。

また、rails じゃない場合、自動で lib/*.rb と test/test_*.rb をみてくれて実行してくれる。で、これは後者がくせ者で、普通 test/test_*.rb という名前にはせずに、test/*_test.rb とテスト名はつける(ハズ)。なので .autoload を起動時に読み込むことを利用し、quick hack して .autoload に↓の書いておくと、test/*_test.rb も autotest 対象に入ってウマー、と。これでライブラリのテストも autotest れるように><。あと autotest -h 見ると解るけど、各種バージョン管理システムを定期的にアップデート(svn up とか)してくれる機能もついており、共同で開発してるときに便利かもしれない。

class Autotest
  alias __tests_for_file tests_for_file
  def tests_for_file(filename)
    case filename
    when /^lib\/.*\.rb$/ then
      impl = File.basename(filename).gsub '_', '_?'
      @files.keys.select do |k|
        k =~ %r%^test/.*#{impl}$%
      end
    when /^test\/.*_test\.rb$/ then
      [filename]
    else
      @output.puts "Dunno! #{filename}" if $TESTING
      []
    end
  end
end
記事の一覧 >